from pydantic import BaseModel, Field, ConfigDict, field_validator
from typing import Optional, List, Dict, Any
from datetime import datetime
import re

# Source schemas
class SourceBase(BaseModel):
    name: str
    type: str = Field(..., pattern="^(local|ssh|database)$")
    config: Dict[str, Any] = Field(default_factory=dict)

class SourceCreate(SourceBase):
    pass

class SourceUpdate(BaseModel):
    name: Optional[str] = None
    config: Optional[Dict[str, Any]] = None

class Source(SourceBase):
    id: int
    created_at: datetime
    updated_at: datetime
    
    model_config = ConfigDict(from_attributes=True)

# Job schemas
class JobBase(BaseModel):
    name: str
    source_id: int
    strategy: str = Field(default="full", pattern="^(full|incremental)$")
    destination_path: str
    exclude_patterns: List[str] = Field(default_factory=list)
    enabled: bool = True

class JobCreate(JobBase):
    pass

class JobUpdate(BaseModel):
    name: Optional[str] = None
    strategy: Optional[str] = None
    destination_path: Optional[str] = None
    exclude_patterns: Optional[List[str]] = None
    enabled: Optional[bool] = None

class Job(JobBase):
    id: int
    created_at: datetime
    updated_at: datetime
    
    model_config = ConfigDict(from_attributes=True)

# Schedule schemas
class ScheduleBase(BaseModel):
    job_id: int
    cron_expression: str
    enabled: bool = True

    @field_validator('cron_expression')
    @classmethod
    def validate_cron(cls, v: str) -> str:
        pattern = r'^([0-9*,/-]+)\s+([0-9*,/-]+)\s+([0-9*,/-]+)\s+([0-9*,/-]+)\s+([0-9*,/-]+)$'
        if not re.match(pattern, v):
            raise ValueError('Invalid cron expression format')
        return v

class ScheduleCreate(ScheduleBase):
    pass

class ScheduleUpdate(BaseModel):
    cron_expression: Optional[str] = None
    enabled: Optional[bool] = None

class Schedule(ScheduleBase):
    id: int
    created_at: datetime
    updated_at: datetime
    
    model_config = ConfigDict(from_attributes=True)

# Execution schemas
class JobExecutionBase(BaseModel):
    job_id: int
    status: str = Field(default="pending", pattern="^(pending|running|success|failed|cancelled)$")
    triggered_by: str = Field(..., pattern="^(manual|schedule)$")

class JobExecutionCreate(JobExecutionBase):
    pass

class JobExecution(JobExecutionBase):
    id: int
    started_at: Optional[datetime] = None
    completed_at: Optional[datetime] = None
    bytes_processed: int = 0
    bytes_backed_up: int = 0
    error_message: Optional[str] = None
    
    model_config = ConfigDict(from_attributes=True)

class JobExecutionUpdate(BaseModel):
    status: Optional[str] = Field(None, pattern="^(pending|running|success|failed|cancelled)$")
    error_message: Optional[str] = None

# Backup schemas
class BackupBase(BaseModel):
    execution_id: int
    storage_path: str
    size_bytes: int = 0
    checksum: Optional[str] = None
    type: str = Field(..., pattern="^(full|incremental)$")
    parent_backup_id: Optional[int] = None

class BackupCreate(BackupBase):
    pass

class Backup(BackupBase):
    id: int
    created_at: datetime
    
    model_config = ConfigDict(from_attributes=True)

# Settings schemas
class SettingBase(BaseModel):
    key: str
    value: Optional[str] = None

class SettingCreate(SettingBase):
    pass

class SettingUpdate(BaseModel):
    value: Optional[str] = None

class Setting(SettingBase):
    updated_at: datetime
    
    model_config = ConfigDict(from_attributes=True)

# Dashboard schemas
class DashboardStats(BaseModel):
    active_jobs: int
    total_backups: int
    storage_used_bytes: int
    recent_failures: int
    recent_executions: List[JobExecution]
