from __future__ import annotations

import importlib.util
import sys
import unittest
from pathlib import Path

from bs4 import BeautifulSoup


ROOT = Path(__file__).resolve().parents[1]
FIXTURES = ROOT / "tests" / "fixtures"


def load_module(name: str, path: Path):
    spec = importlib.util.spec_from_file_location(name, path)
    if spec is None or spec.loader is None:
        raise RuntimeError(f"Could not load module from {path}")
    module = importlib.util.module_from_spec(spec)
    sys.modules[name] = module
    spec.loader.exec_module(module)
    return module


BUILD_DATA = load_module("rw_build_data_tests", ROOT / "scripts" / "build_data.py")
INCOMING = load_module("rw_incoming_stock_tests", ROOT / "Pulled_Info" / "Warehouse" / "Pull_Incoming_Stock.py")
VOUCHERS = load_module("rw_voucher_index_tests", ROOT / "scripts" / "rebuild_voucher_index.py")


class InventoryParserTests(unittest.TestCase):
    def test_load_inventory_parses_parenthetical_negative_qty(self):
        aggregates = BUILD_DATA.load_inventory(FIXTURES / "inventory_parenthetical_qty.csv")
        aggregate = aggregates["3519"]
        self.assertAlmostEqual(aggregate.total_qty, -1.0)
        self.assertAlmostEqual(aggregate.size_map[10.5]["D"], -1.0)

    def test_mixed_non_footwear_footwear_skips_duplicate_existing_size_and_unassigned_rows(self):
        existing = BUILD_DATA.load_inventory(FIXTURES / "inventory_existing.csv")
        mixed = BUILD_DATA.load_mixed_non_footwear_footwear_inventory(FIXTURES / "non_footwear_mixed.csv", existing)
        self.assertEqual(mixed, {})


class IncomingStockParserTests(unittest.TestCase):
    def test_parse_allocations_keeps_size_columns_aligned_without_row_label_column(self):
        soup = BeautifulSoup((FIXTURES / "incoming_allocation_table.html").read_text(encoding="utf-8"), "html.parser")
        card = soup.select_one(".c-card-product-info")
        self.assertIsNotNone(card)
        allocations = INCOMING.parse_allocations(card)
        self.assertEqual(
            [(entry["label"], entry["quantity"]) for entry in allocations],
            [("10", 10.0), ("12", 4.0), ("13", 3.0)],
        )

class VoucherParserTests(unittest.TestCase):
    def test_parse_style_prices_derives_discount_and_fixed_program_prices(self):
        text = (FIXTURES / "voucher_price_sample.md").read_text(encoding="utf-8")
        summary = VOUCHERS.VoucherSummary()
        rows = VOUCHERS.parse_style_prices("sample.md", text, summary)
        self.assertEqual(
            rows,
            [
                ("2230", 200.0, 25.0, 150.0),
                ("3522", 240.0, 0.0, 160.0),
            ],
        )
        self.assertEqual(summary.warnings, [])


if __name__ == "__main__":
    unittest.main()
