"""
Pydantic Models for Time Tracking Module
=========================================

Alle models repræsenterer data fra tmodule_* tabeller.
Ingen afhængigheder til eksisterende Hub-models.
"""

from datetime import date, datetime
from decimal import Decimal
from typing import List, Optional
from pydantic import BaseModel, Field, field_validator


# ============================================================================
# KUNDE MODELS
# ============================================================================

class TModuleCustomerBase(BaseModel):
    """Base model for customer"""
    vtiger_id: str = Field(..., description="vTiger Account ID")
    name: str = Field(..., min_length=1, max_length=255)
    email: Optional[str] = Field(None, max_length=255)
    hourly_rate: Optional[Decimal] = Field(None, ge=0, description="DKK pr. time")
    hub_customer_id: Optional[int] = Field(None, description="Reference til customers.id (read-only)")


class TModuleCustomerCreate(TModuleCustomerBase):
    """Model for creating a customer"""
    vtiger_data: Optional[dict] = Field(default_factory=dict)


class TModuleBulkRateUpdate(BaseModel):
    """Model for bulk customer hourly rate update"""
    customer_ids: List[int] = Field(..., min_length=1, description="List of customer IDs to update")
    hourly_rate: Decimal = Field(..., ge=0, description="New hourly rate in DKK")


class TModuleCustomer(TModuleCustomerBase):
    """Full customer model with DB fields"""
    id: int
    sync_hash: Optional[str] = None
    created_at: datetime
    updated_at: Optional[datetime] = None
    last_synced_at: datetime
    
    class Config:
        from_attributes = True


# ============================================================================
# CASE MODELS
# ============================================================================

class TModuleCaseBase(BaseModel):
    """Base model for case/project"""
    vtiger_id: str = Field(..., description="vTiger HelpDesk/ProjectTask ID")
    customer_id: int = Field(..., gt=0)
    title: str = Field(..., min_length=1, max_length=500)
    description: Optional[str] = None
    status: Optional[str] = Field(None, max_length=50)
    priority: Optional[str] = Field(None, max_length=50)
    module_type: Optional[str] = Field(None, max_length=50, description="HelpDesk, ProjectTask, etc.")


class TModuleCaseCreate(TModuleCaseBase):
    """Model for creating a case"""
    vtiger_data: Optional[dict] = Field(default_factory=dict)


class TModuleCase(TModuleCaseBase):
    """Full case model with DB fields"""
    id: int
    sync_hash: Optional[str] = None
    created_at: datetime
    updated_at: Optional[datetime] = None
    last_synced_at: datetime
    
    class Config:
        from_attributes = True


# ============================================================================
# TIDSREGISTRERING MODELS
# ============================================================================

class TModuleTimeBase(BaseModel):
    """Base model for time entry"""
    vtiger_id: Optional[str] = Field(None, description="vTiger ModComments ID (Optional)")
    case_id: Optional[int] = Field(None, gt=0, description="vTiger Case ID (Optional)")
    sag_id: Optional[int] = Field(None, gt=0, description="Hub Sag ID (Optional)")
    solution_id: Optional[int] = Field(None, gt=0, description="Hub Solution ID (Optional)")
    customer_id: int = Field(..., gt=0)
    description: Optional[str] = None
    original_hours: Decimal = Field(..., gt=0, description="Original timer")
    worked_date: Optional[date] = None
    user_name: Optional[str] = Field(None, max_length=255, description="Bruger")
    start_tid: Optional[datetime] = Field(None, description="Starttid for live timer")
    slut_tid: Optional[datetime] = Field(None, description="Sluttid for live timer")
    faktisk_tid_min: Optional[int] = Field(None, ge=0, description="Reel tid i minutter")
    fakturerbar_tid_min: Optional[int] = Field(None, ge=0, description="Fakturerbar tid i minutter")
    entry_type: Optional[str] = Field("ukendt", pattern="^(opkald|mail|anydesk|indedesk|manuel|ukendt)$")
    kilde: Optional[str] = Field("manuel", pattern="^(auto|manuel|api)$")
    entry_status: Optional[str] = Field("afventer", pattern="^(kladde|afventer|godkendt)$")
    medarbejder_id: Optional[int] = Field(None, gt=0)
    aktiv_timer: Optional[bool] = False
    round_block_min: Optional[int] = Field(30, ge=1, le=240)
    ikke_placeret: Optional[bool] = False


