from pydantic import BaseModel, EmailStr, Field,ConfigDict, validator
from sqlalchemy import Table
from src.core.database import Base
from typing import Optional,Any, Dict, List
from decimal import Decimal
from datetime import datetime, date
from enum import Enum




class finance_chart_of_accounts(BaseModel):
    account_id: int
    account_code: int
    account_name:str
    account_type: str
    parent_account_id : int
    is_active : bool

    class Config:
        from_attributes = True # Allows Pydantic to read from ORM models


class FCASchema(BaseModel):
    account_id: int
    account_code: int
    account_name:str
    account_type: str
    parent_account_id: str | None
    is_active : bool

    class Config:
        from_attributes = True # Allows Pydantic to read from ORM models

class GeneralLedgerTransactionSchema(BaseModel):
    transaction_id: int
    gl_account_id: str
    transaction_date: str
    amount_debit: float
    amount_credit: float
    currency: str
    department_id: str
    cost_center_id: Optional[str] = None
    profit_center_id: Optional[int] = None
    entity_id: Optional[int] = None
    customer_id: Optional[str] = None
    vendor_id: Optional[str] = None
    period: str
    class Config:
        from_attributes = True

class TrialBalanceSchema(BaseModel):
    period: str  # VARCHAR(16) in DB
    gl_account_id: str
    debit_total: Decimal
    credit_total: Decimal
    ending_balance: Decimal
    entity_id: Optional[int] = None
    class Config:
        from_attributes = True

class VendorBase(BaseModel):
    vendor_id : int
    vendor_name: str
    category: str
    region: str
    payment_terms: str

class CustomerBase(BaseModel):
    customer_id: str
    customer_name: str
    industry: str
    region: str
    size_segment: str


####################################
#######################################
class QuarterEnum(str, Enum):
    Q1 = "Q1"
    Q2 = "Q2"
    Q3 = "Q3"
    Q4 = "Q4"
 
 
class WorkflowStage:
    DRAFT = "draft"
    SUBMITTED = "submitted"
    REVIEWED = "reviewed"
    APPROVED = "approved"
    LOCKED = "locked"
 
 
class WorkflowStageEnum(str, Enum):
    DRAFT = "draft"
    SUBMITTED = "submitted"
    REVIEWED = "reviewed"
    APPROVED = "approved"
    LOCKED = "locked"
 
 
class RevenueAdjustmentInput(BaseModel):
    customer_name: str
    month1_adjusted: Optional[float] = None
    month1_comment: Optional[str] = None
    month2_adjusted: Optional[float] = None
    month2_comment: Optional[str] = None
    month3_adjusted: Optional[float] = None
    month3_comment: Optional[str] = None
    quarter_total_adjusted: Optional[float] = None
    overall_comment: Optional[str] = None
 
 
class DriverAdjustmentInput(BaseModel):
    customer_name: str
    month: str
    units_adjusted: Optional[float] = None
    rate_adjusted: Optional[float] = None
    revenue_adjusted: Optional[float] = None
    month_comment: Optional[str] = None
    quarter_revenue_adjusted: Optional[float] = None
    overall_comment: Optional[str] = None
 
 
class WorkflowTransitionRequest(BaseModel):
    target_stage: WorkflowStageEnum
    comment: Optional[str] = None
 
 
class RevenueRow(BaseModel):
    customer_name: str
    previous_month: float
    month1_ai: float
    month1_adjusted: float
    month1_comment: Optional[str] = None
    month2_ai: float
    month2_adjusted: float
    month2_comment: Optional[str] = None
    month3_ai: float
    month3_adjusted: float
    month3_comment: Optional[str] = None
    quarter_total_ai: float
    quarter_total_adjusted: float
    overall_comment: Optional[str] = None
 
 
class RevenueTotal(BaseModel):
    previous_month: float = 0.0
    month1_ai: float = 0.0
    month1_adjusted: float = 0.0
    month2_ai: float = 0.0
    month2_adjusted: float = 0.0
    month3_ai: float = 0.0
    month3_adjusted: float = 0.0
 
 
class DriverRow(BaseModel):
    customer_name: str
    month: str
    units_ai: float
    rate_ai: float
    revenue_ai: float
    units_adjusted: Optional[float] = None
    rate_adjusted: Optional[float] = None
    revenue_adjusted: Optional[float] = None
    month_comment: Optional[str] = None
 
 
class CustomerDriverSummary(BaseModel):
    customer_name: str
    months: List[DriverRow]
    quarter_revenue_ai: float
    quarter_revenue_adjusted: float
    overall_comment: Optional[str] = None
 
 
class ForecastCommentInput(BaseModel):
    comment: str
 
 
class CustomerMultiplierInput(BaseModel):
    customer_name: str
    multiplier: float
 
    @validator("multiplier")
    def multiplier_range(cls, v):
        if not (0.01 <= v <= 10.0):
            raise ValueError("multiplier must be between 0.01 and 10.0")
        return v
 
 
