"""
Dashboard API Models - Pydantic models for dashboard API endpoints
"""
from __future__ import annotations

import re
from datetime import datetime
from typing import Any, Dict, List, Optional
from enum import Enum

from pydantic import BaseModel, EmailStr, Field, validator


class UserRole(str, Enum):
    OWNER = "owner"
    ADMIN = "admin"
    MEMBER = "member"
    VIEWER = "viewer"


class IndustryType(str, Enum):
    TECHNOLOGY = "technology"
    FINANCE = "finance"
    HEALTHCARE = "healthcare"
    RETAIL = "retail"
    MANUFACTURING = "manufacturing"
    REAL_ESTATE = "real-estate"
    CONSULTING = "consulting"
    EDUCATION = "education"
    OTHER = "other"


class CompanySize(str, Enum):
    SIZE_1_10 = "1-10"
    SIZE_11_50 = "11-50"
    SIZE_51_200 = "51-200"
    SIZE_201_500 = "201-500"
    SIZE_500_PLUS = "500+"


# Auth Models
class UserRegistration(BaseModel):
    email: EmailStr
    password: str
    first_name: str = Field(..., min_length=1, max_length=50)
    last_name: str = Field(..., min_length=1, max_length=50)
    
    @validator('password')
    def validate_password(cls, v):
        if len(v) < 8:
            raise ValueError('Password must be at least 8 characters long')
        if not re.search(r'[A-Z]', v):
            raise ValueError('Password must contain at least one uppercase letter')
        if not re.search(r'[a-z]', v):
            raise ValueError('Password must contain at least one lowercase letter')
        if not re.search(r'\d', v):
            raise ValueError('Password must contain at least one digit')
        return v


class UserLogin(BaseModel):
    email: EmailStr
    password: str


class PasswordReset(BaseModel):
    email: EmailStr


class PasswordChange(BaseModel):
    current_password: str
    new_password: str
    
    @validator('new_password')
    def validate_new_password(cls, v):
        if len(v) < 8:
            raise ValueError('Password must be at least 8 characters long')
        if not re.search(r'[A-Z]', v):
            raise ValueError('Password must contain at least one uppercase letter')
        if not re.search(r'[a-z]', v):
            raise ValueError('Password must contain at least one lowercase letter')
        if not re.search(r'\d', v):
            raise ValueError('Password must contain at least one digit')
        return v


# Organization Models
class OrganizationCreate(BaseModel):
    name: str = Field(..., min_length=1, max_length=100)
    industry: IndustryType
    size: CompanySize
    country: str = Field(..., min_length=2, max_length=2)
    website: Optional[str] = Field(None, max_length=255)
    description: Optional[str] = Field(None, max_length=500)


class OrganizationUpdate(BaseModel):
    name: Optional[str] = Field(None, min_length=1, max_length=100)
    industry: Optional[IndustryType] = None
    size: Optional[CompanySize] = None
    country: Optional[str] = Field(None, min_length=2, max_length=2)
    website: Optional[str] = Field(None, max_length=255)
    description: Optional[str] = Field(None, max_length=500)


class OrganizationResponse(BaseModel):
    id: str
    name: str
    industry: IndustryType
    size: CompanySize
    country: str
    website: Optional[str]
    description: Optional[str]
    created_at: datetime
    updated_at: datetime
    plan: str
    member_count: int
    owner_id: str


# User Models
class UserProfile(BaseModel):
    id: str
    email: EmailStr
    first_name: str
    last_name: str
    role: UserRole
    created_at: datetime
    last_login: Optional[datetime]
    avatar_url: Optional[str]


class UserProfileUpdate(BaseModel):
    first_name: Optional[str] = Field(None, min_length=1, max_length=50)
    last_name: Optional[str] = Field(None, min_length=1, max_length=50)


# API Key Models
class ApiKeyCreate(BaseModel):
    name: str = Field(..., min_length=1, max_length=100)
    scopes: List[str] = Field(default_factory=list)


class ApiKeyResponse(BaseModel):
    id: str
    name: str
    key_prefix: str  # Only show first 8 chars for security
    created_at: datetime
    last_used_at: Optional[datetime]
    is_active: bool
    scopes: List[str]
    usage_count: int


class ApiKeyWithSecret(ApiKeyResponse):
    key: str  # Full key only returned on creation


# Dashboard Models
class DashboardStats(BaseModel):
    api_usage_current_month: int
    api_usage_limit: int
    success_rate: float
    active_api_keys: int
    current_plan: str
    plan_display_name: str
    total_requests_today: int
    total_requests_this_month: int
    avg_response_time_ms: float
    error_rate: float


class UsageStats(BaseModel):
    date: str
    requests: int
    errors: int
    avg_response_time_ms: float