class TModuleTimeCreate(TModuleTimeBase):
    """Model for creating a time entry"""
    vtiger_data: Optional[dict] = Field(default_factory=dict)


class TModuleTimeUpdate(BaseModel):
    """Model for updating time entry (godkendelse)"""
    approved_hours: Optional[Decimal] = Field(None, gt=0)
    rounded_to: Optional[Decimal] = Field(None, ge=0.25, description="Afrundingsinterval")
    approval_note: Optional[str] = None
    billable: Optional[bool] = None
    is_travel: Optional[bool] = None
    status: Optional[str] = Field(None, pattern="^(pending|approved|rejected|billed)$")
    entry_status: Optional[str] = Field(None, pattern="^(kladde|afventer|godkendt)$")
    fakturerbar_tid_min: Optional[int] = Field(None, ge=0)
    entry_type: Optional[str] = Field(None, pattern="^(opkald|mail|anydesk|indedesk|manuel|ukendt)$")


class TModuleTimeApproval(BaseModel):
    """Model for wizard approval action"""
    time_id: int = Field(..., gt=0)
    approved_hours: Decimal = Field(..., gt=0, description="Timer efter godkendelse")
    rounded_to: Optional[Decimal] = Field(None, description="Afrundingsinterval brugt (0.25, 0.5, 1.0)")
    approval_note: Optional[str] = Field(None, description="Brugerens note")
    billable: bool = Field(True, description="Skal faktureres?")
    is_travel: bool = Field(False, description="Indeholder kørsel?")
    
    @field_validator('approved_hours')
    @classmethod
    def validate_approved_hours(cls, v: Decimal) -> Decimal:
        if v <= 0:
            raise ValueError("Approved hours must be positive")
        # Max 24 timer pr. dag er rimeligt
        if v > 24:
            raise ValueError("Approved hours cannot exceed 24 per entry")
        return v


class TModuleTime(TModuleTimeBase):
    """Full time entry model with DB fields"""
    id: int
    status: str = Field("pending", pattern="^(pending|approved|rejected|billed)$")
    approved_hours: Optional[Decimal] = None
    rounded_to: Optional[Decimal] = None
    approval_note: Optional[str] = None
    billable: bool = True
    is_travel: bool = False
    approved_at: Optional[datetime] = None
    approved_by: Optional[int] = None
    billed_via_thehub_id: Optional[int] = Field(None, description="Hub order ID this time was billed through")
    sync_hash: Optional[str] = None
    created_at: datetime
    updated_at: Optional[datetime] = None
    last_synced_at: datetime
    
    class Config:
        from_attributes = True


class TModuleTimeWithContext(TModuleTime):
    """Time entry with case and customer context (for wizard)"""
    case_title: str
    case_description: Optional[str] = None
    case_status: Optional[str] = None
    case_vtiger_id: Optional[str] = None
    case_vtiger_data: Optional[dict] = None
    customer_name: str
    customer_rate: Optional[Decimal] = None
    contact_name: Optional[str] = None
    contact_company: Optional[str] = None


# ============================================================================
# ORDRE MODELS
# ============================================================================

class TModuleOrderLineBase(BaseModel):
    """Base model for order line"""
    line_number: int = Field(..., gt=0)
    description: str = Field(..., min_length=1)
    quantity: Decimal = Field(..., gt=0, description="Timer")
    unit_price: Decimal = Field(..., ge=0, description="DKK pr. time")
    line_total: Decimal = Field(..., ge=0, description="Total for linje")
    case_id: Optional[int] = Field(None, gt=0)
    sag_id: Optional[int] = Field(None, gt=0)
    time_entry_ids: List[int] = Field(default_factory=list)
    product_number: Optional[str] = Field(None, max_length=50)
    case_contact: Optional[str] = Field(None, max_length=255)
    time_date: Optional[date] = None
    is_travel: bool = False
    account_number: Optional[str] = Field(None, max_length=50)


class TModuleOrderLineCreate(TModuleOrderLineBase):
    """Model for creating order line"""
    pass


