"""
Fiscal Period Pydantic Schemas

Request/response schemas for fiscal year and period management API
"""

from datetime import date, datetime
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field, validator
from enum import Enum


# ==================== ENUMS ====================

class FiscalYearStatusEnum(str, Enum):
    """Fiscal year status"""
    DRAFT = "draft"
    OPEN = "open"
    CLOSED = "closed"
    ARCHIVED = "archived"


class PeriodStatusEnum(str, Enum):
    """Period status"""
    DRAFT = "draft"
    OPEN = "open"
    SOFT_CLOSED = "soft_closed"
    HARD_CLOSED = "hard_closed"
    LOCKED = "locked"


class PeriodTypeEnum(str, Enum):
    """Period type"""
    MONTHLY = "monthly"
    QUARTERLY = "quarterly"
    YEARLY = "yearly"
    CUSTOM = "custom"


# ==================== FISCAL YEAR SCHEMAS ====================

class FiscalYearCreate(BaseModel):
    """Schema for creating a fiscal year"""
    year_name: str = Field(..., description="Display name (e.g., 'FY 2025-2026')")
    year_code: str = Field(..., description="Short code (e.g., 'FY2025')")
    start_date: date = Field(..., description="First day of fiscal year")
    end_date: date = Field(..., description="Last day of fiscal year")
    period_type_default: PeriodTypeEnum = Field(
        default=PeriodTypeEnum.MONTHLY,
        description="Default period breakdown type"
    )
    auto_create_periods: bool = Field(
        default=True,
        description="Automatically create periods"
    )
    allow_backdated_transactions: bool = Field(
        default=False,
        description="Allow posting to previous periods"
    )
    branch_id: Optional[str] = Field(None, description="Branch ID (for multi-branch)")
    notes: Optional[str] = Field(None, description="Additional notes")

    @validator('start_date', 'end_date', pre=True)
    def parse_dates(cls, v):
        if isinstance(v, date):
            return v
        if isinstance(v, str):
            for fmt in ("%Y-%m-%d", "%d-%m-%Y", "%Y/%m/%d", "%d/%m/%Y"):
                try:
                    return datetime.strptime(v, fmt).date()
                except ValueError:
                    continue
        return v

    @validator('end_date')
    def validate_end_date(cls, v, values):
        if 'start_date' in values and v <= values['start_date']:
            raise ValueError(
                f"End date must be after start date (start={values['start_date']}, end={v})"
            )
        return v


class FiscalYearUpdate(BaseModel):
    """Schema for updating a fiscal year"""
    year_name: Optional[str] = None
    notes: Optional[str] = None
    allow_backdated_transactions: Optional[bool] = None


class FiscalYearResponse(BaseModel):
    """Schema for fiscal year response"""
    id: str
    year_name: str
    year_code: str
    start_date: date
    end_date: date
    status: FiscalYearStatusEnum
    is_active: bool
    period_type_default: PeriodTypeEnum
    auto_create_periods: bool
    allow_backdated_transactions: bool
    closed_date: Optional[datetime] = None
    archived_date: Optional[datetime] = None
    branch_id: Optional[str] = None
    notes: Optional[str] = None
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None

    class Config:
        from_attributes = True


class FiscalYearWithPeriods(FiscalYearResponse):
    """Fiscal year with its periods"""
    periods: List['FiscalPeriodResponse'] = []


# ==================== FISCAL PERIOD SCHEMAS ====================

class FiscalPeriodCreate(BaseModel):
    """Schema for manually creating a fiscal period"""
    fiscal_year_id: str
    period_name: str = Field(..., description="Display name (e.g., 'January 2025')")
    period_code: str = Field(..., description="Short code (e.g., '2025-01')")
    period_number: int = Field(..., description="Sequential number within year")
    period_type: PeriodTypeEnum = Field(
        default=PeriodTypeEnum.MONTHLY,
        description="Type of period"
    )
    start_date: date
    end_date: date
    branch_id: Optional[str] = None
    notes: Optional[str] = None

    @validator('end_date')
    def validate_end_date(cls, v, values):
        if 'start_date' in values and v <= values['start_date']:
            raise ValueError("End date must be after start date")
        return v


class FiscalPeriodUpdate(BaseModel):
    """Schema for updating a fiscal period"""
    period_name: Optional[str] = None
    notes: Optional[str] = None


