from __future__ import annotations
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel, ConfigDict, Field


class PlanRateInput(BaseModel):
    transaction_type: str
    rate_percentage: Optional[float] = Field(None, ge=0, le=100)
    fixed_fee_cents: int = Field(0, ge=0)
    tier_name: Optional[str] = None
    interchange_basis_points: Optional[int] = None
    markup_basis_points: Optional[int] = None


class PlanFeatureItemInput(BaseModel):
    feature_slug: str
    is_enabled: bool


class PlanPricingInput(BaseModel):
    billing_cycle: str = "monthly"
    monthly_fee_cents: int = Field(0, ge=0)
    setup_fee_cents: int = Field(0, ge=0)
    rates: List[PlanRateInput] = Field(default_factory=list)


class PlanFeaturesInput(BaseModel):
    items: List[PlanFeatureItemInput] = Field(default_factory=list)


class PlanCreate(BaseModel):
    name: str = Field(..., max_length=255)
    description: Optional[str] = None
    is_active: bool = True
    pricing: PlanPricingInput
    features: PlanFeaturesInput


class PlanUpdate(BaseModel):
    name: Optional[str] = Field(None, max_length=255)
    description: Optional[str] = None
    is_active: Optional[bool] = None
    pricing: Optional[PlanPricingInput] = None
    features: Optional[PlanFeaturesInput] = None


class PlanAssignRequest(BaseModel):
    merchant_id: int
    notes: Optional[str] = None


class PlanRateResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    id: int
    transaction_type: str
    rate_percentage: Optional[float]
    fixed_fee_cents: int
    tier_name: Optional[str]
    interchange_basis_points: Optional[int]
    markup_basis_points: Optional[int]


class PlanPricingResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    id: int
    name: str
    description: Optional[str]
    pricing_type: str
    billing_cycle: str
    monthly_fee_cents: int
    setup_fee_cents: int
    rates: List[PlanRateResponse] = []


class PlanFeatureItemResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    feature_slug: str
    is_enabled: bool


class PlanFeaturesResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    id: int
    name: str
    description: Optional[str]
    is_active: bool
    items: List[PlanFeatureItemResponse] = []


class PlanDetailResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    id: int
    name: str
    description: Optional[str]
    is_active: bool
    created_by_user_id: Optional[int]
    created_at: datetime
    updated_at: Optional[datetime]
    pricing: PlanPricingResponse
    features: PlanFeaturesResponse
    assigned_merchant_count: int = 0


class PlanListItem(BaseModel):
    id: int
    name: str
    description: Optional[str]
    is_active: bool
    pricing_type: str
    billing_cycle: str
    monthly_fee_cents: int
    created_at: datetime
    updated_at: Optional[datetime]
    assigned_merchant_count: int


class PlanListResponse(BaseModel):
    items: List[PlanListItem]
    total: int
    page: int
    per_page: int


class PlanAssignResponse(BaseModel):
    plan_id: int
    merchant_id: int
    message: str