class TModuleOrderLine(TModuleOrderLineBase):
    """Full order line model"""
    id: int
    order_id: int
    created_at: datetime
    case_contact: Optional[str] = None  # Contact name from case
    time_date: Optional[date] = None     # Date from time entries
    
    class Config:
        from_attributes = True


class TModuleOrderBase(BaseModel):
    """Base model for order"""
    customer_id: int = Field(..., gt=0)
    hub_customer_id: Optional[int] = Field(None, gt=0)
    order_date: date = Field(default_factory=date.today)
    total_hours: Decimal = Field(0, ge=0)
    hourly_rate: Decimal = Field(..., gt=0, description="DKK pr. time")
    subtotal: Decimal = Field(0, ge=0)
    vat_rate: Decimal = Field(Decimal("25.00"), ge=0, le=100, description="Moms %")
    vat_amount: Decimal = Field(0, ge=0)
    total_amount: Decimal = Field(0, ge=0)
    notes: Optional[str] = None


class TModuleOrderCreate(TModuleOrderBase):
    """Model for creating order"""
    lines: List[TModuleOrderLineCreate] = Field(default_factory=list)


class TModuleOrderUpdate(BaseModel):
    """Model for updating order"""
    status: Optional[str] = Field(None, pattern="^(draft|exported|posted|sent|cancelled)$")
    notes: Optional[str] = None


class TModuleOrder(TModuleOrderBase):
    """Full order model with DB fields"""
    id: int
    order_number: Optional[str] = None
    customer_name: Optional[str] = None  # From JOIN med customers table
    status: str = Field("draft", pattern="^(draft|exported|posted|sent|cancelled)$")
    economic_draft_id: Optional[int] = None
    economic_order_number: Optional[str] = None
    exported_at: Optional[datetime] = None
    exported_by: Optional[int] = None
    created_at: datetime
    updated_at: Optional[datetime] = None
    created_by: Optional[int] = None
    line_count: Optional[int] = Field(None, ge=0)
    
    class Config:
        from_attributes = True


class TModuleOrderWithLines(TModuleOrder):
    """Order with lines included"""
    lines: List[TModuleOrderLine] = Field(default_factory=list)


class TModuleOrderDetails(BaseModel):
    """Order details from view (aggregated data)"""
    order_id: int
    order_number: Optional[str] = None
    order_date: date
    order_status: str
    total_hours: Decimal
    total_amount: Decimal
    economic_draft_id: Optional[int] = None
    customer_name: str
    customer_vtiger_id: str
    line_count: int
    time_entry_count: int
    
    class Config:
        from_attributes = True


# ============================================================================
# STATISTIK & WIZARD MODELS
# ============================================================================

class TModuleApprovalStats(BaseModel):
    """Approval statistics per customer (from view)"""
    customer_id: int
    hub_customer_id: Optional[int] = None
    customer_name: str
    customer_vtiger_id: str
    uses_time_card: bool = False
    total_entries: int
    pending_count: int
    approved_count: int
    rejected_count: int
    billed_count: int
    total_original_hours: Optional[Decimal] = None
    total_approved_hours: Optional[Decimal] = None
    latest_work_date: Optional[date] = None
    last_sync: Optional[datetime] = None
    
    class Config:
        from_attributes = True


class TModuleWizardProgress(BaseModel):
    """Progress for wizard flow"""
    customer_id: int
    customer_name: str
    total_entries: int
    approved_entries: int
    pending_entries: int
    rejected_entries: int
    current_case_id: Optional[int] = None
    current_case_title: Optional[str] = None
    progress_percent: float = Field(0, ge=0, le=100)
    
    @field_validator('progress_percent', mode='before')
    @classmethod
    def calculate_progress(cls, v, info):
        """Auto-calculate progress if not provided"""
        if v == 0 and 'total_entries' in info.data and info.data['total_entries'] > 0:
            approved = info.data.get('approved_entries', 0)
            rejected = info.data.get('rejected_entries', 0)
            total = info.data['total_entries']
            return round(((approved + rejected) / total) * 100, 2)
        return v


