"""数据管理模块测试 — Excel导入/导出/数据源CRUD"""
import io
import pandas as pd
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, create_test_kpi


class TestDataSources:
    """数据源CRUD测试"""

    DATA_ENDPOINT = "/api/cma/data"

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

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

    def test_create_source(self, client: TestClient, db: Session):
        """创建数据源"""
        create_test_user(db)
        token = get_token_for_user(client)

        resp = client.post(
            f"{self.DATA_ENDPOINT}/sources",
            headers=auth_header(token),
            json={"name": "ERP数据源", "source_type": "erp", "api_endpoint": "http://erp.example.com"},
        )
        assert resp.status_code == 200
        data = resp.json()["data"]
        assert data["name"] == "ERP数据源"
        assert data["source_type"] == "erp"
        assert data["status"] == "active"

    def test_update_source(self, client: TestClient, db: Session):
        """更新数据源"""
        create_test_user(db)
        token = get_token_for_user(client)

        # 先创建
        create_resp = client.post(
            f"{self.DATA_ENDPOINT}/sources",
            headers=auth_header(token),
            json={"name": "旧名称", "source_type": "manual"},
        )
        source_id = create_resp.json()["data"]["id"]

        # 更新
        resp = client.put(
            f"{self.DATA_ENDPOINT}/sources/{source_id}",
            headers=auth_header(token),
            json={"name": "新名称"},
        )
        assert resp.status_code == 200
        assert resp.json()["data"]["name"] == "新名称"

    def test_delete_source(self, client: TestClient, db: Session):
        """删除数据源"""
        create_test_user(db)
        token = get_token_for_user(client)

        create_resp = client.post(
            f"{self.DATA_ENDPOINT}/sources",
            headers=auth_header(token),
            json={"name": "待删除", "source_type": "manual"},
        )
        source_id = create_resp.json()["data"]["id"]

        resp = client.delete(
            f"{self.DATA_ENDPOINT}/sources/{source_id}",
            headers=auth_header(token),
        )
        assert resp.status_code == 200
        assert resp.json()["message"] == "删除成功"

    def test_delete_source_not_found(self, client: TestClient, db: Session):
        """删除不存在的源"""
        create_test_user(db)
        token = get_token_for_user(client)

        resp = client.delete(
            f"{self.DATA_ENDPOINT}/sources/99999",
            headers=auth_header(token),
        )
        assert resp.status_code == 404


class TestDataImport:
    """Excel导入测试"""

    def test_import_excel_success(self, client: TestClient, db: Session):
        """导入Excel数据"""
        create_test_user(db)
        token = get_token_for_user(client)

        # 先创建KPI
        create_test_kpi(db, kpi_code="F_REVENUE_IMP", kpi_name="导入测试KPI")

        # 构造Excel文件
        df = pd.DataFrame({
            "kpi_code": ["F_REVENUE_IMP", "F_REVENUE_IMP"],
            "period": ["2026-06", "2026-07"],
            "actual_value": [100.0, 200.0],
        })
        buffer = io.BytesIO()
        df.to_excel(buffer, index=False)
        buffer.seek(0)

        resp = client.post(
            f"/api/cma/data/import-excel",
            headers=auth_header(token),
            files={"file": ("test.xlsx", buffer, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")},
        )
        assert resp.status_code == 200
        data = resp.json()
        assert "导入成功" in data["message"]
        assert "2 条" in data["message"]
        assert "batch" in data

    def test_import_excel_missing_columns(self, client: TestClient, db: Session):
        """导入缺少必要列的Excel"""
        create_test_user(db)
        token = get_token_for_user(client)

        df = pd.DataFrame({"name": ["test"], "value": [100]})
        buffer = io.BytesIO()
        df.to_excel(buffer, index=False)
        buffer.seek(0)

        resp = client.post(
            f"/api/cma/data/import-excel",
            headers=auth_header(token),
            files={"file": ("bad.xlsx", buffer, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")},
        )
        assert resp.status_code == 400

    def test_import_excel_no_match_kpi(self, client: TestClient, db: Session):
        """导入时KPI不存在 → 跳过（不报错）"""
        create_test_user(db)
        token = get_token_for_user(client)

        df = pd.DataFrame({
            "kpi_code": ["NON_EXISTENT_KPI"],
            "period": ["2026-06"],
            "actual_value": [999.0],
        })
        buffer = io.BytesIO()
        df.to_excel(buffer, index=False)
        buffer.seek(0)

        resp = client.post(
            f"/api/cma/data/import-excel",
            headers=auth_header(token),
            files={"file": ("test.xlsx", buffer, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")},
        )
        assert resp.status_code == 200
        assert "导入成功" in resp.json()["message"]
        assert "0 条" in resp.json()["message"]

    def test_import_template_download(self, client: TestClient, db: Session):
        """下载导入模板"""
        create_test_user(db)
        token = get_token_for_user(client)

        resp = client.get(
            f"/api/cma/data/import-template",
            headers=auth_header(token),
        )
        # 如果模板文件存在则返回200，否则404（两种情况都算合理）
        assert resp.status_code in (200, 404)
