"""Certificate inventory models for multi-cloud certificate discovery."""

from datetime import datetime, timezone
from enum import Enum
from typing import Any, Dict, List, Optional

from pydantic import BaseModel, Field, computed_field


class CertificateStatus(str, Enum):
    """Certificate lifecycle status."""

    ISSUED = "ISSUED"
    PENDING_VALIDATION = "PENDING_VALIDATION"
    INACTIVE = "INACTIVE"
    EXPIRED = "EXPIRED"
    REVOKED = "REVOKED"
    FAILED = "FAILED"
    VALIDATION_TIMED_OUT = "VALIDATION_TIMED_OUT"


class CertificateSource(str, Enum):
    """Where the certificate originates."""

    ACM = "ACM"
    IAM_SERVER_CERT = "IAM_SERVER_CERT"
    AZURE_KEY_VAULT = "AZURE_KEY_VAULT"
    THIRD_PARTY = "THIRD_PARTY"


class ExpiryBucket(str, Enum):
    """Risk-level classification based on days until expiry."""

    EXPIRED = "EXPIRED"
    CRITICAL_7D = "CRITICAL_7D"
    WARNING_30D = "WARNING_30D"
    ATTENTION_90D = "ATTENTION_90D"
    VALID = "VALID"


class ManagedBy(str, Enum):
    """Who manages certificate lifecycle."""

    DATACOM = "DATACOM"
    BLUECURRENT = "BLUECURRENT"
    AWS_AUTO_RENEW = "AWS_AUTO_RENEW"
    LETS_ENCRYPT = "LETS_ENCRYPT"
    UNKNOWN = "UNKNOWN"


class CertificateUsage(BaseModel):
    """A resource that uses this certificate."""

    resource_type: str = Field(..., description="ALB, NLB, Classic ELB, CloudFront, API Gateway")
    resource_arn: str = Field(default="")
    resource_name: str = Field(default="")
    listener_arn: Optional[str] = None


class CertificateRecord(BaseModel):
    """Core certificate record for the central registry."""

    certificate_arn: str
    domain_name: str
    subject_alternative_names: List[str] = Field(default_factory=list)
    account_id: str = ""
    account_name: str = ""
    region: str = "ap-southeast-2"
    source: CertificateSource = CertificateSource.ACM
    status: CertificateStatus = CertificateStatus.ISSUED
    issuer: str = ""
    key_algorithm: str = ""
    certificate_type: str = ""  # AMAZON_ISSUED, IMPORTED, PRIVATE
    not_before: Optional[datetime] = None
    not_after: Optional[datetime] = None
    in_use: bool = False
    usage: List[CertificateUsage] = Field(default_factory=list)
    auto_renewal_eligible: bool = False
    renewal_status: str = ""  # ACM RenewalSummary.RenewalStatus: SUCCESS, PENDING_AUTO_RENEWAL, FAILED, N/A
    owner_team: str = "UNKNOWN"
    managed_by: ManagedBy = ManagedBy.UNKNOWN
    tags: Dict[str, str] = Field(default_factory=dict)
    discovered_at: datetime = Field(default_factory=datetime.utcnow)

    @computed_field
    @property
    def days_until_expiry(self) -> Optional[int]:
        """Calculate days remaining until certificate expiry."""
        if self.not_after is None:
            return None
        now = datetime.now(timezone.utc)
        # Strip tzinfo from not_after if needed for comparison
        not_after = self.not_after.replace(tzinfo=None) if self.not_after.tzinfo else self.not_after
        now_naive = now.replace(tzinfo=None)
        delta = not_after - now_naive
        return delta.days

    @computed_field
    @property
    def expiry_bucket(self) -> ExpiryBucket:
        """Classify certificate into a risk bucket based on days until expiry."""
        days = self.days_until_expiry
        if days is None:
            return ExpiryBucket.VALID
        if days < 0:
            return ExpiryBucket.EXPIRED
        if days <= 7:
            return ExpiryBucket.CRITICAL_7D
        if days <= 30:
            return ExpiryBucket.WARNING_30D
        if days <= 90:
            return ExpiryBucket.ATTENTION_90D
        return ExpiryBucket.VALID


class CertificateInventorySummary(BaseModel):
    """Aggregated counts for reporting."""

    total_certificates: int = 0
    by_status: Dict[str, int] = Field(default_factory=dict)
    by_expiry_bucket: Dict[str, int] = Field(default_factory=dict)
    by_source: Dict[str, int] = Field(default_factory=dict)
    by_managed_by: Dict[str, int] = Field(default_factory=dict)
    in_use_count: int = 0
    unused_count: int = 0
    auto_renewal_eligible_count: int = 0
    accounts_scanned: int = 0
    accounts_failed: int = 0


class CertificateInventoryResult(BaseModel):
    """Complete inventory scan result."""

    certificates: List[CertificateRecord] = Field(default_factory=list)
    summary: CertificateInventorySummary = Field(default_factory=CertificateInventorySummary)
    scan_metadata: Dict[str, Any] = Field(default_factory=dict)

    def build_summary(self) -> CertificateInventorySummary:
        """Build summary from certificate list."""
        summary = CertificateInventorySummary()
        summary.total_certificates = len(self.certificates)
        for cert in self.certificates:
            # By status
            status_key = cert.status.value
            summary.by_status[status_key] = summary.by_status.get(status_key, 0) + 1
            # By expiry bucket
            bucket_key = cert.expiry_bucket.value
            summary.by_expiry_bucket[bucket_key] = summary.by_expiry_bucket.get(bucket_key, 0) + 1
            # By source
            source_key = cert.source.value
            summary.by_source[source_key] = summary.by_source.get(source_key, 0) + 1
            # By managed_by
            mgr_key = cert.managed_by.value
            summary.by_managed_by[mgr_key] = summary.by_managed_by.get(mgr_key, 0) + 1
            # Usage counts
            if cert.in_use:
                summary.in_use_count += 1
            else:
                summary.unused_count += 1
            if cert.auto_renewal_eligible:
                summary.auto_renewal_eligible_count += 1
        summary.accounts_scanned = len(set(c.account_id for c in self.certificates if c.account_id))
        self.summary = summary
        return summary
