from typing import Optional, List, Literal
from datetime import datetime
from pydantic import BaseModel, HttpUrl, field_validator


class Token(BaseModel):
    access_token: str
    token_type: str
    refresh_token: Optional[str] = None


class TokenData(BaseModel):
    username: Optional[str] = None


class UserCreate(BaseModel):
    username: str
    password: str
    email: Optional[str] = None


class UserResponse(BaseModel):
    id: int
    username: str
    is_active: bool
    display_name: Optional[str] = None
    email: Optional[str] = None
    age: Optional[int] = None
    career: Optional[str] = None
    education: Optional[str] = None
    linkedin_url: Optional[str] = None
    community_role: Optional[str] = None
    bio: Optional[str] = None
    tech_skills: Optional[List[str]] = None

    class Config:
        from_attributes = True


ALLOWED_TECH_SKILLS = {
    "React", "JavaScript", "TypeScript", "PHP", ".NET", "Java",
    "Python", "Node.js", "Vue.js", "Angular", "Go", "Rust",
    "Swift", "Kotlin", "C#", "C++", "Ruby", "SQL",
}

class UserProfileUpdate(BaseModel):
    age: Optional[int] = None
    career: Optional[str] = None
    education: Optional[str] = None
    linkedin_url: Optional[str] = None
    community_role: Optional[Literal["mentor", "mentee"]] = None
    bio: Optional[str] = None
    tech_skills: Optional[List[str]] = None

    @field_validator("age")
    @classmethod
    def age_range(cls, v):
        if v is not None and not (10 <= v <= 120):
            raise ValueError("Age must be between 10 and 120")
        return v

    @field_validator("linkedin_url")
    @classmethod
    def linkedin_domain(cls, v):
        if v and v.strip():
            if not (v.startswith("https://linkedin.com") or v.startswith("https://www.linkedin.com")):
                raise ValueError("LinkedIn URL must start with https://linkedin.com or https://www.linkedin.com")
        return v

    @field_validator("tech_skills")
    @classmethod
    def validate_skills(cls, v):
        if v is not None:
            invalid = [s for s in v if s not in ALLOWED_TECH_SKILLS]
            if invalid:
                raise ValueError(f"Unknown skills: {invalid}")
        return v


class UserActivityResponse(BaseModel):
    id: int
    action: str
    details: Optional[str] = None
    timestamp: datetime

    class Config:
        from_attributes = True


class ActivityCreate(BaseModel):
    action: str
    details: Optional[str] = None


class GoogleLoginRequest(BaseModel):
    access_token: str


class PasswordResetRequest(BaseModel):
    email: str


class PasswordResetConfirm(BaseModel):
    token: str
    new_password: str


# ─── Mentor / Slots ──────────────────────────────────────────────────────────

class MentorPublicResponse(BaseModel):
    id: int
    username: str
    display_name: Optional[str] = None
    career: Optional[str] = None
    education: Optional[str] = None
    bio: Optional[str] = None
    tech_skills: Optional[List[str]] = None
    community_role: Optional[str] = None

    class Config:
        from_attributes = True


class SlotCreate(BaseModel):
    start_time: datetime
    end_time: datetime
    title: Optional[str] = None
    notes: Optional[str] = None
    recurrence: Optional[Literal["none", "daily", "weekly"]] = "none"
    recurrence_count: Optional[int] = 1  # how many occurrences (max 12)

    @field_validator("recurrence_count")
    @classmethod
    def validate_recurrence_count(cls, v):
        if v is not None and not (1 <= v <= 12):
            raise ValueError("recurrence_count must be between 1 and 12")
        return v


class SlotResponse(BaseModel):
    id: int
    mentor_id: int
    start_time: datetime
    end_time: datetime
    title: Optional[str] = None
    notes: Optional[str] = None
    is_booked: bool
    booked_by_id: Optional[int] = None
    booked_by_display_name: Optional[str] = None

    class Config:
        from_attributes = True


class BookingConfirmationResponse(SlotResponse):
    """Returned only on the booking action — includes emails for calendar integration."""
    mentor_email: Optional[str] = None
    mentor_display_name: Optional[str] = None
    mentee_email: Optional[str] = None


class SessionResponse(BaseModel):
    """A booked MentorSlot returned from the /sessions endpoints."""
    id: int
    mentor_id: int
    mentor_display_name: Optional[str] = None
    start_time: datetime
    end_time: datetime
    title: Optional[str] = None
    notes: Optional[str] = None
    booked_by_id: Optional[int] = None
    booked_by_display_name: Optional[str] = None

    class Config:
        from_attributes = True


class SessionReschedule(BaseModel):
    start_time: datetime
    end_time: datetime
