"""Unit and integration tests for Enterprise Advanced Modules (War Room, Site Operations, Telematics, 3-Way Matching, IPC)."""

from datetime import date
from decimal import Decimal

import pytest
from starlette.testclient import TestClient

from app.main import create_app
from app.models.financial_war_room_schemas import BusinessPillarEnum
from app.models.matching_schemas import MatchStatusEnum
from app.models.site_operations_schemas import (
    AttendanceEntry,
    GPSPhotoAttachment,
    MachineHourEntry,
    MaterialRequisitionCreateRequest,
    MaterialRequisitionItem,
    MRStatusEnum,
    SiteDiaryCreateRequest,
)
from app.modules.financial.application.financial_war_room_service import FinancialWarRoomService
from app.modules.operations.application.fuel_telematics_service import FuelTelematicsService
from app.modules.core.application.ipc_exporter_service import IPCExporterService
from app.modules.core.application.matching_service import ThreeWayMatchingService
from app.modules.operations.application.site_operations_service import SiteOperationsService


@pytest.fixture
def client() -> TestClient:
    app = create_app()
    return TestClient(app)


AUTH_HEADERS = {"Authorization": "Bearer dev-test-token"}


# --- 1. Financial War Room Tests ---
def test_financial_war_room_service_calculation():
    service = FinancialWarRoomService()
    data = service.get_war_room_summary()

    assert data.company_tax_id == "0202111150"
    assert len(data.pillars_breakdown) == 4

    # Check 4 pillars present
    pillar_ids = {p.pillar_id for p in data.pillars_breakdown}
    assert BusinessPillarEnum.PILLAR_1_EPC in pillar_ids
    assert BusinessPillarEnum.PILLAR_2_FLEET in pillar_ids
    assert BusinessPillarEnum.PILLAR_3_EQUIPMENT in pillar_ids
    assert BusinessPillarEnum.PILLAR_4_MATERIALS in pillar_ids

    # Precision check
    assert isinstance(data.total_revenue_ytd, Decimal)
    assert isinstance(data.total_gross_profit_ytd, Decimal)
    assert data.total_revenue_ytd > Decimal("0.0000")
    assert data.cashflow_runway.net_runway_days >= 90
    assert len(data.cashflow_runway.forecast_30d) == 30


def test_war_room_api_endpoints(client: TestClient):
    res = client.get("/v1/war-room/summary", headers=AUTH_HEADERS)
    assert res.status_code == 200
    payload = res.json()
    assert payload["company_tax_id"] == "0202111150"
    assert len(payload["pillars_breakdown"]) == 4

    res_pillars = client.get("/v1/war-room/pillars", headers=AUTH_HEADERS)
    assert res_pillars.status_code == 200
    assert len(res_pillars.json()) == 4

    res_cashflow = client.get("/v1/war-room/cashflow", headers=AUTH_HEADERS)
    assert res_cashflow.status_code == 200
    assert "forecast_30d" in res_cashflow.json()


# --- 2. Site Operations & Material Requisition Tests ---
def test_site_operations_service_lifecycle():
    service = SiteOperationsService()

    # Test Create Site Diary
    diary_req = SiteDiaryCreateRequest(
        project_code="DA-KM-BENKEM-2025-2026",
        log_date=date(2026, 8, 23),
        weather_condition="SUNNY",
        temperature_celsius=32.0,
        engineer_name="Kỹ sư Phạm Văn Tùng",
        site_manager_name="Chỉ huy trưởng Nguyễn Sĩ Sơn",
        work_summary="Đào đất hố móng cống Bến Kem",
        attendance=[
            AttendanceEntry(
                employee_code="NV-01",
                employee_name="Phạm Văn Tùng",
                role_title="Kỹ sư",
                hours_worked=Decimal("8.0000"),
            )
        ],
        machine_logs=[
            MachineHourEntry(
                equipment_code="EXC-KOMATSU-01",
                equipment_name="Komatsu PC200",
                operator_name="Lái máy Hùng",
                start_engine_hours=Decimal("4128.0000"),
                end_engine_hours=Decimal("4136.0000"),
                total_operating_hours=Decimal("8.0000"),
                work_description="Đào hố móng",
            )
        ],
        photos=[
            GPSPhotoAttachment(
                photo_id="IMG-TEST-01",
                file_url="/static/uploads/test.jpg",
                latitude=20.7352,
                longitude=106.6811,
                captured_at="2026-08-23T10:00:00",
                caption="Hố móng cống Bến Kem",
            )
        ],
    )
    diary = service.create_site_diary(diary_req)
    assert diary.diary_id.startswith("DIARY-DA-KM-")
    assert diary.total_workers == 1
    assert diary.total_machine_hours == Decimal("8.0000")

    # Test Material Requisition
    mr_req = MaterialRequisitionCreateRequest(
        project_code="DA-KM-BENKEM-2025-2026",
        wbs_task_code="WBS-KM-02-BETONG",
        urgency="HIGH",
        required_date=date(2026, 8, 25),
        requester_name="Kỹ sư Phạm Văn Tùng",
        delivery_location="Bãi đúc cống Bến Kem",
        reason="Đổ bê tông thân cống",
        items=[
            MaterialRequisitionItem(
                item_code="MAT-CAT-VANG",
                material_name="Cát vàng",
                unit="m³",
                requested_qty=Decimal("30.0000"),
                unit_price_estimate=Decimal("320000.0000"),
            )
        ],
    )
    mr = service.create_material_requisition(mr_req)
    assert mr.status == MRStatusEnum.SUBMITTED
    assert mr.total_estimated_amount == Decimal("9600000.0000")

    # Approve MR
    approved_mr = service.update_mr_status(
        mr.mr_id, MRStatusEnum.APPROVED, approver_name="Nguyễn Sĩ Sơn"
    )
    assert approved_mr.status == MRStatusEnum.APPROVED
    assert approved_mr.items[0].approved_qty == Decimal("30.0000")


