from pydantic import BaseModel, EmailStr, Field, field_validator, model_validator
from typing import List, Optional
from datetime import datetime, date
from sqlalchemy import inspect

class SafeORMMixin:
    @model_validator(mode='before')
    @classmethod
    def safe_orm_load(cls, v):
        if hasattr(v, "_sa_instance_state"):
            state = inspect(v)
            d = {}
            for col in state.mapper.column_attrs:
                if col.key not in state.unloaded:
                    d[col.key] = getattr(v, col.key)
            for rel in state.mapper.relationships:
                if rel.key not in state.unloaded:
                    d[rel.key] = getattr(v, rel.key)
            return d
        return v



class CompanyBase(BaseModel):
    name: str = Field(..., max_length=100)
    is_active: bool = True

class CompanyCreate(CompanyBase):
    pass

class CompanyUpdate(BaseModel):
    name: Optional[str] = Field(None, max_length=100)
    is_active: Optional[bool] = None

class CompanyResponse(CompanyBase):
    id: int
    created_at: datetime
    
    class Config:
        from_attributes = True

class CompanySuperAdminResponse(CompanyResponse):
    log_count: int = 0
    log_size_kb: float = 0.0

class UserBase(BaseModel):
    username: str
    email: str

class UserCreate(UserBase):
    password: str
    is_admin: Optional[bool] = False
    role: Optional[str] = None
    viewable_project_ids: Optional[List[int]] = []

class UserUpdate(UserBase):
    password: Optional[str] = None
    is_admin: Optional[bool] = False
    role: Optional[str] = None
    viewable_project_ids: Optional[List[int]] = []

class UserResponse(SafeORMMixin, UserBase):
    id: int
    company_id: Optional[int] = None
    is_active: bool
    created_at: datetime
    is_admin: bool = False
    roles: List[str] = [] # We'll flatten roles into a list of names
    company: Optional[CompanyResponse] = None
    viewable_projects: List[int] = []

    @field_validator('roles', mode='before')
    def extract_role_names(cls, v):
        if not v:
            return []
        if isinstance(v[0], str):
            return v
        return [role.name for role in v]

    @field_validator('viewable_projects', mode='before')
    def extract_project_ids(cls, v, info):
        # We might receive the ORM relationship 'viewable_projects' in v
        if not v:
            return []
        if isinstance(v[0], int):
            return v
        if hasattr(v[0], 'id'):
            return [proj.id for proj in v]
        return []

    class Config:
        from_attributes = True

class Token(BaseModel):
    access_token: Optional[str] = None
    token_type: Optional[str] = None
    mfa_required: bool = False
    mfa_token: Optional[str] = None

class MFAVerify(BaseModel):
    mfa_token: str
    code: str

class RoleBase(BaseModel):
    name: str
    description: str

class RoleResponse(RoleBase):
    id: int
    class Config:
        from_attributes = True

class TeamBase(BaseModel):
    name: str = Field(..., max_length=100)
    description: Optional[str] = None

class TeamCreate(TeamBase):
    pass

class TeamResponse(SafeORMMixin, TeamBase):
    id: int
    company_id: Optional[int] = None
    created_at: datetime
    members: List[UserResponse] = []
    
    class Config:
        from_attributes = True

class TaskBase(BaseModel):
    title: str = Field(..., max_length=200)
    description: Optional[str] = None
    story_points: int = 0
    start_date: Optional[datetime] = None
    due_date: Optional[datetime] = None
    is_blocked: bool = False
    progress: float = 0.0
    priority: str = "low"
    order: int = 0
    baseline_start_date: Optional[datetime] = None
    baseline_end_date: Optional[datetime] = None
    estimated_hours: float = 0.0
    resource_cost: float = 0.0

class TaskLinkCreate(BaseModel):
    source_id: str
    target_id: str
    type: str = "0"
    project_id: int

class TaskLinkResponse(TaskLinkCreate):
    id: int
    
    class Config:
        from_attributes = True

class TaskCreate(TaskBase):
    project_id: Optional[int] = None
    column_id: Optional[int] = None
    assignee_id: Optional[int] = None
    team_id: Optional[int] = None

class TaskAttachmentResponse(BaseModel):
    id: int
    task_id: int
    filename: str
    file_path: str
    uploaded_at: datetime
    
    class Config:
        from_attributes = True

class SubtaskBase(BaseModel):
    title: str = Field(..., max_length=200)

class SubtaskCreate(SubtaskBase):
    pass

