"""Request/response schemas for Orxaq REST API.

Pure-stdlib dataclasses with from_dict / to_dict for JSON serialisation.
No external deps (ADR-007).
"""

from __future__ import annotations

from dataclasses import dataclass, field


@dataclass
class ECLComputeRequest:
    portfolio_size: int = 200
    scenario: str = "baseline"
    horizon: int | str = "dynamic"
    seed: int = 42

    def to_dict(self) -> dict:
        return {
            "portfolio_size": self.portfolio_size,
            "scenario": self.scenario,
            "horizon": self.horizon,
            "seed": self.seed,
        }

    @classmethod
    def from_dict(cls, d: dict) -> ECLComputeRequest:
        return cls(
            portfolio_size=int(d.get("portfolio_size", 200)),
            scenario=str(d.get("scenario", "baseline")),
            horizon=d.get("horizon", "dynamic"),
            seed=int(d.get("seed", 42)),
        )


@dataclass
class ECLComputeResponse:
    ecl: float
    confidence_band: list[float]
    segments: dict
    pd_mean: float = 0.0
    horizon_quarters: int = 9
    horizon_method: str = "dynamic"

    def to_dict(self) -> dict:
        return {
            "ecl": self.ecl,
            "confidence_band": self.confidence_band,
            "segments": self.segments,
            "pd_mean": self.pd_mean,
            "horizon_quarters": self.horizon_quarters,
            "horizon_method": self.horizon_method,
        }

    @classmethod
    def from_dict(cls, d: dict) -> ECLComputeResponse:
        return cls(
            ecl=float(d.get("ecl", 0.0)),
            confidence_band=list(d.get("confidence_band", [0.0, 0.0])),
            segments=dict(d.get("segments", {})),
            pd_mean=float(d.get("pd_mean", 0.0)),
            horizon_quarters=int(d.get("horizon_quarters", 9)),
            horizon_method=str(d.get("horizon_method", "dynamic")),
        )


@dataclass
class FilingGenerateRequest:
    institution_id: str = "BANK001"
    period: str = "2026Q1"
    horizon_quarters: int = 9
    n_samples: int = 100
    seed: int = 42
    output_dir: str = ""

    def to_dict(self) -> dict:
        return {
            "institution_id": self.institution_id,
            "period": self.period,
            "horizon_quarters": self.horizon_quarters,
            "n_samples": self.n_samples,
            "seed": self.seed,
            "output_dir": self.output_dir,
        }

    @classmethod
    def from_dict(cls, d: dict) -> FilingGenerateRequest:
        return cls(
            institution_id=str(d.get("institution_id", "BANK001")),
            period=str(d.get("period", "2026Q1")),
            horizon_quarters=int(d.get("horizon_quarters", 9)),
            n_samples=int(d.get("n_samples", 100)),
            seed=int(d.get("seed", 42)),
            output_dir=str(d.get("output_dir", "")),
        )


@dataclass
class FilingGenerateResponse:
    output_dir: str
    files: list[str]
    audit_entries: int
    duration_ms: float
    period: str = ""
    institution_id: str = ""

    def to_dict(self) -> dict:
        return {
            "output_dir": self.output_dir,
            "files": self.files,
            "audit_entries": self.audit_entries,
            "duration_ms": self.duration_ms,
            "period": self.period,
            "institution_id": self.institution_id,
        }

    @classmethod
    def from_dict(cls, d: dict) -> FilingGenerateResponse:
        return cls(
            output_dir=str(d.get("output_dir", "")),
            files=list(d.get("files", [])),
            audit_entries=int(d.get("audit_entries", 0)),
            duration_ms=float(d.get("duration_ms", 0.0)),
            period=str(d.get("period", "")),
            institution_id=str(d.get("institution_id", "")),
        )


@dataclass
class StressTestRequest:
    scenario: str = "adverse"
    horizon: int = 9
    portfolio_size: int = 100
    seed: int = 42

    def to_dict(self) -> dict:
        return {
            "scenario": self.scenario,
            "horizon": self.horizon,
            "portfolio_size": self.portfolio_size,
            "seed": self.seed,
        }

    @classmethod
    def from_dict(cls, d: dict) -> StressTestRequest:
        return cls(
            scenario=str(d.get("scenario", "adverse")),
            horizon=int(d.get("horizon", 9)),
            portfolio_size=int(d.get("portfolio_size", 100)),
            seed=int(d.get("seed", 42)),
        )


