"""
Unified Inbox Mail Models

Pydantic models for API requests/responses and internal data structures.
Database schema is defined in mail_db.py.
"""

from datetime import datetime
from enum import Enum
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field, EmailStr
import uuid


# =============================================================================
# Enums
# =============================================================================

class AccountStatus(str, Enum):
    """Status of an email account connection."""
    ACTIVE = "active"
    INACTIVE = "inactive"
    ERROR = "error"
    PENDING = "pending"


class TaskStatus(str, Enum):
    """Status of an inbox task."""
    PENDING = "pending"
    IN_PROGRESS = "in_progress"
    COMPLETED = "completed"
    ARCHIVED = "archived"


class TaskPriority(str, Enum):
    """Priority level for tasks."""
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    URGENT = "urgent"


class EmailCategory(str, Enum):
    """AI-detected email categories."""
    DIENSTLICH = "dienstlich"           # Official government/authority
    PERSONAL = "personal"                # Staff/HR matters
    FINANZEN = "finanzen"               # Finance/budget
    ELTERN = "eltern"                   # Parent communication
    SCHUELER = "schueler"               # Student matters
    KOLLEGIUM = "kollegium"             # Teacher colleagues
    FORTBILDUNG = "fortbildung"         # Professional development
    VERANSTALTUNG = "veranstaltung"     # Events
    SICHERHEIT = "sicherheit"           # Safety/security
    TECHNIK = "technik"                 # IT/technical
    NEWSLETTER = "newsletter"           # Newsletters
    WERBUNG = "werbung"                 # Advertising/spam
    SONSTIGES = "sonstiges"             # Other


class SenderType(str, Enum):
    """Type of sender for classification."""
    KULTUSMINISTERIUM = "kultusministerium"
    LANDESSCHULBEHOERDE = "landesschulbehoerde"
    RLSB = "rlsb"                       # Regionales Landesamt für Schule und Bildung
    SCHULAMT = "schulamt"
    NIBIS = "nibis"
    SCHULTRAEGER = "schultraeger"
    ELTERNVERTRETER = "elternvertreter"
    GEWERKSCHAFT = "gewerkschaft"
    FORTBILDUNGSINSTITUT = "fortbildungsinstitut"
    PRIVATPERSON = "privatperson"
    UNTERNEHMEN = "unternehmen"
    UNBEKANNT = "unbekannt"


# =============================================================================
# Known Authority Domains (Niedersachsen)
# =============================================================================

KNOWN_AUTHORITIES_NI = {
    "@mk.niedersachsen.de": {"type": SenderType.KULTUSMINISTERIUM, "name": "Kultusministerium Niedersachsen"},
    "@rlsb.de": {"type": SenderType.RLSB, "name": "Regionales Landesamt für Schule und Bildung"},
    "@rlsb-bs.niedersachsen.de": {"type": SenderType.RLSB, "name": "RLSB Braunschweig"},
    "@rlsb-h.niedersachsen.de": {"type": SenderType.RLSB, "name": "RLSB Hannover"},
    "@rlsb-lg.niedersachsen.de": {"type": SenderType.RLSB, "name": "RLSB Lüneburg"},
    "@rlsb-os.niedersachsen.de": {"type": SenderType.RLSB, "name": "RLSB Osnabrück"},
    "@landesschulbehoerde-nds.de": {"type": SenderType.LANDESSCHULBEHOERDE, "name": "Landesschulbehörde"},
    "@nibis.de": {"type": SenderType.NIBIS, "name": "NiBiS"},
    "@schule.niedersachsen.de": {"type": SenderType.LANDESSCHULBEHOERDE, "name": "Schulnetzwerk NI"},
    "@nlq.nibis.de": {"type": SenderType.FORTBILDUNGSINSTITUT, "name": "NLQ"},
    "@gew-nds.de": {"type": SenderType.GEWERKSCHAFT, "name": "GEW Niedersachsen"},
    "@vbe-nds.de": {"type": SenderType.GEWERKSCHAFT, "name": "VBE Niedersachsen"},
}


# =============================================================================
# Email Account Models
# =============================================================================

class EmailAccountBase(BaseModel):
    """Base model for email account."""
    email: EmailStr = Field(..., description="Email address")
    display_name: str = Field(..., description="Display name for the account")
    account_type: str = Field("personal", description="Type: personal, schulleitung, personal, verwaltung")
    imap_host: str = Field(..., description="IMAP server hostname")
    imap_port: int = Field(993, description="IMAP port (default: 993 for SSL)")
    imap_ssl: bool = Field(True, description="Use SSL for IMAP")
    smtp_host: str = Field(..., description="SMTP server hostname")
    smtp_port: int = Field(465, description="SMTP port (default: 465 for SSL)")
    smtp_ssl: bool = Field(True, description="Use SSL for SMTP")


