from __future__ import annotations

from datetime import datetime
from typing import Any

from app.models.financial_record import ExpenseClaim
from app.schemas.financial_connector import FinancialPaymentEvidenceRead


class FinancialConnectorPaymentEvidenceService:
    """把付款状态映射为明确证据等级，不把内部状态冒充外部现金事实。"""

    @staticmethod
    def read(claim: ExpenseClaim) -> FinancialPaymentEvidenceRead:
        status = str(claim.status or "").strip().lower()
        if status != "paid":
            return FinancialPaymentEvidenceRead(
                claim_id=claim.id,
                claim_status=status,
                payment_state="not_paid",
                evidence_classification="none",
                evidence_label="尚无付款证据",
                trust_level="none",
                source_type="none",
                disclaimer="当前单据尚未形成付款完成事实。",
            )

        flag = _latest_payment_flag(claim.risk_flags_json)
        if flag and str(flag.get("source") or "").strip() == "external_payment":
            classification = str(flag.get("evidence_classification") or "").strip()
            verification = str(flag.get("verification_level") or "").strip() or None
            if classification == "external_cash" and verification == "production_verified":
                return FinancialPaymentEvidenceRead(
                    claim_id=claim.id,
                    claim_status=status,
                    payment_state="paid",
                    evidence_classification="external_cash",
                    evidence_label="生产外部现金回执",
                    trust_level="high",
                    source_type="external_connector",
                    provider=_text(flag.get("provider")),
                    verification_level=verification,
                    external_reference_tail=_tail(flag.get("external_reference_tail")),
                    recorded_at=_datetime(flag.get("created_at")),
                    disclaimer="该状态由生产连接器签名回执和精确对账共同证明。",
                )
            simulated_classification = (
                "staging_connector"
                if classification == "staging_connector"
                else "simulated_connector"
            )
            return FinancialPaymentEvidenceRead(
                claim_id=claim.id,
                claim_status=status,
                payment_state="paid",
                evidence_classification=simulated_classification,
                evidence_label=(
                    "预发布连接器回执"
                    if simulated_classification == "staging_connector"
                    else "模拟连接器回执"
                ),
                trust_level="low",
                source_type="external_connector",
                provider=_text(flag.get("provider")),
                verification_level=verification,
                external_reference_tail=_tail(flag.get("external_reference_tail")),
                recorded_at=_datetime(flag.get("created_at")),
                disclaimer="该回执不构成生产现金或入账证明，不应进入核心财务投影。",
            )

        return FinancialPaymentEvidenceRead(
            claim_id=claim.id,
            claim_status=status,
            payment_state="paid",
            evidence_classification="internal_manual_payment",
            evidence_label="人工付款确认（内部状态）",
            trust_level="low",
            source_type="manual_confirmation",
            recorded_at=_datetime(flag.get("created_at")) if flag else None,
            disclaimer="该状态仅证明平台内有人确认已付款，不等同于银行、支付平台或 ERP 外部回执。",
        )


def _latest_payment_flag(value: Any) -> dict[str, Any] | None:
    if not isinstance(value, list):
        return None
    for item in reversed(value):
        if not isinstance(item, dict):
            continue
        event_type = str(item.get("event_type") or "").strip()
        if event_type in {
            "expense_claim_external_payment_settled",
            "expense_claim_payment_completed",
        }:
            return item
    return None


def _text(value: Any) -> str | None:
    normalized = str(value or "").strip()
    return normalized or None


def _tail(value: Any) -> str | None:
    normalized = str(value or "").strip()
    return normalized[-8:] or None


def _datetime(value: Any) -> datetime | None:
    normalized = str(value or "").strip()
    if not normalized:
        return None
    try:
        return datetime.fromisoformat(normalized.replace("Z", "+00:00"))
    except ValueError:
        return None
