"""
ISO 27001 ISMS API Routes

Provides endpoints for ISO 27001 certification-ready ISMS management:
- Scope & Context (Kapitel 4)
- Policies & Objectives (Kapitel 5, 6)
- Statement of Applicability (SoA)
- Audit Findings & CAPA (Kapitel 9, 10)
- Management Reviews (Kapitel 9.3)
- Internal Audits (Kapitel 9.2)
- ISMS Readiness Check
"""

import uuid
import hashlib
from datetime import datetime, date
from typing import Optional, List

from fastapi import APIRouter, HTTPException, Query, Depends
from sqlalchemy.orm import Session

from ..db.models import (
    ISMSScopeDB, ISMSContextDB, ISMSPolicyDB, SecurityObjectiveDB,
    StatementOfApplicabilityDB, AuditFindingDB, CorrectiveActionDB,
    ManagementReviewDB, InternalAuditDB, AuditTrailDB, ISMSReadinessCheckDB,
    ApprovalStatusEnum, FindingTypeEnum, FindingStatusEnum, CAPATypeEnum
)
from .schemas import (
    # Scope
    ISMSScopeCreate, ISMSScopeUpdate, ISMSScopeResponse, ISMSScopeApproveRequest,
    # Context
    ISMSContextCreate, ISMSContextResponse,
    # Policies
    ISMSPolicyCreate, ISMSPolicyUpdate, ISMSPolicyResponse, ISMSPolicyListResponse,
    ISMSPolicyApproveRequest,
    # Objectives
    SecurityObjectiveCreate, SecurityObjectiveUpdate, SecurityObjectiveResponse,
    SecurityObjectiveListResponse,
    # SoA
    SoAEntryCreate, SoAEntryUpdate, SoAEntryResponse, SoAListResponse, SoAApproveRequest,
    # Findings
    AuditFindingCreate, AuditFindingUpdate, AuditFindingResponse,
    AuditFindingListResponse, AuditFindingCloseRequest,
    # CAPA
    CorrectiveActionCreate, CorrectiveActionUpdate, CorrectiveActionResponse,
    CorrectiveActionListResponse, CAPAVerifyRequest,
    # Management Review
    ManagementReviewCreate, ManagementReviewUpdate, ManagementReviewResponse,
    ManagementReviewListResponse, ManagementReviewApproveRequest,
    # Internal Audit
    InternalAuditCreate, InternalAuditUpdate, InternalAuditResponse,
    InternalAuditListResponse, InternalAuditCompleteRequest,
    # Readiness
    ISMSReadinessCheckResponse, ISMSReadinessCheckRequest, PotentialFinding,
    # Audit Trail
    AuditTrailResponse, AuditTrailEntry, PaginationMeta,
    # Overview
    ISO27001OverviewResponse, ISO27001ChapterStatus
)

# Import database session dependency
from classroom_engine.database import get_db

router = APIRouter(prefix="/isms", tags=["ISMS"])


# =============================================================================
# Helper Functions
# =============================================================================

def generate_id() -> str:
    """Generate a UUID string."""
    return str(uuid.uuid4())


def create_signature(data: str) -> str:
    """Create SHA-256 signature."""
    return hashlib.sha256(data.encode()).hexdigest()


def log_audit_trail(
    db: Session,
    entity_type: str,
    entity_id: str,
    entity_name: str,
    action: str,
    performed_by: str,
    field_changed: str = None,
    old_value: str = None,
    new_value: str = None,
    change_summary: str = None
):
    """Log an entry to the audit trail."""
    trail = AuditTrailDB(
        id=generate_id(),
        entity_type=entity_type,
        entity_id=entity_id,
        entity_name=entity_name,
        action=action,
        field_changed=field_changed,
        old_value=old_value,
        new_value=new_value,
        change_summary=change_summary,
        performed_by=performed_by,
        performed_at=datetime.utcnow(),
        checksum=create_signature(f"{entity_type}|{entity_id}|{action}|{performed_by}")
    )
    db.add(trail)


# =============================================================================
# ISMS SCOPE (ISO 27001 4.3)
# =============================================================================

@router.get("/scope", response_model=ISMSScopeResponse)
async def get_isms_scope(db: Session = Depends(get_db)):
    """
    Get the current ISMS scope.

    The scope defines the boundaries and applicability of the ISMS.
    Only one active scope should exist at a time.
    """
    scope = db.query(ISMSScopeDB).filter(
        ISMSScopeDB.status != ApprovalStatusEnum.SUPERSEDED
    ).order_by(ISMSScopeDB.created_at.desc()).first()

    if not scope:
        raise HTTPException(status_code=404, detail="No ISMS scope defined yet")

    return scope


@router.post("/scope", response_model=ISMSScopeResponse)
async def create_isms_scope(
    data: ISMSScopeCreate,
    created_by: str = Query(..., description="User creating the scope"),
    db: Session = Depends(get_db)
):
    """
    Create a new ISMS scope definition.

    Supersedes any existing scope.
    """
    # Supersede existing scopes
    existing = db.query(ISMSScopeDB).filter(
        ISMSScopeDB.status != ApprovalStatusEnum.SUPERSEDED
    ).all()
    for s in existing:
        s.status = ApprovalStatusEnum.SUPERSEDED

    scope = ISMSScopeDB(
        id=generate_id(),
        scope_statement=data.scope_statement,
        included_locations=data.included_locations,
        included_processes=data.included_processes,
        included_services=data.included_services,
        excluded_items=data.excluded_items,
        exclusion_justification=data.exclusion_justification,
        organizational_boundary=data.organizational_boundary,
        physical_boundary=data.physical_boundary,
        technical_boundary=data.technical_boundary,
        status=ApprovalStatusEnum.DRAFT,
        created_by=created_by
    )
    db.add(scope)

    log_audit_trail(db, "isms_scope", scope.id, "ISMS Scope", "create", created_by)
    db.commit()
    db.refresh(scope)

    return scope


@router.put("/scope/{scope_id}", response_model=ISMSScopeResponse)
async def update_isms_scope(
    scope_id: str,
    data: ISMSScopeUpdate,
    updated_by: str = Query(..., description="User updating the scope"),
    db: Session = Depends(get_db)
):
    """Update ISMS scope (only if in draft status)."""
    scope = db.query(ISMSScopeDB).filter(ISMSScopeDB.id == scope_id).first()
    if not scope:
        raise HTTPException(status_code=404, detail="Scope not found")

    if scope.status == ApprovalStatusEnum.APPROVED:
        raise HTTPException(status_code=400, detail="Cannot modify approved scope. Create new version.")

    for field, value in data.model_dump(exclude_unset=True).items():
        setattr(scope, field, value)

    scope.updated_by = updated_by
    scope.updated_at = datetime.utcnow()

    # Increment version if significant changes
    version_parts = scope.version.split(".")
    scope.version = f"{version_parts[0]}.{int(version_parts[1]) + 1}"

    log_audit_trail(db, "isms_scope", scope.id, "ISMS Scope", "update", updated_by)
    db.commit()
    db.refresh(scope)

    return scope