class TModuleWizardEditRequest(BaseModel):
    """Request model for editing a time entry via Wizard"""
    description: Optional[str] = None
    original_hours: Optional[Decimal] = None # Editing raw hours before approval
    billing_method: Optional[str] = None # For Hub Worklogs (invoice, prepaid, etc)
    billable: Optional[bool] = None # For Module Times

class TModuleWizardNextEntry(BaseModel):
    """Next entry for wizard approval"""
    has_next: bool
    time_entry: Optional[TModuleTimeWithContext] = None
    progress: Optional[TModuleWizardProgress] = None


# ============================================================================
# SYNC & AUDIT MODELS
# ============================================================================

class TModuleSyncStats(BaseModel):
    """Statistics from sync operation"""
    customers_imported: int = 0
    customers_updated: int = 0
    customers_skipped: int = 0
    cases_imported: int = 0
    cases_updated: int = 0
    cases_skipped: int = 0
    times_imported: int = 0
    times_updated: int = 0
    times_skipped: int = 0
    errors: int = 0
    duration_seconds: float = 0.0
    started_at: datetime
    completed_at: Optional[datetime] = None


class TModuleSyncLogCreate(BaseModel):
    """Model for creating audit log entry"""
    event_type: str = Field(..., max_length=50)
    entity_type: Optional[str] = Field(None, max_length=50)
    entity_id: Optional[int] = None
    user_id: Optional[int] = None
    details: Optional[dict] = Field(default_factory=dict)
    ip_address: Optional[str] = None
    user_agent: Optional[str] = None


class TModuleSyncLog(TModuleSyncLogCreate):
    """Full audit log model"""
    id: int
    created_at: datetime
    
    class Config:
        from_attributes = True


# ============================================================================
# e-conomic EXPORT MODELS
# ============================================================================

class TModuleEconomicExportRequest(BaseModel):
    """Request for exporting order to e-conomic"""
    order_id: int = Field(..., gt=0)
    force: bool = Field(False, description="Force export even if already exported")


class TModuleEconomicExportResult(BaseModel):
    """Result of e-conomic export"""
    success: bool
    dry_run: bool = False
    order_id: int
    economic_draft_id: Optional[int] = None
    economic_order_number: Optional[str] = None
    message: str
    details: Optional[dict] = None


# ============================================================================
# MODULE METADATA
# ============================================================================

class TModuleMetadata(BaseModel):
    """Module metadata"""
    id: int
    module_version: str
    installed_at: datetime
    installed_by: Optional[int] = None
    last_sync_at: Optional[datetime] = None
    is_active: bool
    settings: dict = Field(default_factory=dict)
    
    class Config:
        from_attributes = True


class TModuleUninstallRequest(BaseModel):
    """Request for module uninstall"""
    confirm: bool = Field(..., description="Must be True to proceed")
    delete_all_data: bool = Field(..., description="Confirm deletion of ALL module data")
    
    @field_validator('confirm')
    @classmethod
    def validate_confirm(cls, v: bool) -> bool:
        if not v:
            raise ValueError("You must confirm uninstall by setting confirm=True")
        return v
    
    @field_validator('delete_all_data')
    @classmethod
    def validate_delete(cls, v: bool) -> bool:
        if not v:
            raise ValueError("You must confirm data deletion by setting delete_all_data=True")
        return v


class TModuleUninstallResult(BaseModel):
    """Result of module uninstall"""
    success: bool
    message: str
    tables_dropped: List[str] = Field(default_factory=list)
    views_dropped: List[str] = Field(default_factory=list)
    functions_dropped: List[str] = Field(default_factory=list)
    rows_deleted: int = 0


# ============================================================================
# SERVICE CONTRACT MIGRATION WIZARD MODELS
# ============================================================================

class ServiceContractBase(BaseModel):
    """Base service contract model"""
    id: str = Field(..., description="vTiger service contract ID")
    contract_number: str
    subject: str
    account_id: str = Field(..., description="vTiger account ID")


class ServiceContractItem(BaseModel):
    """Single item (case or timelog) to process in wizard"""
    type: str = Field(..., description="'case' or 'timelog'")
    id: str = Field(..., description="vTiger ID")
    title: str = Field(..., description="Display title")
    description: Optional[str] = None
    hours: Optional[Decimal] = None  # For timelogs only
    work_date: Optional[str] = None  # For timelogs only
    priority: Optional[str] = None  # For cases only
    status: Optional[str] = None
    raw_data: dict = Field(default_factory=dict)


