"""Data retention and archival for compliance (SEC Rule 17a-4)."""

from __future__ import annotations

import logging
import os
import shutil
import time
from typing import Any

from horizon.compliance._audit import AuditTrail
from horizon.compliance._store import ComplianceStore
from horizon.compliance._types import AuditEventType, ComplianceConfig

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


class RetentionManager:
    """Manage data retention, archival, and purging.

    SEC Rule 17a-4 requires broker-dealers to retain trade records for
    at least 6 years (first 2 years in easily accessible location).
    Default retention_days=2555 (~7 years) exceeds this.

    Features:
    - Automatic purge of records older than retention_days
    - CSV export for long-term archival before purge
    - Audit trail of all purge operations
    """

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

    @property
    def retention_days(self) -> int:
        return self._config.retention_days

    def cutoff_timestamp(self) -> float:
        """Compute the purge cutoff timestamp based on retention_days."""
        return time.time() - (self._config.retention_days * 86400.0)

    def archive_and_purge(
        self,
        archive_dir: str | None = None,
        actor: str = "system",
    ) -> dict[str, Any]:
        """Archive records older than retention period, then purge.

        Args:
            archive_dir: Directory to write CSV archives.
                         If None, purges without archiving.
            actor: Identity of the person/system initiating the purge.

        Returns:
            Summary dict with counts of archived and purged records.
        """
        cutoff = self.cutoff_timestamp()
        archived_count = 0

        # Step 1: Archive to CSV if directory provided
        if archive_dir is not None:
            os.makedirs(archive_dir, exist_ok=True)
            ts_str = time.strftime("%Y%m%d_%H%M%S", time.gmtime())
            csv_path = os.path.join(archive_dir, f"audit_archive_{ts_str}.csv")
            archived_count = self._audit.export_csv(csv_path, end=cutoff)
            if archived_count > 0:
                logger.info("Archived %d events to %s", archived_count, csv_path)

        # Step 2: Purge old records
        purged = self._store.purge_before(cutoff)

        # Step 3: Record the purge in audit trail
        self._audit.record(
            AuditEventType.DATA_PURGED, actor,
            {
                "cutoff_timestamp": cutoff,
                "retention_days": self._config.retention_days,
                "events_purged": purged,
                "events_archived": archived_count,
                "archive_dir": archive_dir,
            },
        )

        logger.info(
            "Retention purge: %d events purged (archived=%d, retention=%dd)",
            purged, archived_count, self._config.retention_days,
        )

        return {
            "cutoff_timestamp": cutoff,
            "events_purged": purged,
            "events_archived": archived_count,
        }

    def check_retention_status(self) -> dict[str, Any]:
        """Return current retention status for monitoring."""
        total_events = self._store.event_count()
        cutoff = self.cutoff_timestamp()
        eligible = len(self._store.query_audit_events(end=cutoff, limit=1))
        return {
            "total_events": total_events,
            "retention_days": self._config.retention_days,
            "has_purgeable_records": eligible > 0,
            "cutoff_timestamp": cutoff,
        }