class EmailAccountCreate(EmailAccountBase):
    """Model for creating a new email account."""
    password: str = Field(..., description="Password (will be stored in Vault)")


class EmailAccountUpdate(BaseModel):
    """Model for updating an email account."""
    display_name: Optional[str] = None
    account_type: Optional[str] = None
    imap_host: Optional[str] = None
    imap_port: Optional[int] = None
    smtp_host: Optional[str] = None
    smtp_port: Optional[int] = None
    password: Optional[str] = None  # Only if changing


class EmailAccount(EmailAccountBase):
    """Full email account model (without password)."""
    id: str
    user_id: str
    tenant_id: str
    status: AccountStatus = AccountStatus.PENDING
    last_sync: Optional[datetime] = None
    sync_error: Optional[str] = None
    email_count: int = 0
    unread_count: int = 0
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


class AccountTestResult(BaseModel):
    """Result of testing email account connection."""
    success: bool
    imap_connected: bool = False
    smtp_connected: bool = False
    error_message: Optional[str] = None
    folders_found: List[str] = []


# =============================================================================
# Aggregated Email Models
# =============================================================================

class AggregatedEmailBase(BaseModel):
    """Base model for an aggregated email."""
    subject: str
    sender_email: str
    sender_name: Optional[str] = None
    recipients: List[str] = []
    cc: List[str] = []
    body_preview: Optional[str] = None
    has_attachments: bool = False


class AggregatedEmail(AggregatedEmailBase):
    """Full aggregated email model."""
    id: str
    account_id: str
    message_id: str  # Original IMAP message ID
    folder: str = "INBOX"
    is_read: bool = False
    is_starred: bool = False
    is_deleted: bool = False
    body_text: Optional[str] = None
    body_html: Optional[str] = None
    attachments: List[Dict[str, Any]] = []
    headers: Dict[str, str] = {}
    date_sent: datetime
    date_received: datetime

    # AI-enriched fields
    category: Optional[EmailCategory] = None
    sender_type: Optional[SenderType] = None
    sender_authority_name: Optional[str] = None
    detected_deadlines: List[Dict[str, Any]] = []
    suggested_priority: Optional[TaskPriority] = None
    ai_summary: Optional[str] = None

    created_at: datetime

    class Config:
        from_attributes = True


class EmailSearchParams(BaseModel):
    """Parameters for searching emails."""
    query: Optional[str] = None
    account_ids: Optional[List[str]] = None
    categories: Optional[List[EmailCategory]] = None
    is_read: Optional[bool] = None
    is_starred: Optional[bool] = None
    has_deadline: Optional[bool] = None
    date_from: Optional[datetime] = None
    date_to: Optional[datetime] = None
    limit: int = Field(50, ge=1, le=200)
    offset: int = Field(0, ge=0)


# =============================================================================
# Inbox Task Models (Arbeitsvorrat)
# =============================================================================

class TaskBase(BaseModel):
    """Base model for inbox task."""
    title: str = Field(..., description="Task title")
    description: Optional[str] = None
    priority: TaskPriority = TaskPriority.MEDIUM
    deadline: Optional[datetime] = None


class TaskCreate(TaskBase):
    """Model for creating a task manually."""
    email_id: Optional[str] = None  # Link to source email


class TaskUpdate(BaseModel):
    """Model for updating a task."""
    title: Optional[str] = None
    description: Optional[str] = None
    priority: Optional[TaskPriority] = None
    status: Optional[TaskStatus] = None
    deadline: Optional[datetime] = None
    completed_at: Optional[datetime] = None


class InboxTask(TaskBase):
    """Full inbox task model."""
    id: str
    user_id: str
    tenant_id: str
    email_id: Optional[str] = None
    account_id: Optional[str] = None
    status: TaskStatus = TaskStatus.PENDING

    # Source information
    source_email_subject: Optional[str] = None
    source_sender: Optional[str] = None
    source_sender_type: Optional[SenderType] = None

    # AI-extracted information
    ai_extracted: bool = False
    confidence_score: Optional[float] = None

    completed_at: Optional[datetime] = None
    reminder_at: Optional[datetime] = None
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


class TaskDashboardStats(BaseModel):
    """Dashboard statistics for tasks."""
    total_tasks: int = 0
    pending_tasks: int = 0
    in_progress_tasks: int = 0
    completed_tasks: int = 0
    overdue_tasks: int = 0
    due_today: int = 0
    due_this_week: int = 0
    by_priority: Dict[str, int] = {}
    by_sender_type: Dict[str, int] = {}