class ServiceContractWizardData(BaseModel):
    """Complete contract data for wizard"""
    contract_id: str
    contract_number: str
    subject: str
    account_id: str
    account_name: Optional[str] = None
    customer_id: Optional[int] = None
    cases: List[dict] = Field(default_factory=list)
    timelogs: List[dict] = Field(default_factory=list)
    available_cards: List[dict] = Field(default_factory=list)
    total_items: int


class ServiceContractWizardAction(BaseModel):
    """Action result from a wizard step"""
    type: str = Field(..., description="'archive' or 'transfer'")
    item_id: str = Field(..., description="vTiger item ID")
    title: str
    success: bool
    message: str
    dry_run: bool
    result_id: Optional[int] = None  # ID of archived/transferred item in Hub
    timestamp: datetime = Field(default_factory=datetime.now)


class ServiceContractWizardSummary(BaseModel):
    """Summary of wizard execution"""
    contract_id: str
    contract_number: str
    subject: str
    dry_run: bool
    total_items_processed: int
    cases_archived: int
    timelogs_transferred: int
    failed_items: int
    status: str = Field(..., description="'completed' or 'completed_with_errors'")
    timestamp: datetime


class ServiceContractReportCustomer(BaseModel):
    """Customer selector payload for service contract report."""
    account_id: str
    account_name: str


class ServiceContractReportContract(BaseModel):
    """Service contract selector payload for report."""
    id: str
    contract_number: str = ""
    subject: str = ""
    contract_status: Optional[str] = None
    vtiger_url: str = ""


class ServiceContractReportTimelog(BaseModel):
    """Single timelog row in report."""
    id: str
    related_case_id: Optional[str] = None
    worked_date: Optional[str] = None
    user_name: Optional[str] = None
    employee_initials: str = ""
    description: str = ""
    status: Optional[str] = None
    billable: Optional[bool] = None
    hours: Decimal = Field(default=Decimal("0"), ge=0)
    vtiger_url: str = ""


class ServiceContractReportCase(BaseModel):
    """Case with nested timelogs for report display."""
    id: str
    cc_number: str = ""
    title: str
    description: str = ""
    contact_person: str = ""
    vtiger_url: str = ""
    status: Optional[str] = None
    priority: Optional[str] = None
    total_hours: Decimal = Field(default=Decimal("0"), ge=0)
    timelog_count: int = Field(default=0, ge=0)
    timelogs: List[ServiceContractReportTimelog] = Field(default_factory=list)


class ServiceContractReportSummary(BaseModel):
    """Computed totals for report footer/cards."""
    total_cases: int = Field(default=0, ge=0)
    open_cases: int = Field(default=0, ge=0)
    closed_cases: int = Field(default=0, ge=0)
    total_timelogs: int = Field(default=0, ge=0)
    total_hours: Decimal = Field(default=Decimal("0"), ge=0)


class ServiceContractReportData(BaseModel):
    """Complete report payload shared by web and PDF output."""
    customer: ServiceContractReportCustomer
    contract: ServiceContractReportContract
    cases: List[ServiceContractReportCase] = Field(default_factory=list)
    summary: ServiceContractReportSummary
    generated_at: datetime = Field(default_factory=datetime.utcnow)
    # Backward compatibility: older workers mistakenly expected wizard summary fields here.
    failed_items: int = 0
    status: Optional[str] = None
    timestamp: Optional[datetime] = None


class TimologTransferRequest(BaseModel):
    """Request to transfer single timelog to klippekort"""
    timelog_id: str = Field(..., description="vTiger timelog ID")
    card_id: int = Field(..., description="Hub klippekort card ID")
    customer_id: int = Field(..., description="Hub customer ID")
    contract_id: str = Field(..., description="Service contract ID for reference")
    dry_run: bool = Field(default=False)


class TimologTransferResult(BaseModel):
    """Result of timelog transfer"""
    success: bool
    message: str
    transaction_id: Optional[int] = None
    new_card_balance: Optional[Decimal] = None
    dry_run: bool
