from __future__ import annotations

from datetime import UTC, datetime, timedelta
from decimal import Decimal

from sqlalchemy import create_engine
from sqlalchemy.orm import Session, sessionmaker
from sqlalchemy.pool import StaticPool

from app.core.config import get_settings
from app.db.base import Base
from app.models.agent_run import AgentRun
from app.models.financial_record import ExpenseClaim
from app.models.risk_observation import RiskObservation
from app.services.digital_employee_finance_report_task import (
    FINANCE_REPORT_TASK_TYPE,
    DigitalEmployeeFinanceReportTaskService,
)


def build_session() -> Session:
    engine = create_engine(
        "sqlite+pysqlite:///:memory:",
        connect_args={"check_same_thread": False},
        poolclass=StaticPool,
    )
    Base.metadata.create_all(bind=engine)
    session_factory = sessionmaker(bind=engine, autoflush=False, autocommit=False)
    return session_factory()


def test_finance_report_task_generates_pdf_and_agent_record(monkeypatch, tmp_path) -> None:
    monkeypatch.setenv("STORAGE_ROOT_DIR", str(tmp_path))
    get_settings.cache_clear()
    now = datetime.now(UTC)

    with build_session() as db:
        db.add(
            ExpenseClaim(
                claim_no="RE-REPORT-001",
                employee_name="林嘉宁",
                department_name="市场部",
                expense_type="travel",
                reason="客户拜访",
                location="上海",
                amount=Decimal("3600.00"),
                invoice_count=2,
                occurred_at=now - timedelta(days=2),
                submitted_at=now - timedelta(days=2),
                status="paid",
                approval_stage="已付款",
                risk_flags_json=[],
                hermes_risk_flag=False,
                created_at=now - timedelta(days=2),
                updated_at=now - timedelta(days=1),
            )
        )
        db.add(
            RiskObservation(
                observation_key="risk-report-001",
                subject_type="expense_claim",
                subject_key="RE-REPORT-001",
                subject_label="RE-REPORT-001",
                claim_no="RE-REPORT-001",
                risk_type="policy",
                risk_signal="amount_outlier",
                title="金额异常",
                risk_level="high",
                status="pending_review",
                created_at=now - timedelta(days=1),
                updated_at=now - timedelta(days=1),
            )
        )
        db.commit()

        result = DigitalEmployeeFinanceReportTaskService(db).generate_report(
            report_type="weekly",
            start_date=(now - timedelta(days=7)).date(),
            end_date=now.date(),
            send_email=True,
            dry_run_email=True,
        )

        pdf_path = tmp_path / result["pdf"]["storage_key"]
        html_path = pdf_path.with_name("report.html")
        runs = [
            run
            for run in db.query(AgentRun).filter(AgentRun.agent == "hermes").all()
            if (run.route_json or {}).get("task_type") == FINANCE_REPORT_TASK_TYPE
        ]

        assert pdf_path.exists()
        assert pdf_path.read_bytes().startswith(b"%PDF")
        assert html_path.exists()
        assert result["delivery"]["status"] in {"dry_run", "pending_configuration"}
        assert result["summary"]["reimbursement_count"] >= 1
        assert runs
        assert runs[0].status == "succeeded"
        assert runs[0].route_json["report_delivery"]["pdf"]["storage_key"].endswith("report.pdf")

    get_settings.cache_clear()