class SubtaskResponse(SubtaskBase):
    id: int
    task_id: int
    is_completed: bool
    created_at: datetime
    
    class Config:
        from_attributes = True

class TaskResponse(SafeORMMixin, TaskBase):
    id: int
    project_id: Optional[int]
    column_id: Optional[int]
    assignee_id: Optional[int]
    team_id: Optional[int]
    created_at: datetime
    completed_at: Optional[datetime] = None
    assignee: Optional[UserResponse] = None
    team: Optional[TeamResponse] = None
    attachments: List[TaskAttachmentResponse] = []
    tags: List['TagResponse'] = []
    subtasks: List[SubtaskResponse] = []
    
    class Config:
        from_attributes = True

class ProjectBase(BaseModel):
    name: str = Field(..., max_length=100)
    description: Optional[str] = None
    is_archived: bool = False
    is_public: bool = True
    roadmap_objectives: Optional[str] = None
    roadmap_deliverables: Optional[str] = None
    roadmap_strategy: Optional[str] = None
    roadmap_resources: Optional[str] = None
    roadmap_deadlines: Optional[str] = None
    roadmap_stakeholders: Optional[str] = None

class KanbanColumnBase(BaseModel):
    name: str = Field(..., max_length=50)
    order: int = 0

class KanbanColumnCreate(KanbanColumnBase):
    pass

class KanbanColumnUpdate(BaseModel):
    name: Optional[str] = Field(None, max_length=50)
    order: Optional[int] = None

class KanbanColumnResponse(KanbanColumnBase):
    id: int
    project_id: int
    
    class Config:
        from_attributes = True

class ProjectCreate(ProjectBase):
    assignee_id: Optional[int] = None
    team_id: Optional[int] = None

class ProjectUpdate(BaseModel):
    name: Optional[str] = Field(None, max_length=100)
    description: Optional[str] = None
    is_public: Optional[bool] = None
    assignee_id: Optional[int] = None
    team_id: Optional[int] = None
    roadmap_objectives: Optional[str] = None
    roadmap_deliverables: Optional[str] = None
    roadmap_strategy: Optional[str] = None
    roadmap_resources: Optional[str] = None
    roadmap_deadlines: Optional[str] = None
    roadmap_stakeholders: Optional[str] = None

class ProjectResponse(SafeORMMixin, ProjectBase):
    id: int
    company_id: Optional[int] = None
    created_at: datetime
    creator_id: Optional[int] = None
    assignee_id: Optional[int] = None
    team_id: Optional[int] = None
    assignee: Optional[UserResponse] = None
    team: Optional[TeamResponse] = None
    company: Optional[CompanyResponse] = None
    
    class Config:
        from_attributes = True


class RoadmapVersionBase(BaseModel):
    version_name: str
    roadmap_objectives: Optional[str] = None
    roadmap_deliverables: Optional[str] = None
    roadmap_strategy: Optional[str] = None
    roadmap_resources: Optional[str] = None
    roadmap_deadlines: Optional[str] = None
    roadmap_stakeholders: Optional[str] = None


class RoadmapVersionCreate(RoadmapVersionBase):
    pass


class RoadmapVersionResponse(RoadmapVersionBase):
    id: int
    project_id: int
    created_at: datetime

    class Config:
        from_attributes = True


class ReportVersionBase(BaseModel):
    version_name: str
    report_html: str


class ReportVersionCreate(ReportVersionBase):
    pass


class ReportVersionResponse(ReportVersionBase):
    id: int
    project_id: int
    created_at: datetime

    class Config:
        from_attributes = True


class SystemSettingResponse(BaseModel):
    id: int
    company_id: Optional[int] = None
    key: str
    value: str
    
    class Config:
        from_attributes = True

class CommentCreate(BaseModel):
    content: str

class CommentResponse(BaseModel):
    id: int
    content: str
    created_at: datetime
    user: Optional[UserResponse] = None
    
    class Config:
        from_attributes = True

class TagBase(BaseModel):
    name: str = Field(..., max_length=50)
    color: str = Field("#888888", max_length=20)

class TagCreate(TagBase):
    pass

class TagResponse(TagBase):
    id: int
    project_id: int
    
    class Config:
        from_attributes = True

TaskResponse.model_rebuild()

class TicketAttachmentResponse(BaseModel):
    id: int
    filename: str
    file_path: str
    uploaded_at: datetime
    
    class Config:
        from_attributes = True