class ActivityItem(BaseModel):
    id: str
    type: str
    title: str
    description: str
    timestamp: datetime
    icon: str
    user_id: Optional[str] = None
    user_name: Optional[str] = None


# Billing Models
class PlanFeature(BaseModel):
    name: str
    included: bool
    value: Optional[str] = None


class BillingPlan(BaseModel):
    id: str
    name: str
    display_name: str
    price: int  # in cents
    currency: str
    interval: str  # "month" or "year"
    description: str
    features: List[PlanFeature]
    limits: Dict[str, Any]
    is_popular: bool = False


class SubscriptionResponse(BaseModel):
    id: str
    plan_id: str
    plan_name: str
    status: str
    billing_interval: str
    current_period_start: datetime
    current_period_end: datetime
    cancel_at_period_end: bool
    usage_current_period: Dict[str, int]


class PaymentMethod(BaseModel):
    id: str
    type: str  # "card", "bank_account"
    last_four: str
    brand: Optional[str] = None  # For cards
    exp_month: Optional[int] = None
    exp_year: Optional[int] = None
    is_default: bool


class Invoice(BaseModel):
    id: str
    number: str
    amount: int  # in cents
    currency: str
    status: str
    created_at: datetime
    due_date: datetime
    paid_at: Optional[datetime]
    pdf_url: Optional[str]


# Settings Models
class NotificationSettings(BaseModel):
    email_notifications: bool = True
    usage_alerts: bool = True
    security_alerts: bool = True
    billing_alerts: bool = True


class SecuritySettings(BaseModel):
    two_factor_enabled: bool = False
    session_timeout_minutes: int = 480  # 8 hours default


class UserSettings(BaseModel):
    notifications: NotificationSettings
    security: SecuritySettings


# Response Models
class AuthResponse(BaseModel):
    access_token: str
    refresh_token: Optional[str]
    token_type: str = "Bearer"
    expires_in: int
    user: UserProfile
    organization: Optional[OrganizationResponse] = None


class MessageResponse(BaseModel):
    message: str
    success: bool = True


class ErrorResponse(BaseModel):
    error: str
    code: Optional[str] = None
    details: Optional[Dict[str, Any]] = None
    success: bool = False


# Team Management Models
class TeamInvite(BaseModel):
    email: EmailStr
    role: UserRole
    message: Optional[str] = None


class TeamMember(BaseModel):
    id: str
    email: EmailStr
    first_name: str
    last_name: str
    role: UserRole
    status: str  # "active", "pending", "suspended"
    joined_at: Optional[datetime]
    last_active: Optional[datetime]
    invited_by: Optional[str]


class RoleUpdate(BaseModel):
    role: UserRole


# Analytics Models
class TimeSeriesDataPoint(BaseModel):
    timestamp: datetime
    value: float
    label: Optional[str] = None


class AnalyticsResponse(BaseModel):
    metric_name: str
    time_range: str
    data_points: List[TimeSeriesDataPoint]
    total: float
    average: float
    change_percent: Optional[float] = None


class UsageAnalytics(BaseModel):
    requests_over_time: List[TimeSeriesDataPoint]
    errors_over_time: List[TimeSeriesDataPoint]
    response_times: List[TimeSeriesDataPoint]
    top_endpoints: List[Dict[str, Any]]
    geographic_distribution: List[Dict[str, Any]]
    peak_usage_hours: List[int]


# Subscription Models
class SubscriptionResponse(BaseModel):
    id: str
    organization_id: str
    plan: str
    status: str  # "active", "canceled", "past_due"
    billing_interval: str
    current_period_start: datetime
    current_period_end: datetime
    cancel_at_period_end: bool
    created_at: datetime
    updated_at: datetime


class PaymentMethod(BaseModel):
    id: str
    type: str  # "card", "bank_account"
    last_four: str
    brand: Optional[str] = None
    expiry_month: Optional[int] = None
    expiry_year: Optional[int] = None
    is_default: bool = True


class BillingHistory(BaseModel):
    id: str
    amount: float
    currency: str = "USD"
    status: str  # "paid", "pending", "failed"
    description: str
    created_at: datetime
    invoice_url: Optional[str] = None


# Team Management Models  
class TeamInvite(BaseModel):
    email: EmailStr
    role: UserRole
    message: Optional[str] = None


class TeamMember(BaseModel):
    id: str
    email: EmailStr
    first_name: str
    last_name: str
    role: UserRole
    status: str  # "active", "pending", "suspended"
    joined_at: Optional[datetime]
    last_active: Optional[datetime]
    invited_by: Optional[str]


class RoleUpdate(BaseModel):
    role: UserRole