class FiscalPeriodResponse(BaseModel):
    """Schema for fiscal period response"""
    id: str
    fiscal_year_id: str
    period_name: str
    period_code: str
    period_number: int
    period_type: PeriodTypeEnum
    start_date: date
    end_date: date
    status: PeriodStatusEnum
    is_locked: bool
    opened_date: Optional[datetime] = None
    soft_closed_date: Optional[datetime] = None
    hard_closed_date: Optional[datetime] = None
    locked_date: Optional[datetime] = None
    last_reopened_date: Optional[datetime] = None
    reopen_count: int = 0
    total_debits: Optional[float] = None
    total_credits: Optional[float] = None
    transaction_count: Optional[int] = None
    branch_id: Optional[str] = None
    notes: Optional[str] = None
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None

    class Config:
        from_attributes = True


class PeriodActionRequest(BaseModel):
    """Schema for period actions (open, close, lock, etc.)"""
    notes: Optional[str] = Field(None, description="Optional notes for the action")
    reason: Optional[str] = Field(None, description="Reason for action (for reopen/lock)")
    generate_statements: bool = Field(
        default=True,
        description="Generate financial statements (for hard close)"
    )


# ==================== PERIOD-END STATEMENT SCHEMAS ====================

class PeriodEndStatementResponse(BaseModel):
    """Schema for period-end statement response"""
    id: str
    fiscal_period_id: str
    fiscal_year_id: str
    statement_type: str
    statement_name: str
    statement_date: date
    generated_date: datetime
    total_assets: Optional[float] = None
    total_liabilities: Optional[float] = None
    total_equity: Optional[float] = None
    net_income: Optional[float] = None
    total_revenue: Optional[float] = None
    total_expenses: Optional[float] = None
    is_audited: bool = False
    audited_date: Optional[datetime] = None
    audited_by: Optional[str] = None
    branch_id: Optional[str] = None
    created_at: Optional[datetime] = None

    class Config:
        from_attributes = True


class PeriodEndStatementDetail(PeriodEndStatementResponse):
    """Detailed statement including data"""
    statement_data: Dict[str, Any]
    pdf_file_path: Optional[str] = None
    excel_file_path: Optional[str] = None
    audit_notes: Optional[str] = None
    notes: Optional[str] = None


class GenerateStatementsRequest(BaseModel):
    """Request to generate period-end statements"""
    statement_types: List[str] = Field(
        default=['trial_balance', 'income_statement', 'balance_sheet'],
        description="Types of statements to generate"
    )


# ==================== CHECKLIST SCHEMAS ====================

class ChecklistItem(BaseModel):
    """Individual checklist item"""
    task: str
    status: str = "pending"  # pending, completed, skipped
    required: bool = True
    order: int
    completed_by: Optional[str] = None
    completed_date: Optional[datetime] = None
    notes: Optional[str] = None


class PeriodCloseChecklistResponse(BaseModel):
    """Schema for period close checklist response"""
    id: str
    is_template: bool
    template_name: Optional[str] = None
    fiscal_period_id: Optional[str] = None
    checklist_items: List[Dict[str, Any]]
    total_items: int
    completed_items: int
    completion_percentage: float
    is_complete: bool
    created_at: Optional[datetime] = None

    class Config:
        from_attributes = True


class UpdateChecklistRequest(BaseModel):
    """Request to update checklist items"""
    checklist_items: List[ChecklistItem]


# ==================== DASHBOARD/SUMMARY SCHEMAS ====================

class PeriodSummary(BaseModel):
    """Summary information for a period"""
    period_id: str
    period_name: str
    period_code: str
    status: PeriodStatusEnum
    is_locked: bool
    is_current: bool
    transaction_count: Optional[int] = None
    total_debits: Optional[float] = None
    total_credits: Optional[float] = None
    checklist_completion: Optional[float] = None


class FiscalYearDashboard(BaseModel):
    """Dashboard view of fiscal year status"""
    fiscal_year: FiscalYearResponse
    current_period: Optional[PeriodSummary] = None
    periods: List[PeriodSummary]
    total_transactions: int
    open_periods_count: int
    closed_periods_count: int


# Update forward references
FiscalYearWithPeriods.model_rebuild()