@dataclass
class StressTestResponse:
    scenario: str
    quarterly_ecl: list[float]
    peak_quarter: str
    portfolio_loss_rate: float = 0.0
    capital_impact: float = 0.0

    def to_dict(self) -> dict:
        return {
            "scenario": self.scenario,
            "quarterly_ecl": self.quarterly_ecl,
            "peak_quarter": self.peak_quarter,
            "portfolio_loss_rate": self.portfolio_loss_rate,
            "capital_impact": self.capital_impact,
        }

    @classmethod
    def from_dict(cls, d: dict) -> StressTestResponse:
        ecl = list(d.get("quarterly_ecl", []))
        peak = f"Q{ecl.index(max(ecl)) + 1}" if ecl else "Q1"
        return cls(
            scenario=str(d.get("scenario", "adverse")),
            quarterly_ecl=ecl,
            peak_quarter=str(d.get("peak_quarter", peak)),
            portfolio_loss_rate=float(d.get("portfolio_loss_rate", 0.0)),
            capital_impact=float(d.get("capital_impact", 0.0)),
        )


@dataclass
class ScenarioCompareRequest:
    scenarios: list[str] = field(
        default_factory=lambda: ["baseline", "adverse", "severely_adverse"]
    )
    cet1_ratio: float = 0.12
    portfolio_size: int = 100
    seed: int = 42

    def to_dict(self) -> dict:
        return {
            "scenarios": self.scenarios,
            "cet1_ratio": self.cet1_ratio,
            "portfolio_size": self.portfolio_size,
            "seed": self.seed,
        }

    @classmethod
    def from_dict(cls, d: dict) -> ScenarioCompareRequest:
        return cls(
            scenarios=list(d.get("scenarios", ["baseline", "adverse", "severely_adverse"])),
            cet1_ratio=float(d.get("cet1_ratio", 0.12)),
            portfolio_size=int(d.get("portfolio_size", 100)),
            seed=int(d.get("seed", 42)),
        )


@dataclass
class ScenarioCompareResponse:
    ecl_deltas: dict
    capital_waterfall: dict
    sensitivity_attribution: dict
    peak_loss_quarter: dict
    scenarios: list[str] = field(default_factory=list)
    quarter_labels: list[str] = field(default_factory=list)

    def to_dict(self) -> dict:
        return {
            "scenarios": self.scenarios,
            "quarter_labels": self.quarter_labels,
            "ecl_deltas": self.ecl_deltas,
            "capital_waterfall": self.capital_waterfall,
            "sensitivity_attribution": self.sensitivity_attribution,
            "peak_loss_quarter": self.peak_loss_quarter,
        }

    @classmethod
    def from_dict(cls, d: dict) -> ScenarioCompareResponse:
        return cls(
            ecl_deltas=dict(d.get("ecl_deltas", {})),
            capital_waterfall=dict(d.get("capital_waterfall", {})),
            sensitivity_attribution=dict(d.get("sensitivity_attribution", {})),
            peak_loss_quarter=dict(d.get("peak_loss_quarter", {})),
            scenarios=list(d.get("scenarios", [])),
            quarter_labels=list(d.get("quarter_labels", [])),
        )


@dataclass
class RegulatoryExportRequest:
    framework: str = "cecl"
    format: str = "json"
    institution_id: str = "ORXAQ-DEMO-001"
    period: str = "2024-Q4"

    def to_dict(self) -> dict:
        return {
            "framework": self.framework,
            "format": self.format,
            "institution_id": self.institution_id,
            "period": self.period,
        }

    @classmethod
    def from_dict(cls, d: dict) -> RegulatoryExportRequest:
        return cls(
            framework=str(d.get("framework", "cecl")),
            format=str(d.get("format", "json")),
            institution_id=str(d.get("institution_id", "ORXAQ-DEMO-001")),
            period=str(d.get("period", "2024-Q4")),
        )


@dataclass
class RegulatoryExportResponse:
    framework: str
    content: object
    institution_id: str = ""
    period: str = ""

    def to_dict(self) -> dict:
        return {
            "framework": self.framework,
            "content": self.content,
            "institution_id": self.institution_id,
            "period": self.period,
        }

    @classmethod
    def from_dict(cls, d: dict) -> RegulatoryExportResponse:
        return cls(
            framework=str(d.get("framework", "")),
            content=d.get("content", {}),
            institution_id=str(d.get("institution_id", "")),
            period=str(d.get("period", "")),
        )


__all__ = [
    "ECLComputeRequest",
    "ECLComputeResponse",
    "FilingGenerateRequest",
    "FilingGenerateResponse",
    "ScenarioCompareRequest",
    "ScenarioCompareResponse",
    "StressTestRequest",
    "StressTestResponse",
    "RegulatoryExportRequest",
    "RegulatoryExportResponse",
]
