import math
import sys
from pathlib import Path
import unittest

PROJECT_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(PROJECT_ROOT))

from pricing import PriceInput, build_price_input, calculate_pricing, suggest_price_tiers


class PricingCalculatorTest(unittest.TestCase):
    def test_liangzhu_default_formula_matches_handoff_example(self):
        result = calculate_pricing(
            PriceInput(
                product_name="测试良渚自研产品",
                tax_included_cost=360,
                freight=8,
                platform_rate=0.061,
                promotion_rate=0.10,
                team_rate=0.28,
                vat_rate=0.13,
                discount_rate=0.85,
            )
        )

        self.assertAlmostEqual(result.break_even_price_raw, 735.62, places=2)
        self.assertEqual(result.break_even_price_ceil, 736)
        self.assertAlmostEqual(result.list_price_raw, 865.44, places=2)
        self.assertEqual(result.list_price_ceil, 866)
        self.assertAlmostEqual(result.discount_sale_price, 736.10, places=2)
        self.assertTrue(result.discount_break_even)
        self.assertAlmostEqual(result.net_vat, (result.break_even_price_raw - 360) * 13 / 113, places=6)

    def test_liangzhu_factory_purchase_formula_matches_handoff_example(self):
        item = build_price_input(
            {
                "pricing_type": "liangzhu_factory_purchase",
                "product_name": "测试厂家采购产品",
                "tax_included_cost": 360,
                "freight": 5.5,
                "ip_rate": 0.03,
                "platform_rate": 0.065,
                "promotion_rate": 0.10,
                "team_rate": 0.10,
                "vat_rate": 0.13,
                "target_profit_rate": 0.10,
                "discount_rate": 0.85,
            }
        )
        result = calculate_pricing(item)

        self.assertEqual(item.pricing_type, "liangzhu_factory_purchase")
        self.assertAlmostEqual(result.total_cost_rate, 0.295, places=6)
        self.assertAlmostEqual(result.break_even_price_raw, 661.46, places=2)
        self.assertEqual(result.break_even_price_ceil, 662)
        self.assertAlmostEqual(result.list_price_raw, 778.18, places=2)
        self.assertEqual(result.list_price_ceil, 779)
        self.assertAlmostEqual(
            result.profit_at_break_even_raw,
            result.break_even_price_raw * item.target_profit_rate,
            places=6,
        )
        self.assertAlmostEqual(result.net_vat, (result.break_even_price_raw - 360) * 13 / 113, places=6)

    def test_factory_purchase_defaults_are_applied_from_pricing_type(self):
        item = build_price_input(
            {
                "pricing_type": "liangzhu_factory_purchase",
                "product_name": "测试厂家采购产品",
                "tax_included_cost": 360,
            }
        )

        self.assertEqual(item.freight, 5.5)
        self.assertEqual(item.ip_rate, 0.03)
        self.assertEqual(item.platform_rate, 0.065)
        self.assertEqual(item.promotion_rate, 0.10)
        self.assertEqual(item.team_rate, 0.10)
        self.assertEqual(item.target_profit_rate, 0.10)

    def test_target_profit_sensitivity_table_includes_required_scenarios(self):
        item = build_price_input(
            {
                "pricing_type": "liangzhu_factory_purchase",
                "product_name": "测试厂家采购产品",
                "tax_included_cost": 360,
            }
        )
        result = calculate_pricing(item).to_dict()
        rows = result["target_profit_sensitivity"]
        self.assertEqual([row["target_profit_rate"] for row in rows], [0.0, 0.05, 0.10, 0.15, 0.20])
        ten_percent = rows[2]
        self.assertTrue(ten_percent["feasible"])
        self.assertAlmostEqual(ten_percent["break_even_price_raw"], 661.46, places=2)
        self.assertEqual(ten_percent["break_even_price_ceil"], 662)
        self.assertEqual(ten_percent["list_price_ceil"], 779)
        self.assertAlmostEqual(ten_percent["discount_sale_price"], 662.15, places=2)
        self.assertAlmostEqual(ten_percent["profit_amount"], 66.15, places=2)

    def test_adjusting_promotion_team_and_target_profit_changes_price(self):
        base = calculate_pricing(
            build_price_input(
                {
                    "pricing_type": "liangzhu_factory_purchase",
                    "product_name": "测试厂家采购产品",
                    "tax_included_cost": 360,
                    "promotion_rate": 0.10,
                    "team_rate": 0.10,
                    "target_profit_rate": 0.10,
                }
            )
        )
        higher_rates = calculate_pricing(
            build_price_input(
                {
                    "pricing_type": "liangzhu_factory_purchase",
                    "product_name": "测试厂家采购产品",
                    "tax_included_cost": 360,
                    "promotion_rate": 0.15,
                    "team_rate": 0.15,
                    "target_profit_rate": 0.15,
                }
            )
        )
        self.assertGreater(higher_rates.break_even_price_raw, base.break_even_price_raw)
        self.assertGreater(higher_rates.list_price_raw, base.list_price_raw)
        self.assertAlmostEqual(higher_rates.total_cost_rate, 0.395, places=6)

    def test_suggest_price_tiers_returns_good_looking_prices_at_or_above_base(self):
        self.assertEqual(suggest_price_tiers(866)[:4], [866, 869, 879, 899])

    def test_invalid_denominator_is_rejected(self):
        with self.assertRaises(ValueError):
            calculate_pricing(
                PriceInput(
                    product_name="费率过高产品",
                    tax_included_cost=100,
                    freight=8,
                    platform_rate=0.4,
                    promotion_rate=0.3,
                    team_rate=0.2,
                    vat_rate=0.13,
                    discount_rate=0.85,
                )
            )


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