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.db.base import Base
from app.models.employee import Employee
from app.models.financial_record import ExpenseClaim
from app.models.role import Role
from app.services.digital_employee_dashboard import DigitalEmployeeDashboardService
from app.services.digital_employee_reminder_task import DigitalEmployeeReminderTaskService


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_digital_employee_reminder_task_generates_actionable_report() -> None:
    now = datetime(2026, 6, 2, 2, 0, tzinfo=UTC)

    with build_session() as db:
        _seed_reminder_data(db, now)

        result = DigitalEmployeeReminderTaskService(
            db,
            tenant_id="default",
        ).refresh_reminders(now=now)

        summary = result["summary"]
        report = result["report"]
        assert result["task_type"] == "digital_employee_reminder_scan"
        assert summary["recipient_count"] >= 3
        assert summary["reminder_count"] >= 4
        assert summary["approval_pending_count"] == 1
        assert summary["budget_reminder_count"] == 1
        assert summary["travel_application_reminder_count"] == 1
        assert summary["reimbursement_overdue_count"] == 1

        reminder_types = {
            reminder["type"]
            for recipient in report["recipients"]
            for reminder in recipient["reminders"]
        }
        assert {
            "approval_pending",
            "budget_compilation",
            "travel_application_expiry",
            "reimbursement_overdue",
        }.issubset(reminder_types)

        dashboard = DigitalEmployeeDashboardService(db).build_dashboard(days=7, now=now)
        assert dashboard.totals["reminders"] >= 4
        assert dashboard.totals["businessOutputs"] >= 4
        assert dashboard.task_distribution[0]["taskType"] == "digital_employee_reminder_scan"


def _seed_reminder_data(db: Session, now: datetime) -> None:
    budget_role = Role(
        id="role-budget",
        role_code="budget_monitor",
        name="预算管理员",
        description="预算编制提醒接收人",
    )
    manager = Employee(
        id="emp-manager",
        employee_no="M001",
        name="审批领导",
        email="manager@example.com",
        position="部门负责人",
        grade="M2",
    )
    employee = Employee(
        id="emp-user",
        employee_no="E001",
        name="出差员工",
        email="employee@example.com",
        position="客户经理",
        grade="P5",
        manager=manager,
        finance_owner_name="财务BP",
    )
    budget_admin = Employee(
        id="emp-budget",
        employee_no="B001",
        name="预算管理员甲",
        email="budget@example.com",
        position="预算管理员",
        grade="P6",
        roles=[budget_role],
    )
    db.add_all([budget_role, manager, employee, budget_admin])
    db.add_all(
        [
            _claim(
                "claim-approval",
                "EXP-APPROVAL-001",
                employee,
                "travel",
                "12000.00",
                now - timedelta(days=3),
                "submitted",
                "直属领导审批",
            ),
            _claim(
                "claim-travel-app",
                "APP-TRAVEL-001",
                employee,
                "travel_application",
                "8000.00",
                now - timedelta(days=1),
                "approved",
                "已审批",
                risk_flags=[
                    {
                        "source": "application_detail",
                        "application_detail": {
                            "application_type": "差旅申请",
                            "time": "2026-06-01",
                        },
                    }
                ],
            ),
            _claim(
                "claim-supplement",
                "EXP-SUPPLEMENT-001",
                employee,
                "meal",
                "600.00",
                now - timedelta(days=2),
                "returned",
                "材料待补",
            ),
        ]
    )
    db.commit()


def _claim(
    claim_id: str,
    claim_no: str,
    employee: Employee,
    expense_type: str,
    amount: str,
    happened_at: datetime,
    status: str,
    approval_stage: str,
    *,
    risk_flags: list[dict] | None = None,
) -> ExpenseClaim:
    return ExpenseClaim(
        id=claim_id,
        claim_no=claim_no,
        employee_id=employee.id,
        employee_name=employee.name,
        department_name="市场部",
        expense_type=expense_type,
        reason="客户拜访",
        location="上海",
        amount=Decimal(amount),
        invoice_count=1,
        occurred_at=happened_at,
        submitted_at=happened_at,
        status=status,
        approval_stage=approval_stage,
        risk_flags_json=risk_flags or [],
        created_at=happened_at,
        updated_at=happened_at,
    )
