"""
Compliance repositories — extracted from compliance/db/repository.py.

Phase 1 Step 5: the monolithic repository module is decomposed per
aggregate. Every repository class is re-exported from
``compliance.db.repository`` for backwards compatibility.
"""

import uuid
from datetime import datetime, date, timezone
from typing import List, Optional, Dict, Any, Tuple

from sqlalchemy.orm import Session as DBSession, selectinload, joinedload
from sqlalchemy import func, and_, or_

from compliance.db.models import (
    RegulationDB, RequirementDB, ControlDB, ControlMappingDB,
    EvidenceDB, RiskDB, AuditExportDB,
    AuditSessionDB, AuditSignOffDB, AuditResultEnum, AuditSessionStatusEnum,
    RegulationTypeEnum, ControlDomainEnum, ControlStatusEnum,
    RiskLevelEnum, EvidenceStatusEnum, ExportStatusEnum,
    ServiceModuleDB, ModuleRegulationMappingDB,
)

class AuditExportRepository:
    """Repository for audit exports."""

    def __init__(self, db: DBSession):
        self.db = db

    def create(
        self,
        export_type: str,
        requested_by: str,
        export_name: Optional[str] = None,
        included_regulations: Optional[List[str]] = None,
        included_domains: Optional[List[str]] = None,
        date_range_start: Optional[date] = None,
        date_range_end: Optional[date] = None,
    ) -> AuditExportDB:
        """Create an export request."""
        export = AuditExportDB(
            id=str(uuid.uuid4()),
            export_type=export_type,
            export_name=export_name or f"audit_export_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
            requested_by=requested_by,
            included_regulations=included_regulations,
            included_domains=included_domains,
            date_range_start=date_range_start,
            date_range_end=date_range_end,
        )
        self.db.add(export)
        self.db.commit()
        self.db.refresh(export)
        return export

    def get_by_id(self, export_id: str) -> Optional[AuditExportDB]:
        """Get export by ID."""
        return self.db.query(AuditExportDB).filter(AuditExportDB.id == export_id).first()

    def get_all(self, limit: int = 50) -> List[AuditExportDB]:
        """Get all exports."""
        return (
            self.db.query(AuditExportDB)
            .order_by(AuditExportDB.requested_at.desc())
            .limit(limit)
            .all()
        )

    def update_status(
        self,
        export_id: str,
        status: ExportStatusEnum,
        file_path: Optional[str] = None,
        file_hash: Optional[str] = None,
        file_size_bytes: Optional[int] = None,
        error_message: Optional[str] = None,
        total_controls: Optional[int] = None,
        total_evidence: Optional[int] = None,
        compliance_score: Optional[float] = None,
    ) -> Optional[AuditExportDB]:
        """Update export status."""
        export = self.get_by_id(export_id)
        if not export:
            return None

        export.status = status
        if file_path:
            export.file_path = file_path
        if file_hash:
            export.file_hash = file_hash
        if file_size_bytes:
            export.file_size_bytes = file_size_bytes
        if error_message:
            export.error_message = error_message
        if total_controls is not None:
            export.total_controls = total_controls
        if total_evidence is not None:
            export.total_evidence = total_evidence
        if compliance_score is not None:
            export.compliance_score = compliance_score

        if status == ExportStatusEnum.COMPLETED:
            export.completed_at = datetime.now(timezone.utc)

        export.updated_at = datetime.now(timezone.utc)
        self.db.commit()
        self.db.refresh(export)
        return export