@router.post("/scope/{scope_id}/approve", response_model=ISMSScopeResponse)
async def approve_isms_scope(
    scope_id: str,
    data: ISMSScopeApproveRequest,
    db: Session = Depends(get_db)
):
    """
    Approve the ISMS scope.

    This is a MANDATORY step for ISO 27001 certification.
    Must be approved by top management.
    """
    scope = db.query(ISMSScopeDB).filter(ISMSScopeDB.id == scope_id).first()
    if not scope:
        raise HTTPException(status_code=404, detail="Scope not found")

    scope.status = ApprovalStatusEnum.APPROVED
    scope.approved_by = data.approved_by
    scope.approved_at = datetime.utcnow()
    scope.effective_date = data.effective_date
    scope.review_date = data.review_date
    scope.approval_signature = create_signature(
        f"{scope.scope_statement}|{data.approved_by}|{datetime.utcnow().isoformat()}"
    )

    log_audit_trail(db, "isms_scope", scope.id, "ISMS Scope", "approve", data.approved_by)
    db.commit()
    db.refresh(scope)

    return scope


# =============================================================================
# ISMS CONTEXT (ISO 27001 4.1, 4.2)
# =============================================================================

@router.get("/context", response_model=ISMSContextResponse)
async def get_isms_context(db: Session = Depends(get_db)):
    """Get the current ISMS context analysis."""
    context = db.query(ISMSContextDB).filter(
        ISMSContextDB.status != ApprovalStatusEnum.SUPERSEDED
    ).order_by(ISMSContextDB.created_at.desc()).first()

    if not context:
        raise HTTPException(status_code=404, detail="No ISMS context defined yet")

    return context