def test_site_operations_api_endpoints(client: TestClient):
    # Test list diaries
    res = client.get("/v1/site/diaries", headers=AUTH_HEADERS)
    assert res.status_code == 200
    assert len(res.json()) >= 1

    # Test list requisitions
    res_mr = client.get("/v1/site/requisitions", headers=AUTH_HEADERS)
    assert res_mr.status_code == 200
    assert len(res_mr.json()) >= 1


# --- 3. Fuel Telematics & Equipment Maintenance Tests ---
def test_fuel_telematics_service():
    service = FuelTelematicsService()
    summary = service.get_dashboard_summary()

    assert summary.total_active_equipment >= 4
    assert summary.average_consumption_liters_per_hour > Decimal("0.0000")

    # Check overconsumption detection
    kobelco = next(
        a for a in summary.assessments if a.equipment_code == "EXC-KOBELCO-02"
    )
    assert kobelco.status == "WARNING_OVERCONSUMPTION"
    assert kobelco.variance_percentage > Decimal("15.0000")


def test_telematics_api_endpoint(client: TestClient):
    res = client.get("/v1/telematics/summary", headers=AUTH_HEADERS)
    assert res.status_code == 200
    payload = res.json()
    assert "assessments" in payload
    assert "maintenance_schedules" in payload


# --- 4. 3-Way Matching Engine Tests ---
def test_matching_service():
    service = ThreeWayMatchingService()
    summary = service.get_dashboard_summary()

    assert summary.total_invoices_checked == 2
    assert summary.perfect_matches_count == 1
    assert summary.mismatches_count == 1
    assert summary.matches[0].match_status == MatchStatusEnum.PERFECT_MATCH


def test_matching_api_endpoint(client: TestClient):
    res = client.get("/v1/matching/summary", headers=AUTH_HEADERS)
    assert res.status_code == 200
    payload = res.json()
    assert payload["perfect_matches_count"] >= 1


# --- 5. IPC Interim Payment Certificate (Mẫu 03a) Tests ---
def test_ipc_exporter_service():
    service = IPCExporterService()
    ipc = service.generate_ipc_03a(
        project_code="DA-KM-BENKEM-2025-2026", period_number=3
    )

    assert ipc.project_code == "DA-KM-BENKEM-2025-2026"
    assert ipc.period_number == 3
    assert len(ipc.items) == 4
    assert ipc.advance_recovery_rate_pct == Decimal("10.0000")
    assert ipc.retention_rate_pct == Decimal("5.0000")
    assert ipc.vat_rate_pct == Decimal("8.0000")
    assert ipc.total_net_payable_period > Decimal("0.0000")


def test_ipc_api_endpoint(client: TestClient):
    res = client.get(
        "/v1/ipc/03a?project_code=DA-KM-BENKEM-2025-2026&period_number=3",
        headers=AUTH_HEADERS,
    )
    assert res.status_code == 200
    payload = res.json()
    assert payload["contractor_name"] == "CÔNG TY TNHH XÂY DỰNG ĐỊNH SƠN"
    assert len(payload["items"]) == 4


# --- 6. Static Web Dashboards Availability ---
def test_static_dashboard_endpoints(client: TestClient):
    res_warroom = client.get("/dashboard/war-room")
    assert res_warroom.status_code == 200
    assert "Executive Financial War Room" in res_warroom.text

    res_pwa = client.get("/dashboard/site-diary-mobile")
    assert res_pwa.status_code == 200
    assert "Site Operations PWA" in res_pwa.text
