"""成本分析模块测试 — 标准成本/实际成本CRUD + ABC + 看板"""
import pytest
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from tests.conftest import create_test_user, get_token_for_user, auth_header
from app.models import StandardCost, ActualCost, AbcActivity


class TestStandardCost:
    """标准成本卡片CRUD测试"""

    BASE = "/api/cma/cost"

    def test_list_standard_costs_empty(self, client: TestClient, db: Session):
        """空列表"""
        create_test_user(db)
        token = get_token_for_user(client)

        resp = client.get(f"{self.BASE}/standard-costs", headers=auth_header(token))
        assert resp.status_code == 200
        assert resp.json()["data"] == []

    def test_create_standard_cost(self, client: TestClient, db: Session):
        """创建标准成本卡片"""
        create_test_user(db)
        token = get_token_for_user(client)

        resp = client.post(
            f"{self.BASE}/standard-costs",
            headers=auth_header(token),
            json={
                "product_code": "PROD_A",
                "product_name": "产品A",
                "cost_type": "material",
                "item_name": "原材料X",
                "standard_quantity": 10.0,
                "standard_price": 5.0,
                "unit": "kg",
            },
        )
        assert resp.status_code == 200
        assert resp.json()["message"] == "标准成本已创建"

        # 验证列表中有数据
        list_resp = client.get(f"{self.BASE}/standard-costs", headers=auth_header(token))
        assert len(list_resp.json()["data"]) == 1

    def test_update_standard_cost(self, client: TestClient, db: Session):
        """修改标准成本卡片"""
        create_test_user(db)
        token = get_token_for_user(client)

        sc = StandardCost(
            product_code="PROD_B", product_name="产品B", cost_type="labor",
            item_name="人工", standard_quantity=100, unit="小时",
            standard_price=50.0, standard_cost=5000.0,
        )
        db.add(sc)
        db.commit()

        resp = client.put(
            f"{self.BASE}/standard-costs/{sc.id}",
            headers=auth_header(token),
            json={"standard_price": 55.0, "remark": "调薪后更新"},
        )
        assert resp.status_code == 200
        assert resp.json()["message"] == "已更新"

    def test_delete_standard_cost(self, client: TestClient, db: Session):
        """删除（归档）标准成本卡片"""
        create_test_user(db)
        token = get_token_for_user(client)

        sc = StandardCost(
            product_code="PROD_C", product_name="产品C", cost_type="overhead",
            item_name="水电费", standard_quantity=1, unit="项",
            standard_price=1000.0, standard_cost=1000.0,
        )
        db.add(sc)
        db.commit()

        resp = client.delete(
            f"{self.BASE}/standard-costs/{sc.id}",
            headers=auth_header(token),
        )
        assert resp.status_code == 200
        assert resp.json()["message"] == "已归档"


class TestActualCost:
    """实际成本CRUD测试"""

    BASE = "/api/cma/cost"

    def test_create_actual_cost(self, client: TestClient, db: Session):
        """录入实际成本"""
        create_test_user(db)
        token = get_token_for_user(client)

        resp = client.post(
            f"{self.BASE}/actual-costs",
            headers=auth_header(token),
            json={
                "period": "2026-06",
                "product_code": "PROD_A",
                "product_name": "产品A",
                "cost_type": "material",
                "item_name": "原材料X",
                "actual_quantity": 12.0,
                "actual_price": 4.8,
            },
        )
        assert resp.status_code == 200
        assert resp.json()["message"] == "实际成本已录入"

    def test_list_actual_costs(self, client: TestClient, db: Session):
        """查询实际成本"""
        create_test_user(db)
        token = get_token_for_user(client)

        ac = ActualCost(
            period="2026-06", product_code="PROD_A", product_name="产品A",
            cost_type="material", item_name="原材料X",
            actual_quantity=10, actual_price=5.0, actual_cost=50.0,
        )
        db.add(ac)
        db.commit()

        resp = client.get(f"{self.BASE}/actual-costs?period=2026-06", headers=auth_header(token))
        assert resp.status_code == 200
        assert len(resp.json()["data"]) == 1


class TestAbcCost:
    """ABC作业成本测试"""

    BASE = "/api/cma/cost"

    def test_create_abc_activity(self, client: TestClient, db: Session):
        """创建ABC作业中心"""
        create_test_user(db)
        token = get_token_for_user(client)

        resp = client.post(
            f"{self.BASE}/abc/activities",
            headers=auth_header(token),
            json={
                "activity_code": "ACT_001",
                "activity_name": "机器调试",
                "cost_driver": "调试次数",
                "driver_unit": "次",
                "total_cost": 50000.0,
                "driver_volume": 100,
            },
        )
        assert resp.status_code == 200
        assert resp.json()["message"] == "作业中心已创建"

    def test_list_abc_activities(self, client: TestClient, db: Session):
        """查询ABC作业中心列表"""
        create_test_user(db)
        token = get_token_for_user(client)

        act = AbcActivity(
            activity_code="ACT_002", activity_name="品质检验",
            cost_driver="检验批次", driver_unit="批",
            total_cost=30000.0, driver_volume=200, driver_rate=150.0,
        )
        db.add(act)
        db.commit()

        resp = client.get(f"{self.BASE}/abc/activities", headers=auth_header(token))
        assert resp.status_code == 200
        assert len(resp.json()["data"]) >= 1
        assert resp.json()["data"][0]["activity_code"] == "ACT_002"

    def test_abc_allocate(self, client: TestClient, db: Session):
        """执行ABC成本分配"""
        create_test_user(db)
        token = get_token_for_user(client)

        act = AbcActivity(
            activity_code="ACT_003", activity_name="订单处理",
            cost_driver="订单数", driver_unit="单",
            total_cost=20000.0, driver_volume=400, driver_rate=50.0,
        )
        db.add(act)
        db.commit()

        resp = client.post(
            f"{self.BASE}/abc/allocate",
            headers=auth_header(token),
            json={
                "activity_id": act.id,
                "period": "2026-06",
                "product_code": "PROD_A",
                "product_name": "产品A",
                "driver_consumed": 30,
            },
        )
        assert resp.status_code == 200
        data = resp.json()
        # 30 * 50 = 1500
        assert data["allocated_cost"] == 1500.0