# =============================================================================
# AI Analysis Models
# =============================================================================

class SenderClassification(BaseModel):
    """Result of AI sender classification."""
    sender_type: SenderType
    authority_name: Optional[str] = None
    confidence: float = Field(..., ge=0, le=1)
    domain_matched: bool = False
    ai_classified: bool = False


class DeadlineExtraction(BaseModel):
    """Extracted deadline from email."""
    deadline_date: datetime
    description: str
    confidence: float = Field(..., ge=0, le=1)
    source_text: str  # Original text containing the deadline
    is_firm: bool = True  # True for "bis zum", False for "etwa"


class EmailAnalysisResult(BaseModel):
    """Complete AI analysis result for an email."""
    email_id: str
    category: EmailCategory
    category_confidence: float
    sender_classification: SenderClassification
    deadlines: List[DeadlineExtraction] = []
    suggested_priority: TaskPriority
    summary: Optional[str] = None
    suggested_actions: List[str] = []
    auto_create_task: bool = False


class ResponseSuggestion(BaseModel):
    """AI-generated response suggestion."""
    template_type: str  # "acknowledgment", "request_info", "delegation", etc.
    subject: str
    body: str
    confidence: float


# =============================================================================
# Email Template Models
# =============================================================================

class EmailTemplateBase(BaseModel):
    """Base model for email template."""
    name: str
    category: str  # "acknowledgment", "request", "forwarding", etc.
    subject_template: str
    body_template: str
    variables: List[str] = []  # e.g., ["sender_name", "deadline", "topic"]


class EmailTemplateCreate(EmailTemplateBase):
    """Model for creating a template."""
    pass


class EmailTemplate(EmailTemplateBase):
    """Full email template model."""
    id: str
    user_id: Optional[str] = None  # None = system template
    tenant_id: Optional[str] = None
    is_system: bool = False
    usage_count: int = 0
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


# =============================================================================
# Compose Email Models
# =============================================================================

class EmailComposeRequest(BaseModel):
    """Request to compose/send an email."""
    account_id: str = Field(..., description="Account to send from")
    to: List[EmailStr]
    cc: Optional[List[EmailStr]] = []
    bcc: Optional[List[EmailStr]] = []
    subject: str
    body: str
    is_html: bool = False
    reply_to_message_id: Optional[str] = None
    attachments: Optional[List[Dict[str, Any]]] = None


class EmailSendResult(BaseModel):
    """Result of sending an email."""
    success: bool
    message_id: Optional[str] = None
    error: Optional[str] = None


# =============================================================================
# Statistics & Health Models
# =============================================================================

class MailStats(BaseModel):
    """Overall mail system statistics."""
    total_accounts: int = 0
    active_accounts: int = 0
    error_accounts: int = 0
    total_emails: int = 0
    unread_emails: int = 0
    total_tasks: int = 0
    pending_tasks: int = 0
    overdue_tasks: int = 0
    emails_today: int = 0
    ai_analyses_today: int = 0
    per_account: List[Dict[str, Any]] = []


class MailHealthCheck(BaseModel):
    """Health check for mail system."""
    status: str  # "healthy", "degraded", "unhealthy"
    database_connected: bool = False
    vault_connected: bool = False
    accounts_checked: int = 0
    accounts_healthy: int = 0
    last_sync: Optional[datetime] = None
    errors: List[str] = []


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

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


def classify_sender_by_domain(email: str) -> Optional[SenderClassification]:
    """
    Classify sender by known authority domains.
    Returns None if domain is not recognized.
    """
    email_lower = email.lower()
    for domain, info in KNOWN_AUTHORITIES_NI.items():
        if domain in email_lower:
            return SenderClassification(
                sender_type=info["type"],
                authority_name=info["name"],
                confidence=0.95,
                domain_matched=True,
                ai_classified=False,
            )
    return None


def get_priority_from_sender_type(sender_type: SenderType) -> TaskPriority:
    """Get suggested priority based on sender type."""
    high_priority = {
        SenderType.KULTUSMINISTERIUM,
        SenderType.LANDESSCHULBEHOERDE,
        SenderType.RLSB,
        SenderType.SCHULAMT,
    }
    medium_priority = {
        SenderType.NIBIS,
        SenderType.SCHULTRAEGER,
        SenderType.ELTERNVERTRETER,
    }

    if sender_type in high_priority:
        return TaskPriority.HIGH
    elif sender_type in medium_priority:
        return TaskPriority.MEDIUM
    return TaskPriority.LOW