@router.post("/context", response_model=ISMSContextResponse)
async def create_isms_context(
    data: ISMSContextCreate,
    created_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Create or update ISMS context analysis."""
    # Supersede existing
    existing = db.query(ISMSContextDB).filter(
        ISMSContextDB.status != ApprovalStatusEnum.SUPERSEDED
    ).all()
    for c in existing:
        c.status = ApprovalStatusEnum.SUPERSEDED

    context = ISMSContextDB(
        id=generate_id(),
        internal_issues=[i.model_dump() for i in data.internal_issues] if data.internal_issues else None,
        external_issues=[i.model_dump() for i in data.external_issues] if data.external_issues else None,
        interested_parties=[p.model_dump() for p in data.interested_parties] if data.interested_parties else None,
        regulatory_requirements=data.regulatory_requirements,
        contractual_requirements=data.contractual_requirements,
        swot_strengths=data.swot_strengths,
        swot_weaknesses=data.swot_weaknesses,
        swot_opportunities=data.swot_opportunities,
        swot_threats=data.swot_threats,
        status=ApprovalStatusEnum.DRAFT
    )
    db.add(context)

    log_audit_trail(db, "isms_context", context.id, "ISMS Context", "create", created_by)
    db.commit()
    db.refresh(context)

    return context


# =============================================================================
# ISMS POLICIES (ISO 27001 5.2)
# =============================================================================

@router.get("/policies", response_model=ISMSPolicyListResponse)
async def list_policies(
    policy_type: Optional[str] = None,
    status: Optional[str] = None,
    db: Session = Depends(get_db)
):
    """List all ISMS policies."""
    query = db.query(ISMSPolicyDB)

    if policy_type:
        query = query.filter(ISMSPolicyDB.policy_type == policy_type)
    if status:
        query = query.filter(ISMSPolicyDB.status == status)

    policies = query.order_by(ISMSPolicyDB.policy_id).all()

    return ISMSPolicyListResponse(policies=policies, total=len(policies))


@router.post("/policies", response_model=ISMSPolicyResponse)
async def create_policy(data: ISMSPolicyCreate, db: Session = Depends(get_db)):
    """Create a new ISMS policy."""
    # Check for duplicate policy_id
    existing = db.query(ISMSPolicyDB).filter(
        ISMSPolicyDB.policy_id == data.policy_id
    ).first()
    if existing:
        raise HTTPException(status_code=400, detail=f"Policy {data.policy_id} already exists")

    policy = ISMSPolicyDB(
        id=generate_id(),
        policy_id=data.policy_id,
        title=data.title,
        policy_type=data.policy_type,
        description=data.description,
        policy_text=data.policy_text,
        applies_to=data.applies_to,
        review_frequency_months=data.review_frequency_months,
        related_controls=data.related_controls,
        authored_by=data.authored_by,
        status=ApprovalStatusEnum.DRAFT
    )
    db.add(policy)

    log_audit_trail(db, "isms_policy", policy.id, policy.policy_id, "create", data.authored_by)
    db.commit()
    db.refresh(policy)

    return policy


@router.get("/policies/{policy_id}", response_model=ISMSPolicyResponse)
async def get_policy(policy_id: str, db: Session = Depends(get_db)):
    """Get a specific policy by ID."""
    policy = db.query(ISMSPolicyDB).filter(
        (ISMSPolicyDB.id == policy_id) | (ISMSPolicyDB.policy_id == policy_id)
    ).first()

    if not policy:
        raise HTTPException(status_code=404, detail="Policy not found")

    return policy


@router.put("/policies/{policy_id}", response_model=ISMSPolicyResponse)
async def update_policy(
    policy_id: str,
    data: ISMSPolicyUpdate,
    updated_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Update a policy (creates new version if approved)."""
    policy = db.query(ISMSPolicyDB).filter(
        (ISMSPolicyDB.id == policy_id) | (ISMSPolicyDB.policy_id == policy_id)
    ).first()

    if not policy:
        raise HTTPException(status_code=404, detail="Policy not found")

    if policy.status == ApprovalStatusEnum.APPROVED:
        # Increment major version
        version_parts = policy.version.split(".")
        policy.version = f"{int(version_parts[0]) + 1}.0"
        policy.status = ApprovalStatusEnum.DRAFT

    for field, value in data.model_dump(exclude_unset=True).items():
        setattr(policy, field, value)

    log_audit_trail(db, "isms_policy", policy.id, policy.policy_id, "update", updated_by)
    db.commit()
    db.refresh(policy)

    return policy


@router.post("/policies/{policy_id}/approve", response_model=ISMSPolicyResponse)
async def approve_policy(
    policy_id: str,
    data: ISMSPolicyApproveRequest,
    db: Session = Depends(get_db)
):
    """Approve a policy. Must be approved by top management."""
    policy = db.query(ISMSPolicyDB).filter(
        (ISMSPolicyDB.id == policy_id) | (ISMSPolicyDB.policy_id == policy_id)
    ).first()

    if not policy:
        raise HTTPException(status_code=404, detail="Policy not found")

    policy.reviewed_by = data.reviewed_by
    policy.approved_by = data.approved_by
    policy.approved_at = datetime.utcnow()
    policy.effective_date = data.effective_date
    policy.next_review_date = date(
        data.effective_date.year + (policy.review_frequency_months // 12),
        data.effective_date.month,
        data.effective_date.day
    )
    policy.status = ApprovalStatusEnum.APPROVED
    policy.approval_signature = create_signature(
        f"{policy.policy_id}|{data.approved_by}|{datetime.utcnow().isoformat()}"
    )

    log_audit_trail(db, "isms_policy", policy.id, policy.policy_id, "approve", data.approved_by)
    db.commit()
    db.refresh(policy)

    return policy


# =============================================================================
# SECURITY OBJECTIVES (ISO 27001 6.2)
# =============================================================================

@router.get("/objectives", response_model=SecurityObjectiveListResponse)
async def list_objectives(
    category: Optional[str] = None,
    status: Optional[str] = None,
    db: Session = Depends(get_db)
):
    """List all security objectives."""
    query = db.query(SecurityObjectiveDB)

    if category:
        query = query.filter(SecurityObjectiveDB.category == category)
    if status:
        query = query.filter(SecurityObjectiveDB.status == status)

    objectives = query.order_by(SecurityObjectiveDB.objective_id).all()

    return SecurityObjectiveListResponse(objectives=objectives, total=len(objectives))


@router.post("/objectives", response_model=SecurityObjectiveResponse)
async def create_objective(
    data: SecurityObjectiveCreate,
    created_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Create a new security objective."""
    objective = SecurityObjectiveDB(
        id=generate_id(),
        objective_id=data.objective_id,
        title=data.title,
        description=data.description,
        category=data.category,
        specific=data.specific,
        measurable=data.measurable,
        achievable=data.achievable,
        relevant=data.relevant,
        time_bound=data.time_bound,
        kpi_name=data.kpi_name,
        kpi_target=data.kpi_target,
        kpi_unit=data.kpi_unit,
        measurement_frequency=data.measurement_frequency,
        owner=data.owner,
        target_date=data.target_date,
        related_controls=data.related_controls,
        related_risks=data.related_risks,
        status="active"
    )
    db.add(objective)

    log_audit_trail(db, "security_objective", objective.id, objective.objective_id, "create", created_by)
    db.commit()
    db.refresh(objective)

    return objective


@router.put("/objectives/{objective_id}", response_model=SecurityObjectiveResponse)
async def update_objective(
    objective_id: str,
    data: SecurityObjectiveUpdate,
    updated_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Update a security objective's progress."""
    objective = db.query(SecurityObjectiveDB).filter(
        (SecurityObjectiveDB.id == objective_id) |
        (SecurityObjectiveDB.objective_id == objective_id)
    ).first()

    if not objective:
        raise HTTPException(status_code=404, detail="Objective not found")

    for field, value in data.model_dump(exclude_unset=True).items():
        setattr(objective, field, value)

    # Mark as achieved if progress is 100%
    if objective.progress_percentage >= 100 and objective.status == "active":
        objective.status = "achieved"
        objective.achieved_date = date.today()

    log_audit_trail(db, "security_objective", objective.id, objective.objective_id, "update", updated_by)
    db.commit()
    db.refresh(objective)

    return objective


# =============================================================================
# STATEMENT OF APPLICABILITY (SoA)
# =============================================================================

@router.get("/soa", response_model=SoAListResponse)
async def list_soa_entries(
    is_applicable: Optional[bool] = None,
    implementation_status: Optional[str] = None,
    category: Optional[str] = None,
    db: Session = Depends(get_db)
):
    """List all Statement of Applicability entries."""
    query = db.query(StatementOfApplicabilityDB)

    if is_applicable is not None:
        query = query.filter(StatementOfApplicabilityDB.is_applicable == is_applicable)
    if implementation_status:
        query = query.filter(StatementOfApplicabilityDB.implementation_status == implementation_status)
    if category:
        query = query.filter(StatementOfApplicabilityDB.annex_a_category == category)

    entries = query.order_by(StatementOfApplicabilityDB.annex_a_control).all()

    applicable_count = sum(1 for e in entries if e.is_applicable)
    implemented_count = sum(1 for e in entries if e.implementation_status == "implemented")
    planned_count = sum(1 for e in entries if e.implementation_status == "planned")

    return SoAListResponse(
        entries=entries,
        total=len(entries),
        applicable_count=applicable_count,
        not_applicable_count=len(entries) - applicable_count,
        implemented_count=implemented_count,
        planned_count=planned_count
    )


@router.post("/soa", response_model=SoAEntryResponse)
async def create_soa_entry(
    data: SoAEntryCreate,
    created_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Create a new SoA entry for an Annex A control."""
    # Check for duplicate
    existing = db.query(StatementOfApplicabilityDB).filter(
        StatementOfApplicabilityDB.annex_a_control == data.annex_a_control
    ).first()
    if existing:
        raise HTTPException(status_code=400, detail=f"SoA entry for {data.annex_a_control} already exists")

    entry = StatementOfApplicabilityDB(
        id=generate_id(),
        annex_a_control=data.annex_a_control,
        annex_a_title=data.annex_a_title,
        annex_a_category=data.annex_a_category,
        is_applicable=data.is_applicable,
        applicability_justification=data.applicability_justification,
        implementation_status=data.implementation_status,
        implementation_notes=data.implementation_notes,
        breakpilot_control_ids=data.breakpilot_control_ids,
        coverage_level=data.coverage_level,
        evidence_description=data.evidence_description,
        risk_assessment_notes=data.risk_assessment_notes,
        compensating_controls=data.compensating_controls
    )
    db.add(entry)

    log_audit_trail(db, "soa", entry.id, entry.annex_a_control, "create", created_by)
    db.commit()
    db.refresh(entry)

    return entry


@router.put("/soa/{entry_id}", response_model=SoAEntryResponse)
async def update_soa_entry(
    entry_id: str,
    data: SoAEntryUpdate,
    updated_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Update an SoA entry."""
    entry = db.query(StatementOfApplicabilityDB).filter(
        (StatementOfApplicabilityDB.id == entry_id) |
        (StatementOfApplicabilityDB.annex_a_control == entry_id)
    ).first()

    if not entry:
        raise HTTPException(status_code=404, detail="SoA entry not found")

    for field, value in data.model_dump(exclude_unset=True).items():
        setattr(entry, field, value)

    # Increment version
    version_parts = entry.version.split(".")
    entry.version = f"{version_parts[0]}.{int(version_parts[1]) + 1}"

    log_audit_trail(db, "soa", entry.id, entry.annex_a_control, "update", updated_by)
    db.commit()
    db.refresh(entry)

    return entry


@router.post("/soa/{entry_id}/approve", response_model=SoAEntryResponse)
async def approve_soa_entry(
    entry_id: str,
    data: SoAApproveRequest,
    db: Session = Depends(get_db)
):
    """Approve an SoA entry."""
    entry = db.query(StatementOfApplicabilityDB).filter(
        (StatementOfApplicabilityDB.id == entry_id) |
        (StatementOfApplicabilityDB.annex_a_control == entry_id)
    ).first()

    if not entry:
        raise HTTPException(status_code=404, detail="SoA entry not found")

    entry.reviewed_by = data.reviewed_by
    entry.reviewed_at = datetime.utcnow()
    entry.approved_by = data.approved_by
    entry.approved_at = datetime.utcnow()

    log_audit_trail(db, "soa", entry.id, entry.annex_a_control, "approve", data.approved_by)
    db.commit()
    db.refresh(entry)

    return entry


# =============================================================================
# AUDIT FINDINGS (Major/Minor/OFI)
# =============================================================================

@router.get("/findings", response_model=AuditFindingListResponse)
async def list_findings(
    finding_type: Optional[str] = None,
    status: Optional[str] = None,
    internal_audit_id: Optional[str] = None,
    db: Session = Depends(get_db)
):
    """List all audit findings."""
    query = db.query(AuditFindingDB)

    if finding_type:
        query = query.filter(AuditFindingDB.finding_type == finding_type)
    if status:
        query = query.filter(AuditFindingDB.status == status)
    if internal_audit_id:
        query = query.filter(AuditFindingDB.internal_audit_id == internal_audit_id)

    findings = query.order_by(AuditFindingDB.identified_date.desc()).all()

    major_count = sum(1 for f in findings if f.finding_type == FindingTypeEnum.MAJOR)
    minor_count = sum(1 for f in findings if f.finding_type == FindingTypeEnum.MINOR)
    ofi_count = sum(1 for f in findings if f.finding_type == FindingTypeEnum.OFI)
    open_count = sum(1 for f in findings if f.status != FindingStatusEnum.CLOSED)

    # Add is_blocking property to each finding
    for f in findings:
        f.is_blocking = f.finding_type == FindingTypeEnum.MAJOR and f.status != FindingStatusEnum.CLOSED

    return AuditFindingListResponse(
        findings=findings,
        total=len(findings),
        major_count=major_count,
        minor_count=minor_count,
        ofi_count=ofi_count,
        open_count=open_count
    )


@router.post("/findings", response_model=AuditFindingResponse)
async def create_finding(data: AuditFindingCreate, db: Session = Depends(get_db)):
    """
    Create a new audit finding.

    Finding types:
    - major: Blocks certification, requires immediate CAPA
    - minor: Requires CAPA within deadline
    - ofi: Opportunity for improvement (no mandatory action)
    - positive: Good practice observation
    """
    # Generate finding ID
    year = date.today().year
    existing_count = db.query(AuditFindingDB).filter(
        AuditFindingDB.finding_id.like(f"FIND-{year}-%")
    ).count()
    finding_id = f"FIND-{year}-{existing_count + 1:03d}"

    finding = AuditFindingDB(
        id=generate_id(),
        finding_id=finding_id,
        audit_session_id=data.audit_session_id,
        internal_audit_id=data.internal_audit_id,
        finding_type=FindingTypeEnum(data.finding_type),
        iso_chapter=data.iso_chapter,
        annex_a_control=data.annex_a_control,
        title=data.title,
        description=data.description,
        objective_evidence=data.objective_evidence,
        impact_description=data.impact_description,
        affected_processes=data.affected_processes,
        affected_assets=data.affected_assets,
        owner=data.owner,
        auditor=data.auditor,
        due_date=data.due_date,
        status=FindingStatusEnum.OPEN
    )
    db.add(finding)

    # Update internal audit counts if linked
    if data.internal_audit_id:
        audit = db.query(InternalAuditDB).filter(
            InternalAuditDB.id == data.internal_audit_id
        ).first()
        if audit:
            audit.total_findings = (audit.total_findings or 0) + 1
            if data.finding_type == "major":
                audit.major_findings = (audit.major_findings or 0) + 1
            elif data.finding_type == "minor":
                audit.minor_findings = (audit.minor_findings or 0) + 1
            elif data.finding_type == "ofi":
                audit.ofi_count = (audit.ofi_count or 0) + 1
            elif data.finding_type == "positive":
                audit.positive_observations = (audit.positive_observations or 0) + 1

    log_audit_trail(db, "audit_finding", finding.id, finding_id, "create", data.auditor)
    db.commit()
    db.refresh(finding)

    finding.is_blocking = finding.finding_type == FindingTypeEnum.MAJOR
    return finding


@router.put("/findings/{finding_id}", response_model=AuditFindingResponse)
async def update_finding(
    finding_id: str,
    data: AuditFindingUpdate,
    updated_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Update an audit finding."""
    finding = db.query(AuditFindingDB).filter(
        (AuditFindingDB.id == finding_id) | (AuditFindingDB.finding_id == finding_id)
    ).first()

    if not finding:
        raise HTTPException(status_code=404, detail="Finding not found")

    for field, value in data.model_dump(exclude_unset=True).items():
        if field == "status" and value:
            setattr(finding, field, FindingStatusEnum(value))
        else:
            setattr(finding, field, value)

    log_audit_trail(db, "audit_finding", finding.id, finding.finding_id, "update", updated_by)
    db.commit()
    db.refresh(finding)

    finding.is_blocking = finding.finding_type == FindingTypeEnum.MAJOR and finding.status != FindingStatusEnum.CLOSED
    return finding


@router.post("/findings/{finding_id}/close", response_model=AuditFindingResponse)
async def close_finding(
    finding_id: str,
    data: AuditFindingCloseRequest,
    db: Session = Depends(get_db)
):
    """
    Close an audit finding after verification.

    Requires:
    - All CAPAs to be completed and verified
    - Verification evidence documenting the fix
    """
    finding = db.query(AuditFindingDB).filter(
        (AuditFindingDB.id == finding_id) | (AuditFindingDB.finding_id == finding_id)
    ).first()

    if not finding:
        raise HTTPException(status_code=404, detail="Finding not found")

    # Check if all CAPAs are verified
    open_capas = db.query(CorrectiveActionDB).filter(
        CorrectiveActionDB.finding_id == finding.id,
        CorrectiveActionDB.status != "verified"
    ).count()

    if open_capas > 0:
        raise HTTPException(
            status_code=400,
            detail=f"Cannot close finding: {open_capas} CAPA(s) not yet verified"
        )

    finding.status = FindingStatusEnum.CLOSED
    finding.closed_date = date.today()
    finding.closure_notes = data.closure_notes
    finding.closed_by = data.closed_by
    finding.verification_method = data.verification_method
    finding.verification_evidence = data.verification_evidence
    finding.verified_by = data.closed_by
    finding.verified_at = datetime.utcnow()

    log_audit_trail(db, "audit_finding", finding.id, finding.finding_id, "close", data.closed_by)
    db.commit()
    db.refresh(finding)

    finding.is_blocking = False
    return finding


# =============================================================================
# CORRECTIVE ACTIONS (CAPA)
# =============================================================================

@router.get("/capa", response_model=CorrectiveActionListResponse)
async def list_capas(
    finding_id: Optional[str] = None,
    status: Optional[str] = None,
    assigned_to: Optional[str] = None,
    db: Session = Depends(get_db)
):
    """List all corrective/preventive actions."""
    query = db.query(CorrectiveActionDB)

    if finding_id:
        query = query.filter(CorrectiveActionDB.finding_id == finding_id)
    if status:
        query = query.filter(CorrectiveActionDB.status == status)
    if assigned_to:
        query = query.filter(CorrectiveActionDB.assigned_to == assigned_to)

    actions = query.order_by(CorrectiveActionDB.planned_completion).all()

    return CorrectiveActionListResponse(actions=actions, total=len(actions))


@router.post("/capa", response_model=CorrectiveActionResponse)
async def create_capa(
    data: CorrectiveActionCreate,
    created_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Create a new corrective/preventive action for a finding."""
    # Verify finding exists
    finding = db.query(AuditFindingDB).filter(AuditFindingDB.id == data.finding_id).first()
    if not finding:
        raise HTTPException(status_code=404, detail="Finding not found")

    # Generate CAPA ID
    year = date.today().year
    existing_count = db.query(CorrectiveActionDB).filter(
        CorrectiveActionDB.capa_id.like(f"CAPA-{year}-%")
    ).count()
    capa_id = f"CAPA-{year}-{existing_count + 1:03d}"

    capa = CorrectiveActionDB(
        id=generate_id(),
        capa_id=capa_id,
        finding_id=data.finding_id,
        capa_type=CAPATypeEnum(data.capa_type),
        title=data.title,
        description=data.description,
        expected_outcome=data.expected_outcome,
        assigned_to=data.assigned_to,
        planned_start=data.planned_start,
        planned_completion=data.planned_completion,
        effectiveness_criteria=data.effectiveness_criteria,
        estimated_effort_hours=data.estimated_effort_hours,
        resources_required=data.resources_required,
        status="planned"
    )
    db.add(capa)

    # Update finding status
    finding.status = FindingStatusEnum.CORRECTIVE_ACTION_PENDING

    log_audit_trail(db, "capa", capa.id, capa_id, "create", created_by)
    db.commit()
    db.refresh(capa)

    return capa


@router.put("/capa/{capa_id}", response_model=CorrectiveActionResponse)
async def update_capa(
    capa_id: str,
    data: CorrectiveActionUpdate,
    updated_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Update a CAPA's progress."""
    capa = db.query(CorrectiveActionDB).filter(
        (CorrectiveActionDB.id == capa_id) | (CorrectiveActionDB.capa_id == capa_id)
    ).first()

    if not capa:
        raise HTTPException(status_code=404, detail="CAPA not found")

    for field, value in data.model_dump(exclude_unset=True).items():
        setattr(capa, field, value)

    # If completed, set actual completion date
    if capa.status == "completed" and not capa.actual_completion:
        capa.actual_completion = date.today()

    log_audit_trail(db, "capa", capa.id, capa.capa_id, "update", updated_by)
    db.commit()
    db.refresh(capa)

    return capa


@router.post("/capa/{capa_id}/verify", response_model=CorrectiveActionResponse)
async def verify_capa(
    capa_id: str,
    data: CAPAVerifyRequest,
    db: Session = Depends(get_db)
):
    """Verify the effectiveness of a CAPA."""
    capa = db.query(CorrectiveActionDB).filter(
        (CorrectiveActionDB.id == capa_id) | (CorrectiveActionDB.capa_id == capa_id)
    ).first()

    if not capa:
        raise HTTPException(status_code=404, detail="CAPA not found")

    if capa.status != "completed":
        raise HTTPException(status_code=400, detail="CAPA must be completed before verification")

    capa.effectiveness_verified = data.is_effective
    capa.effectiveness_verification_date = date.today()
    capa.effectiveness_notes = data.effectiveness_notes
    capa.status = "verified" if data.is_effective else "completed"

    # If verified and all CAPAs for finding are verified, update finding status
    if data.is_effective:
        finding = db.query(AuditFindingDB).filter(AuditFindingDB.id == capa.finding_id).first()
        if finding:
            unverified = db.query(CorrectiveActionDB).filter(
                CorrectiveActionDB.finding_id == finding.id,
                CorrectiveActionDB.id != capa.id,
                CorrectiveActionDB.status != "verified"
            ).count()
            if unverified == 0:
                finding.status = FindingStatusEnum.VERIFICATION_PENDING

    log_audit_trail(db, "capa", capa.id, capa.capa_id, "verify", data.verified_by)
    db.commit()
    db.refresh(capa)

    return capa


# =============================================================================
# MANAGEMENT REVIEW (ISO 27001 9.3)
# =============================================================================

@router.get("/management-reviews", response_model=ManagementReviewListResponse)
async def list_management_reviews(
    status: Optional[str] = None,
    db: Session = Depends(get_db)
):
    """List all management reviews."""
    query = db.query(ManagementReviewDB)

    if status:
        query = query.filter(ManagementReviewDB.status == status)

    reviews = query.order_by(ManagementReviewDB.review_date.desc()).all()

    return ManagementReviewListResponse(reviews=reviews, total=len(reviews))


@router.post("/management-reviews", response_model=ManagementReviewResponse)
async def create_management_review(
    data: ManagementReviewCreate,
    created_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Create a new management review."""
    # Generate review ID
    year = data.review_date.year
    quarter = (data.review_date.month - 1) // 3 + 1
    review_id = f"MR-{year}-Q{quarter}"

    # Check for duplicate
    existing = db.query(ManagementReviewDB).filter(
        ManagementReviewDB.review_id == review_id
    ).first()
    if existing:
        review_id = f"{review_id}-{generate_id()[:4]}"

    review = ManagementReviewDB(
        id=generate_id(),
        review_id=review_id,
        title=data.title,
        review_date=data.review_date,
        review_period_start=data.review_period_start,
        review_period_end=data.review_period_end,
        chairperson=data.chairperson,
        attendees=[a.model_dump() for a in data.attendees] if data.attendees else None,
        status="draft"
    )
    db.add(review)

    log_audit_trail(db, "management_review", review.id, review_id, "create", created_by)
    db.commit()
    db.refresh(review)

    return review


@router.get("/management-reviews/{review_id}", response_model=ManagementReviewResponse)
async def get_management_review(review_id: str, db: Session = Depends(get_db)):
    """Get a specific management review."""
    review = db.query(ManagementReviewDB).filter(
        (ManagementReviewDB.id == review_id) | (ManagementReviewDB.review_id == review_id)
    ).first()

    if not review:
        raise HTTPException(status_code=404, detail="Management review not found")

    return review


@router.put("/management-reviews/{review_id}", response_model=ManagementReviewResponse)
async def update_management_review(
    review_id: str,
    data: ManagementReviewUpdate,
    updated_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Update a management review with inputs/outputs."""
    review = db.query(ManagementReviewDB).filter(
        (ManagementReviewDB.id == review_id) | (ManagementReviewDB.review_id == review_id)
    ).first()

    if not review:
        raise HTTPException(status_code=404, detail="Management review not found")

    for field, value in data.model_dump(exclude_unset=True).items():
        if field == "action_items" and value:
            setattr(review, field, [item.model_dump() for item in value])
        else:
            setattr(review, field, value)

    log_audit_trail(db, "management_review", review.id, review.review_id, "update", updated_by)
    db.commit()
    db.refresh(review)

    return review


@router.post("/management-reviews/{review_id}/approve", response_model=ManagementReviewResponse)
async def approve_management_review(
    review_id: str,
    data: ManagementReviewApproveRequest,
    db: Session = Depends(get_db)
):
    """Approve a management review."""
    review = db.query(ManagementReviewDB).filter(
        (ManagementReviewDB.id == review_id) | (ManagementReviewDB.review_id == review_id)
    ).first()

    if not review:
        raise HTTPException(status_code=404, detail="Management review not found")

    review.status = "approved"
    review.approved_by = data.approved_by
    review.approved_at = datetime.utcnow()
    review.next_review_date = data.next_review_date
    review.minutes_document_path = data.minutes_document_path

    log_audit_trail(db, "management_review", review.id, review.review_id, "approve", data.approved_by)
    db.commit()
    db.refresh(review)

    return review


# =============================================================================
# INTERNAL AUDIT (ISO 27001 9.2)
# =============================================================================

@router.get("/internal-audits", response_model=InternalAuditListResponse)
async def list_internal_audits(
    status: Optional[str] = None,
    audit_type: Optional[str] = None,
    db: Session = Depends(get_db)
):
    """List all internal audits."""
    query = db.query(InternalAuditDB)

    if status:
        query = query.filter(InternalAuditDB.status == status)
    if audit_type:
        query = query.filter(InternalAuditDB.audit_type == audit_type)

    audits = query.order_by(InternalAuditDB.planned_date.desc()).all()

    return InternalAuditListResponse(audits=audits, total=len(audits))


@router.post("/internal-audits", response_model=InternalAuditResponse)
async def create_internal_audit(
    data: InternalAuditCreate,
    created_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Create a new internal audit."""
    # Generate audit ID
    year = data.planned_date.year
    existing_count = db.query(InternalAuditDB).filter(
        InternalAuditDB.audit_id.like(f"IA-{year}-%")
    ).count()
    audit_id = f"IA-{year}-{existing_count + 1:03d}"

    audit = InternalAuditDB(
        id=generate_id(),
        audit_id=audit_id,
        title=data.title,
        audit_type=data.audit_type,
        scope_description=data.scope_description,
        iso_chapters_covered=data.iso_chapters_covered,
        annex_a_controls_covered=data.annex_a_controls_covered,
        processes_covered=data.processes_covered,
        departments_covered=data.departments_covered,
        criteria=data.criteria,
        planned_date=data.planned_date,
        lead_auditor=data.lead_auditor,
        audit_team=data.audit_team,
        status="planned"
    )
    db.add(audit)

    log_audit_trail(db, "internal_audit", audit.id, audit_id, "create", created_by)
    db.commit()
    db.refresh(audit)

    return audit


@router.put("/internal-audits/{audit_id}", response_model=InternalAuditResponse)
async def update_internal_audit(
    audit_id: str,
    data: InternalAuditUpdate,
    updated_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Update an internal audit."""
    audit = db.query(InternalAuditDB).filter(
        (InternalAuditDB.id == audit_id) | (InternalAuditDB.audit_id == audit_id)
    ).first()

    if not audit:
        raise HTTPException(status_code=404, detail="Internal audit not found")

    for field, value in data.model_dump(exclude_unset=True).items():
        setattr(audit, field, value)

    log_audit_trail(db, "internal_audit", audit.id, audit.audit_id, "update", updated_by)
    db.commit()
    db.refresh(audit)

    return audit


@router.post("/internal-audits/{audit_id}/complete", response_model=InternalAuditResponse)
async def complete_internal_audit(
    audit_id: str,
    data: InternalAuditCompleteRequest,
    completed_by: str = Query(...),
    db: Session = Depends(get_db)
):
    """Complete an internal audit with conclusion."""
    audit = db.query(InternalAuditDB).filter(
        (InternalAuditDB.id == audit_id) | (InternalAuditDB.audit_id == audit_id)
    ).first()

    if not audit:
        raise HTTPException(status_code=404, detail="Internal audit not found")

    audit.status = "completed"
    audit.actual_end_date = date.today()
    audit.report_date = date.today()
    audit.audit_conclusion = data.audit_conclusion
    audit.overall_assessment = data.overall_assessment
    audit.follow_up_audit_required = data.follow_up_audit_required

    log_audit_trail(db, "internal_audit", audit.id, audit.audit_id, "complete", completed_by)
    db.commit()
    db.refresh(audit)

    return audit


# =============================================================================
# ISMS READINESS CHECK
# =============================================================================

@router.post("/readiness-check", response_model=ISMSReadinessCheckResponse)
async def run_readiness_check(
    data: ISMSReadinessCheckRequest,
    db: Session = Depends(get_db)
):
    """
    Run ISMS readiness check.

    Identifies potential Major/Minor findings BEFORE external audit.
    This helps achieve ISO 27001 certification on the first attempt.
    """
    potential_majors = []
    potential_minors = []
    improvement_opportunities = []

    # Chapter 4: Context
    scope = db.query(ISMSScopeDB).filter(
        ISMSScopeDB.status == ApprovalStatusEnum.APPROVED
    ).first()
    if not scope:
        potential_majors.append(PotentialFinding(
            check="ISMS Scope not approved",
            status="fail",
            recommendation="Approve ISMS scope with top management signature",
            iso_reference="4.3"
        ))

    context = db.query(ISMSContextDB).filter(
        ISMSContextDB.status == ApprovalStatusEnum.APPROVED
    ).first()
    if not context:
        potential_majors.append(PotentialFinding(
            check="ISMS Context not documented",
            status="fail",
            recommendation="Document and approve context analysis (4.1, 4.2)",
            iso_reference="4.1, 4.2"
        ))

    # Chapter 5: Leadership
    master_policy = db.query(ISMSPolicyDB).filter(
        ISMSPolicyDB.policy_type == "master",
        ISMSPolicyDB.status == ApprovalStatusEnum.APPROVED
    ).first()
    if not master_policy:
        potential_majors.append(PotentialFinding(
            check="Information Security Policy not approved",
            status="fail",
            recommendation="Create and approve master ISMS policy",
            iso_reference="5.2"
        ))

    # Chapter 6: Planning - Risk Assessment
    from ..db.models import RiskDB
    risks = db.query(RiskDB).filter(RiskDB.status == "open").count()
    risks_without_treatment = db.query(RiskDB).filter(
        RiskDB.status == "open",
        RiskDB.treatment_plan == None
    ).count()
    if risks_without_treatment > 0:
        potential_majors.append(PotentialFinding(
            check=f"{risks_without_treatment} risks without treatment plan",
            status="fail",
            recommendation="Define risk treatment for all identified risks",
            iso_reference="6.1.2"
        ))

    # Chapter 6: Objectives
    objectives = db.query(SecurityObjectiveDB).filter(
        SecurityObjectiveDB.status == "active"
    ).count()
    if objectives == 0:
        potential_majors.append(PotentialFinding(
            check="No security objectives defined",
            status="fail",
            recommendation="Define measurable security objectives",
            iso_reference="6.2"
        ))

    # SoA
    soa_total = db.query(StatementOfApplicabilityDB).count()
    soa_unapproved = db.query(StatementOfApplicabilityDB).filter(
        StatementOfApplicabilityDB.approved_at == None
    ).count()
    if soa_total == 0:
        potential_majors.append(PotentialFinding(
            check="Statement of Applicability not created",
            status="fail",
            recommendation="Create SoA for all 93 Annex A controls",
            iso_reference="Annex A"
        ))
    elif soa_unapproved > 0:
        potential_minors.append(PotentialFinding(
            check=f"{soa_unapproved} SoA entries not approved",
            status="warning",
            recommendation="Review and approve all SoA entries",
            iso_reference="Annex A"
        ))

    # Chapter 9: Internal Audit
    last_year = date.today().replace(year=date.today().year - 1)
    internal_audit = db.query(InternalAuditDB).filter(
        InternalAuditDB.status == "completed",
        InternalAuditDB.actual_end_date >= last_year
    ).first()
    if not internal_audit:
        potential_majors.append(PotentialFinding(
            check="No internal audit in last 12 months",
            status="fail",
            recommendation="Conduct internal audit before certification",
            iso_reference="9.2"
        ))

    # Chapter 9: Management Review
    mgmt_review = db.query(ManagementReviewDB).filter(
        ManagementReviewDB.status == "approved",
        ManagementReviewDB.review_date >= last_year
    ).first()
    if not mgmt_review:
        potential_majors.append(PotentialFinding(
            check="No management review in last 12 months",
            status="fail",
            recommendation="Conduct and approve management review",
            iso_reference="9.3"
        ))

    # Chapter 10: Open Findings
    open_majors = db.query(AuditFindingDB).filter(
        AuditFindingDB.finding_type == FindingTypeEnum.MAJOR,
        AuditFindingDB.status != FindingStatusEnum.CLOSED
    ).count()
    if open_majors > 0:
        potential_majors.append(PotentialFinding(
            check=f"{open_majors} open major finding(s)",
            status="fail",
            recommendation="Close all major findings before certification",
            iso_reference="10.1"
        ))

    open_minors = db.query(AuditFindingDB).filter(
        AuditFindingDB.finding_type == FindingTypeEnum.MINOR,
        AuditFindingDB.status != FindingStatusEnum.CLOSED
    ).count()
    if open_minors > 0:
        potential_minors.append(PotentialFinding(
            check=f"{open_minors} open minor finding(s)",
            status="warning",
            recommendation="Address minor findings or have CAPA in progress",
            iso_reference="10.1"
        ))

    # Calculate scores
    total_checks = 10
    passed_checks = total_checks - len(potential_majors)
    readiness_score = (passed_checks / total_checks) * 100

    # Determine overall status
    certification_possible = len(potential_majors) == 0
    if certification_possible:
        overall_status = "ready" if len(potential_minors) == 0 else "at_risk"
    else:
        overall_status = "not_ready"

    # Determine chapter statuses
    def get_chapter_status(has_major: bool, has_minor: bool) -> str:
        if has_major:
            return "fail"
        elif has_minor:
            return "warning"
        return "pass"

    chapter_4_majors = any("4." in (f.iso_reference or "") for f in potential_majors)
    chapter_5_majors = any("5." in (f.iso_reference or "") for f in potential_majors)
    chapter_6_majors = any("6." in (f.iso_reference or "") for f in potential_majors)
    chapter_9_majors = any("9." in (f.iso_reference or "") for f in potential_majors)
    chapter_10_majors = any("10." in (f.iso_reference or "") for f in potential_majors)

    # Priority actions
    priority_actions = [f.recommendation for f in potential_majors[:5]]

    # Save check result
    check = ISMSReadinessCheckDB(
        id=generate_id(),
        check_date=datetime.utcnow(),
        triggered_by=data.triggered_by,
        overall_status=overall_status,
        certification_possible=certification_possible,
        chapter_4_status=get_chapter_status(chapter_4_majors, False),
        chapter_5_status=get_chapter_status(chapter_5_majors, False),
        chapter_6_status=get_chapter_status(chapter_6_majors, False),
        chapter_7_status="pass",  # Support - typically ok
        chapter_8_status="pass",  # Operation - checked via controls
        chapter_9_status=get_chapter_status(chapter_9_majors, False),
        chapter_10_status=get_chapter_status(chapter_10_majors, False),
        potential_majors=[f.model_dump() for f in potential_majors],
        potential_minors=[f.model_dump() for f in potential_minors],
        improvement_opportunities=[f.model_dump() for f in improvement_opportunities],
        readiness_score=readiness_score,
        priority_actions=priority_actions
    )
    db.add(check)
    db.commit()
    db.refresh(check)

    return ISMSReadinessCheckResponse(
        id=check.id,
        check_date=check.check_date,
        triggered_by=check.triggered_by,
        overall_status=check.overall_status,
        certification_possible=check.certification_possible,
        chapter_4_status=check.chapter_4_status,
        chapter_5_status=check.chapter_5_status,
        chapter_6_status=check.chapter_6_status,
        chapter_7_status=check.chapter_7_status,
        chapter_8_status=check.chapter_8_status,
        chapter_9_status=check.chapter_9_status,
        chapter_10_status=check.chapter_10_status,
        potential_majors=potential_majors,
        potential_minors=potential_minors,
        improvement_opportunities=improvement_opportunities,
        readiness_score=check.readiness_score,
        documentation_score=None,
        implementation_score=None,
        evidence_score=None,
        priority_actions=priority_actions
    )


@router.get("/readiness-check/latest", response_model=ISMSReadinessCheckResponse)
async def get_latest_readiness_check(db: Session = Depends(get_db)):
    """Get the most recent readiness check result."""
    check = db.query(ISMSReadinessCheckDB).order_by(
        ISMSReadinessCheckDB.check_date.desc()
    ).first()

    if not check:
        raise HTTPException(status_code=404, detail="No readiness check found. Run one first.")

    return check


# =============================================================================
# AUDIT TRAIL
# =============================================================================

@router.get("/audit-trail", response_model=AuditTrailResponse)
async def get_audit_trail(
    entity_type: Optional[str] = None,
    entity_id: Optional[str] = None,
    performed_by: Optional[str] = None,
    action: Optional[str] = None,
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=200),
    db: Session = Depends(get_db)
):
    """Query the audit trail with filters."""
    query = db.query(AuditTrailDB)

    if entity_type:
        query = query.filter(AuditTrailDB.entity_type == entity_type)
    if entity_id:
        query = query.filter(AuditTrailDB.entity_id == entity_id)
    if performed_by:
        query = query.filter(AuditTrailDB.performed_by == performed_by)
    if action:
        query = query.filter(AuditTrailDB.action == action)

    total = query.count()

    entries = query.order_by(AuditTrailDB.performed_at.desc()).offset(
        (page - 1) * page_size
    ).limit(page_size).all()

    total_pages = (total + page_size - 1) // page_size

    return AuditTrailResponse(
        entries=entries,
        total=total,
        pagination=PaginationMeta(
            page=page,
            page_size=page_size,
            total=total,
            total_pages=total_pages,
            has_next=page < total_pages,
            has_prev=page > 1
        )
    )


# =============================================================================
# ISO 27001 OVERVIEW
# =============================================================================

@router.get("/overview", response_model=ISO27001OverviewResponse)
async def get_iso27001_overview(db: Session = Depends(get_db)):
    """
    Get complete ISO 27001 compliance overview.

    Shows status of all chapters, key metrics, and readiness for certification.
    """
    # Scope & SoA approval status
    scope = db.query(ISMSScopeDB).filter(
        ISMSScopeDB.status == ApprovalStatusEnum.APPROVED
    ).first()
    scope_approved = scope is not None

    soa_total = db.query(StatementOfApplicabilityDB).count()
    soa_approved = db.query(StatementOfApplicabilityDB).filter(
        StatementOfApplicabilityDB.approved_at != None
    ).count()
    soa_all_approved = soa_total > 0 and soa_approved == soa_total

    # Management Review & Internal Audit
    last_year = date.today().replace(year=date.today().year - 1)

    last_mgmt_review = db.query(ManagementReviewDB).filter(
        ManagementReviewDB.status == "approved"
    ).order_by(ManagementReviewDB.review_date.desc()).first()

    last_internal_audit = db.query(InternalAuditDB).filter(
        InternalAuditDB.status == "completed"
    ).order_by(InternalAuditDB.actual_end_date.desc()).first()

    # Findings
    open_majors = db.query(AuditFindingDB).filter(
        AuditFindingDB.finding_type == FindingTypeEnum.MAJOR,
        AuditFindingDB.status != FindingStatusEnum.CLOSED
    ).count()

    open_minors = db.query(AuditFindingDB).filter(
        AuditFindingDB.finding_type == FindingTypeEnum.MINOR,
        AuditFindingDB.status != FindingStatusEnum.CLOSED
    ).count()

    # Policies
    policies_total = db.query(ISMSPolicyDB).count()
    policies_approved = db.query(ISMSPolicyDB).filter(
        ISMSPolicyDB.status == ApprovalStatusEnum.APPROVED
    ).count()

    # Objectives
    objectives_total = db.query(SecurityObjectiveDB).count()
    objectives_achieved = db.query(SecurityObjectiveDB).filter(
        SecurityObjectiveDB.status == "achieved"
    ).count()

    # Calculate readiness
    readiness_factors = [
        scope_approved,
        soa_all_approved,
        last_mgmt_review is not None and last_mgmt_review.review_date >= last_year,
        last_internal_audit is not None and (last_internal_audit.actual_end_date or date.min) >= last_year,
        open_majors == 0,
        policies_total > 0 and policies_approved >= policies_total * 0.8,
        objectives_total > 0
    ]
    certification_readiness = sum(readiness_factors) / len(readiness_factors) * 100

    # Overall status
    if open_majors > 0:
        overall_status = "not_ready"
    elif certification_readiness >= 80:
        overall_status = "ready"
    else:
        overall_status = "at_risk"

    # Build chapter status list
    chapters = [
        ISO27001ChapterStatus(
            chapter="4",
            title="Kontext der Organisation",
            status="compliant" if scope_approved else "non_compliant",
            completion_percentage=100.0 if scope_approved else 0.0,
            open_findings=0,
            key_documents=["ISMS Scope", "Context Analysis"] if scope_approved else [],
            last_reviewed=scope.approved_at if scope else None
        ),
        ISO27001ChapterStatus(
            chapter="5",
            title="Führung",
            status="compliant" if policies_approved > 0 else "non_compliant",
            completion_percentage=(policies_approved / max(policies_total, 1)) * 100,
            open_findings=0,
            key_documents=[f"Policy {i+1}" for i in range(min(policies_approved, 3))],
            last_reviewed=None
        ),
        ISO27001ChapterStatus(
            chapter="6",
            title="Planung",
            status="compliant" if objectives_total > 0 else "partial",
            completion_percentage=75.0 if objectives_total > 0 else 25.0,
            open_findings=0,
            key_documents=["Risk Register", "Security Objectives"],
            last_reviewed=None
        ),
        ISO27001ChapterStatus(
            chapter="9",
            title="Bewertung der Leistung",
            status="compliant" if (last_mgmt_review and last_internal_audit) else "non_compliant",
            completion_percentage=100.0 if (last_mgmt_review and last_internal_audit) else 50.0,
            open_findings=open_majors + open_minors,
            key_documents=["Internal Audit Report", "Management Review Minutes"],
            last_reviewed=last_mgmt_review.approved_at if last_mgmt_review else None
        ),
        ISO27001ChapterStatus(
            chapter="10",
            title="Verbesserung",
            status="compliant" if open_majors == 0 else "non_compliant",
            completion_percentage=100.0 if open_majors == 0 else 50.0,
            open_findings=open_majors,
            key_documents=["CAPA Register"],
            last_reviewed=None
        )
    ]

    return ISO27001OverviewResponse(
        overall_status=overall_status,
        certification_readiness=certification_readiness,
        chapters=chapters,
        scope_approved=scope_approved,
        soa_approved=soa_all_approved,
        last_management_review=last_mgmt_review.approved_at if last_mgmt_review else None,
        last_internal_audit=datetime.combine(last_internal_audit.actual_end_date, datetime.min.time()) if last_internal_audit and last_internal_audit.actual_end_date else None,
        open_major_findings=open_majors,
        open_minor_findings=open_minors,
        policies_count=policies_total,
        policies_approved=policies_approved,
        objectives_count=objectives_total,
        objectives_achieved=objectives_achieved
    )