class TicketCommentCreate(BaseModel):
    content: str
    is_internal: Optional[bool] = False

class TicketCommentResponse(BaseModel):
    id: int
    content: str
    is_internal: bool
    created_at: datetime
    user: Optional[UserResponse] = None
    attachments: List[TicketAttachmentResponse] = []
    
    class Config:
        from_attributes = True

class TicketBase(BaseModel):
    title: str = Field(..., max_length=200)
    description: str
    status: Optional[str] = "Abierto"
    priority: Optional[str] = "Media"
    category: Optional[str] = None
    company: Optional[str] = None
    tags: Optional[str] = None
    email_reporter: Optional[str] = None

class TicketCreate(TicketBase):
    pass

class TicketUpdate(BaseModel):
    title: Optional[str] = None
    description: Optional[str] = None
    status: Optional[str] = None
    priority: Optional[str] = None
    category: Optional[str] = None
    company: Optional[str] = None
    tags: Optional[str] = None
    assignee_id: Optional[int] = None
    team_id: Optional[int] = None
    sla_deadline: Optional[datetime] = None
    email_reporter: Optional[str] = None

class TicketMerge(BaseModel):
    target_ticket_id: int

class TicketResponse(TicketBase):
    id: int
    company_id: Optional[int] = None
    created_by_id: Optional[int] = None
    assignee_id: Optional[int] = None
    team_id: Optional[int] = None
    linked_task_id: Optional[int] = None
    linked_project_id: Optional[int] = None
    sla_deadline: Optional[datetime] = None
    created_at: datetime
    updated_at: datetime
    
    created_by: Optional[UserResponse] = None
    assignee: Optional[UserResponse] = None
    team: Optional[TeamResponse] = None
    comments: List[TicketCommentResponse] = []
    attachments: List[TicketAttachmentResponse] = []
    
    class Config:
        from_attributes = True

class NotificationBase(BaseModel):
    message: str
    link: Optional[str] = None
    is_read: Optional[bool] = False

class NotificationCreate(NotificationBase):
    user_id: int

class NotificationResponse(NotificationBase):
    id: int
    user_id: int
    created_at: datetime
    
    class Config:
        from_attributes = True

class KbArticleBase(BaseModel):
    title: str = Field(..., max_length=200)
    content: str
    category: Optional[str] = None
    is_published: Optional[bool] = True

class KbArticleCreate(KbArticleBase):
    pass

class KbArticleUpdate(BaseModel):
    title: Optional[str] = None
    content: Optional[str] = None
    category: Optional[str] = None
    is_published: Optional[bool] = None

class KbArticleResponse(KbArticleBase):
    id: int
    company_id: Optional[int] = None
    author_id: Optional[int] = None
    views: int
    created_at: datetime
    updated_at: datetime
    author: Optional[UserResponse] = None

    class Config:
        from_attributes = True

class TicketRatingBase(BaseModel):
    rating: int = Field(..., ge=1, le=5)
    comment: Optional[str] = None

class TicketRatingCreate(TicketRatingBase):
    pass

class TicketRatingResponse(TicketRatingBase):
    id: int
    ticket_id: int
    user_id: Optional[int] = None
    created_at: datetime
    user: Optional[UserResponse] = None

    class Config:
        from_attributes = True

class TicketAutomationBase(BaseModel):
    name: str = Field(..., max_length=100)
    conditions_json: str
    actions_json: str
    is_active: Optional[bool] = True

class TicketAutomationCreate(TicketAutomationBase):
    pass

class TicketAutomationUpdate(BaseModel):
    name: Optional[str] = None
    conditions_json: Optional[str] = None
    actions_json: Optional[str] = None
    is_active: Optional[bool] = None

class TicketAutomationResponse(TicketAutomationBase):
    id: int
    company_id: Optional[int] = None
    created_at: datetime

    class Config:
        from_attributes = True

class RoadmapTaskDef(BaseModel):
    name: str
    duration_days: int
    subtasks: List[str] = []

class RoadmapPhaseDef(BaseModel):
    name: str
    tasks: List[RoadmapTaskDef]

class RoadmapCreate(BaseModel):
    project_name: str
    start_date: datetime
    phases: List[RoadmapPhaseDef]

class HolidayBase(BaseModel):
    date: date
    name: str

class HolidayCreate(HolidayBase):
    pass

class HolidayResponse(HolidayBase):
    id: int
    company_id: int
    
    class Config:
        from_attributes = True