class ForecastScenarioInput(BaseModel):
    scenario_name: str
    multiplier: float
    description: Optional[str] = None
    parameter_types: Optional[List[str]] = Field(default=["revenue"])
    customer_scope: Optional[str] = Field(default="all")
    customer_multipliers: Optional[List[CustomerMultiplierInput]] = Field(default=[])
 
    @validator("multiplier")
    def multiplier_range(cls, v):
        if not (0.01 <= v <= 10.0):
            raise ValueError("multiplier must be between 0.01 and 10.0")
        return v
 
    @validator("parameter_types", each_item=True, pre=True)
    def valid_parameter_types(cls, v):
        allowed = {"revenue", "rate", "volume", "quantity"}
        if v not in allowed:
            raise ValueError(f"'{v}' is not a valid parameter type. Allowed: {sorted(allowed)}")
        return v
 
    @validator("customer_scope")
    def valid_customer_scope(cls, v):
        if v not in ("all", "specific"):
            raise ValueError("customer_scope must be 'all' or 'specific'")
        return v
 
    @validator("customer_multipliers", pre=True, always=True)
    def default_customer_multipliers(cls, v):
        return v or []
 
 
class ForecastScenarioUpdateInput(BaseModel):
    scenario_name: Optional[str] = None
    multiplier: Optional[float] = None
    description: Optional[str] = None
    parameter_types: Optional[List[str]] = None
    customer_scope: Optional[str] = None
    customer_multipliers: Optional[List[CustomerMultiplierInput]] = None
 
    @validator("multiplier")
    def multiplier_range(cls, v):
        if v is not None and not (0.01 <= v <= 10.0):
            raise ValueError("multiplier must be between 0.01 and 10.0")
        return v
 
    @validator("parameter_types", each_item=True, pre=True)
    def valid_parameter_types(cls, v):
        if v is not None:
            allowed = {"revenue", "rate", "volume", "quantity"}
            if v not in allowed:
                raise ValueError(f"'{v}' is not a valid parameter type. Allowed: {sorted(allowed)}")
        return v
 
    @validator("customer_scope")
    def valid_customer_scope(cls, v):
        if v is not None and v not in ("all", "specific"):
            raise ValueError("customer_scope must be 'all' or 'specific'")
        return v
 
 
class RevenueForecastResponse(BaseModel):
    year: int
    quarter: QuarterEnum
    prev_month: str
    rows: List[RevenueRow]
    total: RevenueTotal
    Baseline_forecast_summary: Dict[str, Any]
    Compare_Revenue_Forecast_Scenarios: Dict[str, Any]
    drivers: List[CustomerDriverSummary]
    workflow_stage: str
    reviewed_by: Optional[str] = None
    approved_by: Optional[str] = None
    locked_by: Optional[str] = None


# ===== PnL Forecasting Schemas =====

class PnLMetricAdjustmentInput(BaseModel):
    """Input schema for adjusting a single PnL metric"""
    metric: str
    month1_your_adjustment: Optional[float] = None
    month2_your_adjustment: Optional[float] = None
    month3_your_adjustment: Optional[float] = None
    overall_comment: Optional[str] = None


class PnLMetricRow(BaseModel):
    """Row for a single metric in PnL forecast"""
    metric: str
    prev_month: float
    month1_ai_suggested: float
    month1_your_adjustment: float
    month1_comment: Optional[str] = None
    month2_ai_suggested: float
    month2_your_adjustment: float
    month2_comment: Optional[str] = None
    month3_ai_suggested: float
    month3_your_adjustment: float
    month3_comment: Optional[str] = None
    quarter_total_ai: float
    quarter_total_adjusted: float
    overall_comment: Optional[str] = None


class PnLForecastTotal(BaseModel):
    """Aggregated totals for PnL metrics"""
    prev_month: float = 0.0
    month1_ai_suggested: float = 0.0
    month1_your_adjustment: float = 0.0
    month2_ai_suggested: float = 0.0
    month2_your_adjustment: float = 0.0
    month3_ai_suggested: float = 0.0
    month3_your_adjustment: float = 0.0
    variance_amount: float = 0.0
    variance_percent: float = 0.0


class PnLForecastFilters(BaseModel):
    """Filters for PnL forecast"""
    year: int
    quarter: QuarterEnum


class PnLForecastResponse(BaseModel):
    """Complete PnL Forecast response"""
    title: str = "Profit & Loss Forecast"
    filters: PnLForecastFilters
    data: List[PnLMetricRow]
    summary: Dict[str, Any]
    workflow_stage: str = "draft"
    reviewed_by: Optional[str] = None
    approved_by: Optional[str] = None
    locked_by: Optional[str] = None


class PnLForecastInput(BaseModel):
    """Input for saving/updating PnL forecast data"""
    year: int
    quarter: QuarterEnum
    metrics: List[PnLMetricAdjustmentInput]


#############################
