"""
Fixed-Price Agreement Models
Pydantic schemas for API validation
"""
from typing import Optional, Literal
from pydantic import BaseModel, Field, field_validator, model_validator
from datetime import date, datetime
from decimal import Decimal


# Type aliases
PeriodType = Literal['calendar_month', 'rolling_30days', 'quarterly', 'yearly']
AgreementStatus = Literal['active', 'suspended', 'expired', 'cancelled', 'pending_cancellation']
BillingPeriodStatus = Literal['active', 'pending_approval', 'ready_to_bill', 'billed', 'cancelled']


class FixedPriceAgreementBase(BaseModel):
    """Base schema with common fields"""
    customer_id: int
    customer_name: Optional[str] = None
    monthly_hours: Decimal = Field(gt=0)
    monthly_amount: Optional[Decimal] = Field(default=None, ge=0)  # Fast månedspris
    hourly_rate: Optional[Decimal] = Field(default=None, ge=0)  # Beregnes fra monthly_amount hvis ikke givet
    overtime_rate: Decimal = Field(ge=0)
    internal_cost_rate: Decimal = Field(default=Decimal("350.00"), ge=0)
    rounding_minutes: int = Field(default=0, ge=0, le=60)
    notes: Optional[str] = None
    
    @field_validator('rounding_minutes')
    @classmethod
    def validate_rounding(cls, v: int) -> int:
        if v not in (0, 15, 30, 60):
            raise ValueError('rounding_minutes must be 0, 15, 30, or 60')
        return v
    
    @model_validator(mode='after')
    def compute_hourly_rate(self):
        """Beregn hourly_rate fra monthly_amount hvis ikke direkte angivet"""
        if self.hourly_rate is None:
            if self.monthly_amount is not None and self.monthly_hours:
                self.hourly_rate = self.monthly_amount / self.monthly_hours
            else:
                raise ValueError('Either hourly_rate or monthly_amount must be provided')
        return self


class FixedPriceAgreementCreate(FixedPriceAgreementBase):
    """Schema for creating new agreement"""
    subscription_id: Optional[int] = None
    
    # Contract terms
    start_date: date
    binding_months: int = Field(default=0, ge=0)
    end_date: Optional[date] = None
    notice_period_days: int = Field(default=30, ge=0)
    auto_renew: bool = False
    
    # e-conomic integration
    economic_product_number: Optional[str] = None
    economic_overtime_product_number: Optional[str] = None
    
    @field_validator('end_date')
    @classmethod
    def validate_end_date(cls, v: Optional[date], info) -> Optional[date]:
        if v and 'start_date' in info.data and v < info.data['start_date']:
            raise ValueError('end_date must be after start_date')
        return v


class FixedPriceAgreementUpdate(BaseModel):
    """Schema for updating existing agreement"""
    monthly_hours: Optional[Decimal] = Field(default=None, gt=0)
    hourly_rate: Optional[Decimal] = Field(default=None, ge=0)
    overtime_rate: Optional[Decimal] = Field(default=None, ge=0)
    internal_cost_rate: Optional[Decimal] = Field(default=None, ge=0)
    rounding_minutes: Optional[int] = Field(default=None, ge=0, le=60)
    end_date: Optional[date] = None
    notice_period_days: Optional[int] = Field(default=None, ge=0)
    auto_renew: Optional[bool] = None
    billing_enabled: Optional[bool] = None
    notes: Optional[str] = None
    
    @field_validator('rounding_minutes')
    @classmethod
    def validate_rounding(cls, v: Optional[int]) -> Optional[int]:
        if v is not None and v not in (0, 15, 30, 60):
            raise ValueError('rounding_minutes must be 0, 15, 30, or 60')
        return v


class FixedPriceAgreement(FixedPriceAgreementBase):
    """Full agreement response schema"""
    id: int
    agreement_number: str
    subscription_id: Optional[int]
    
    start_date: date
    binding_months: int
    binding_end_date: Optional[date]
    end_date: Optional[date]
    notice_period_days: int
    auto_renew: bool
    
    status: AgreementStatus
    cancellation_requested_date: Optional[date]
    cancellation_effective_date: Optional[date]
    cancelled_by_user_id: Optional[int]
    cancellation_reason: Optional[str]
    
    billing_enabled: bool
    last_billed_period: Optional[date]
    
    economic_product_number: Optional[str]
    economic_overtime_product_number: Optional[str]
    
    created_by_user_id: Optional[int]
    created_at: datetime
    updated_at: datetime
    
    class Config:
        from_attributes = True


class CancellationRequest(BaseModel):
    """Schema for agreement cancellation"""
    reason: str = Field(min_length=1)
    effective_date: Optional[date] = None
    force: bool = False  # Admin override for binding period
    
    @field_validator('reason')
    @classmethod
    def validate_reason(cls, v: str) -> str:
        if not v or not v.strip():
            raise ValueError('cancellation reason is required')
        return v.strip()


class BillingPeriodBase(BaseModel):
    """Base schema for billing periods"""
    agreement_id: int
    period_start: date
    period_end: date
    period_type: PeriodType = 'calendar_month'
    included_hours: Decimal = Field(gt=0)
    base_amount: Decimal = Field(ge=0)


class BillingPeriodCreate(BillingPeriodBase):
    """Schema for creating billing period"""
    pass


class BillingPeriod(BillingPeriodBase):
    """Full billing period response"""
    id: int
    used_hours: Decimal
    overtime_hours: Decimal
    remaining_hours: Decimal
    overtime_amount: Decimal
    overtime_approved: bool
    status: BillingPeriodStatus
    billed_at: Optional[datetime]
    economic_invoice_number: Optional[str]
    invoice_id: Optional[int]
    created_at: datetime
    updated_at: datetime
    
    class Config:
        from_attributes = True


class BillingPeriodApproval(BaseModel):
    """Schema for approving overtime"""
    overtime_hours: Decimal = Field(ge=0)
    approved: bool
    approved_by_user_id: Optional[int] = None
    notes: Optional[str] = None


class AgreementPerformance(BaseModel):
    """Schema for performance metrics"""
    id: int
    agreement_number: str
    customer_name: str
    status: AgreementStatus
    total_periods: int
    total_used_hours: Decimal
    total_revenue: Decimal
    total_internal_cost: Decimal
    total_profit: Decimal
    utilization_percent: Decimal
    
    class Config:
        from_attributes = True
