"""Compliance reporting: daily trade reports, position reports, regulatory exports."""

from __future__ import annotations

import logging
import time
from collections import defaultdict
from datetime import datetime, timezone
from typing import Any

from horizon.compliance._audit import AuditTrail
from horizon.compliance._store import ComplianceStore
from horizon.compliance._types import (
    AuditEventType, ComplianceReport, DailyTradeReport, PositionReport,
)

logger = logging.getLogger("horizon.compliance.reporting")


class ReportGenerator:
    """Generate compliance reports for regulatory filing and internal review."""

    def __init__(self, store: ComplianceStore, audit: AuditTrail) -> None:
        self._store = store
        self._audit = audit

    def daily_trade_report(self, date: str | None = None) -> DailyTradeReport:
        """Generate a daily trade report.

        Args:
            date: Date string "YYYY-MM-DD". Defaults to today (UTC).
        """
        if date is None:
            date = datetime.now(timezone.utc).strftime("%Y-%m-%d")

        # Parse date to timestamp range
        dt = datetime.strptime(date, "%Y-%m-%d").replace(tzinfo=timezone.utc)
        start = dt.timestamp()
        end = start + 86400.0

        events = self._store.query_audit_events(start, end, limit=1_000_000)

        total_orders = 0
        total_fills = 0
        total_cancels = 0
        total_volume = 0.0
        by_market: dict[str, dict[str, Any]] = defaultdict(
            lambda: {"orders": 0, "fills": 0, "cancels": 0, "volume": 0.0}
        )
        by_exchange: dict[str, dict[str, Any]] = defaultdict(
            lambda: {"orders": 0, "fills": 0, "cancels": 0, "volume": 0.0}
        )

        for event in events:
            mid = event.market_id or "unknown"
            exch = event.exchange or "paper"

            if event.event_type == AuditEventType.ORDER_SUBMITTED:
                total_orders += 1
                by_market[mid]["orders"] += 1
                by_exchange[exch]["orders"] += 1
                vol = event.details.get("notional", 0.0)
                total_volume += vol
                by_market[mid]["volume"] += vol
                by_exchange[exch]["volume"] += vol

            elif event.event_type == AuditEventType.ORDER_FILLED:
                total_fills += 1
                by_market[mid]["fills"] += 1
                by_exchange[exch]["fills"] += 1

            elif event.event_type == AuditEventType.ORDER_CANCELED:
                total_cancels += 1
                by_market[mid]["cancels"] += 1
                by_exchange[exch]["cancels"] += 1

        alert_count = self._store.alert_count(start, end)

        report = DailyTradeReport(
            date=date,
            total_orders=total_orders,
            total_fills=total_fills,
            total_cancels=total_cancels,
            total_volume=total_volume,
            by_market=[{"market_id": k, **v} for k, v in sorted(by_market.items())],
            by_exchange=[{"exchange": k, **v} for k, v in sorted(by_exchange.items())],
            surveillance_alerts=alert_count,
            generated_at=time.time(),
        )

        self._audit.record(
            AuditEventType.REPORT_GENERATED, "system",
            {"report_type": "daily_trade", "date": date},
        )

        return report

    def position_report(self, engine: Any) -> PositionReport:
        """Generate current position report with concentration analysis."""
        try:
            positions = engine.positions()
        except Exception:
            positions = []

        total_notional = 0.0
        notional_by_market: dict[str, float] = {}
        pos_list: list[dict[str, Any]] = []

        for pos in positions:
            n = pos.size * pos.avg_entry_price
            notional_by_market[pos.market_id] = notional_by_market.get(pos.market_id, 0.0) + n
            total_notional += n
            pos_list.append({
                "market_id": pos.market_id,
                "side": str(pos.side),
                "size": pos.size,
                "avg_entry_price": pos.avg_entry_price,
                "notional": n,
                "exchange": getattr(pos, "exchange", "paper"),
            })

        concentration = {}
        if total_notional > 0:
            concentration = {
                mid: (n / total_notional) * 100.0
                for mid, n in notional_by_market.items()
            }

        # Limit utilization (placeholder -- actual limits come from RegulatoryLimits)
        util: dict[str, float] = {}
        if total_notional > 0:
            util["total_positions"] = len(positions)

        return PositionReport(
            timestamp=time.time(),
            positions=pos_list,
            total_notional=total_notional,
            concentration=concentration,
            limit_utilization=util,
        )

    def compliance_report(
        self,
        period_start: float,
        period_end: float,
        engine: Any,
    ) -> ComplianceReport:
        """Generate a full compliance report for a time period."""
        from datetime import datetime, timezone

        date_str = datetime.fromtimestamp(period_start, tz=timezone.utc).strftime("%Y-%m-%d")
        trade_report = self.daily_trade_report(date_str)
        position_report = self.position_report(engine)

        # Surveillance summary
        alerts = self._store.query_alerts(period_start, period_end, limit=10000)
        surv_summary: dict[str, int] = defaultdict(int)
        for a in alerts:
            surv_summary[a.alert_type] += 1

        # Approval summary
        events = self._store.query_audit_events(
            period_start, period_end,
            limit=100000,
        )
        approval_summary: dict[str, int] = defaultdict(int)
        kill_switch_count = 0
        for e in events:
            if e.event_type in (
                AuditEventType.APPROVAL_GRANTED,
                AuditEventType.APPROVAL_DENIED,
                AuditEventType.APPROVAL_EXPIRED,
                AuditEventType.APPROVAL_REQUESTED,
            ):
                approval_summary[e.event_type.value] += 1
            elif e.event_type == AuditEventType.KILL_SWITCH_ACTIVATED:
                kill_switch_count += 1

        # Chain integrity
        valid, _ = self._audit.verify_integrity(period_start, period_end)

        report = ComplianceReport(
            period_start=period_start,
            period_end=period_end,
            trade_report=trade_report,
            position_report=position_report,
            surveillance_summary=dict(surv_summary),
            approval_summary=dict(approval_summary),
            kill_switch_events=kill_switch_count,
            chain_integrity=valid,
        )

        self._audit.record(
            AuditEventType.REPORT_GENERATED, "system",
            {"report_type": "compliance", "period_start": period_start, "period_end": period_end},
        )

        return report
