from typing import Optional, List, Dict
from sqlmodel import SQLModel
from datetime import datetime

class UserCreate(SQLModel):
    email: str
    password: str
    username: str

class UserRead(SQLModel):
    id: int
    email: str
    is_active: bool
    is_superuser: bool
    role: str = "user"
    avatar_bg_color: Optional[str] = "#3B82F6"
    avatar_text: Optional[str] = None
    profile_public: bool = True
    show_attendance_public: bool = True
    appear_in_leaderboards: bool = True

class Token(SQLModel):
    access_token: str
    token_type: str

class TokenData(SQLModel):
    email: Optional[str] = None

# --- Venue Schemas ---
class VenueBase(SQLModel):
    name: str
    city: str
    state: Optional[str] = None
    country: str
    capacity: Optional[int] = None
    notes: Optional[str] = None

class VenueCreate(VenueBase):
    pass

class VenueRead(VenueBase):
    id: int
    slug: Optional[str] = None

class VenueUpdate(SQLModel):
    name: Optional[str] = None
    city: Optional[str] = None
    state: Optional[str] = None
    country: Optional[str] = None
    capacity: Optional[int] = None
    notes: Optional[str] = None

# --- Song Schemas ---
class SongBase(SQLModel):
    title: str
    original_artist: Optional[str] = None
    vertical_id: int
    notes: Optional[str] = None

class SongCreate(SongBase):
    pass

class SongRead(SongBase):
    id: int
    slug: Optional[str] = None
    tags: List["TagRead"] = []



class SongUpdate(SQLModel):
    title: Optional[str] = None
    original_artist: Optional[str] = None
    notes: Optional[str] = None

# --- Vertical Schema (simple for embedding) ---
class VerticalSimple(SQLModel):
    id: int
    name: str
    slug: str
    description: Optional[str] = None
    logo_url: Optional[str] = None
    accent_color: Optional[str] = None

# --- Show Schemas ---
class ShowBase(SQLModel):
    date: datetime
    vertical_id: int
    venue_id: Optional[int] = None
    tour_id: Optional[int] = None
    notes: Optional[str] = None

class ShowCreate(ShowBase):
    pass

# --- Performance Schemas ---
class PerformanceBase(SQLModel):
    show_id: int
    song_id: int
    position: int
    set_name: Optional[str] = None
    segue: bool = False
    notes: Optional[str] = None

class PerformanceRead(PerformanceBase):
    id: int
    slug: Optional[str] = None
    song: Optional["SongRead"] = None
    nicknames: List["PerformanceNicknameRead"] = []
    youtube_link: Optional[str] = None

class PerformanceReadWithShow(PerformanceRead):
    show_date: datetime
    show_slug: Optional[str] = None
    venue_name: str
    venue_city: str
    venue_state: Optional[str] = None
    avg_rating: Optional[float] = 0.0
    total_reviews: Optional[int] = 0

class SongReadWithStats(SongRead):
    times_played: int
    gap: int
    last_played: Optional[datetime] = None
    set_breakdown: Dict[str, int] = {}
    performances: List[PerformanceReadWithShow] = []

class PerformanceDetailRead(PerformanceRead):
    show: Optional["ShowRead"] = None
    previous_performance_id: Optional[int] = None
    previous_performance_slug: Optional[str] = None
    next_performance_id: Optional[int] = None
    next_performance_slug: Optional[str] = None
    gap: Optional[int] = 0
    times_played: Optional[int] = 0
    other_performances: List[PerformanceReadWithShow] = []
    # Ranking fields
    rank: Optional[int] = None
    total_versions: Optional[int] = None
    avg_rating: Optional[float] = None
    rating_count: Optional[int] = None
    is_heady: Optional[bool] = False

# --- Groups ---
class GroupBase(SQLModel):
    name: str
    description: Optional[str] = None
    privacy: str = "public"

class GroupCreate(GroupBase):
    pass

class GroupRead(GroupBase):
    id: int
    created_by: int
    created_at: datetime
    member_count: Optional[int] = 0

class GroupPostBase(SQLModel):
    content: str

class GroupPostCreate(GroupPostBase):
    group_id: int

class GroupPostRead(GroupPostBase):
    id: int
    group_id: int
    user_id: int
    created_at: datetime
    song: Optional["SongRead"] = None
    nicknames: List["PerformanceNicknameRead"] = []

class ShowRead(ShowBase):
    id: int
    slug: Optional[str] = None
    vertical: Optional["VerticalSimple"] = None
    venue: Optional["VenueRead"] = None
    tour: Optional["TourRead"] = None
    tags: List["TagRead"] = []
    performances: List["PerformanceRead"] = []
    notes: Optional[str] = None
    youtube_link: Optional[str] = None
    nugs_link: Optional[str] = None
    bandcamp_link: Optional[str] = None

class ShowUpdate(SQLModel):
    date: Optional[datetime] = None
    venue_id: Optional[int] = None
    tour_id: Optional[int] = None
    notes: Optional[str] = None

# --- Tour Schemas ---
class TourBase(SQLModel):
    name: str
    start_date: Optional[datetime] = None
    end_date: Optional[datetime] = None
    notes: Optional[str] = None

class TourCreate(TourBase):
    pass

class TourRead(TourBase):
    id: int
    slug: Optional[str] = None

class TourUpdate(SQLModel):
    name: Optional[str] = None
    start_date: Optional[datetime] = None
    end_date: Optional[datetime] = None
    notes: Optional[str] = None

# --- Artist Schemas ---
class ArtistBase(SQLModel):
    name: str
    instrument: Optional[str] = None
    notes: Optional[str] = None

class ArtistCreate(ArtistBase):
    pass

class ArtistRead(ArtistBase):
    id: int

class ArtistUpdate(SQLModel):
    name: Optional[str] = None
    instrument: Optional[str] = None
    notes: Optional[str] = None

# --- Attendance Schemas ---
class AttendanceBase(SQLModel):
    show_id: int
    notes: Optional[str] = None

class AttendanceCreate(AttendanceBase):
    pass

class AttendanceRead(AttendanceBase):
    id: int
    user_id: int
    created_at: datetime

# --- Social Schemas ---
class CommentBase(SQLModel):
    content: str
    show_id: Optional[int] = None
    venue_id: Optional[int] = None
    song_id: Optional[int] = None
    parent_id: Optional[int] = None

class CommentCreate(CommentBase):
    pass

class CommentRead(CommentBase):
    id: int
    user_id: int
    created_at: datetime
    # We might want to include the username here later

class RatingBase(SQLModel):
    score: Optional[float] = None  # 1-5 stars, optional
    show_id: Optional[int] = None
    song_id: Optional[int] = None
    performance_id: Optional[int] = None
    venue_id: Optional[int] = None
    tour_id: Optional[int] = None

class RatingCreate(RatingBase):
    pass

class RatingRead(RatingBase):
    id: int
    user_id: int
    created_at: datetime

class ReviewBase(SQLModel):
    blurb: Optional[str] = None  # Short tagline/summary
    content: Optional[str] = None  # Full review text
    score: Optional[float] = None  # Optional rating with review
    show_id: Optional[int] = None
    venue_id: Optional[int] = None
    song_id: Optional[int] = None
    performance_id: Optional[int] = None
    tour_id: Optional[int] = None
    year: Optional[int] = None

class ReviewCreate(ReviewBase):
    pass

class ReviewRead(ReviewBase):
    id: int
    user_id: int
    created_at: datetime

# --- Badge Schemas ---
class BadgeBase(SQLModel):
    name: str
    description: str
    icon: str
    slug: str

class BadgeCreate(BadgeBase):
    pass

class BadgeRead(BadgeBase):
    id: int

class UserBadgeRead(SQLModel):
    id: int
    user_id: int
    badge: BadgeRead
    awarded_at: datetime

# --- Nickname Schemas ---
class PerformanceNicknameBase(SQLModel):
    performance_id: int
    nickname: str
    description: Optional[str] = None

class PerformanceNicknameCreate(PerformanceNicknameBase):
    pass

class PerformanceNicknameRead(PerformanceNicknameBase):
    id: int
    status: str
    suggested_by: int
    created_at: datetime

# --- Report Schemas ---
class ReportBase(SQLModel):
    entity_type: str
    entity_id: int
    reason: str

class ReportCreate(ReportBase):
    pass

class ReportRead(ReportBase):
    id: int
    user_id: int
    status: str
    created_at: datetime

# --- User Preferences Schemas ---
class UserPreferencesBase(SQLModel):
    wiki_mode: bool = False
    show_ratings: bool = True
    show_comments: bool = True
    theme: str = "system"
    email_on_reply: bool = True
    email_on_chase: bool = True
    email_digest: bool = False

class UserPreferencesCreate(UserPreferencesBase):
    pass

class UserPreferencesUpdate(SQLModel):
    wiki_mode: Optional[bool] = None
    show_ratings: Optional[bool] = None
    show_comments: Optional[bool] = None
    theme: Optional[str] = None
    email_on_reply: Optional[bool] = None
    email_on_chase: Optional[bool] = None
    email_digest: Optional[bool] = None

class UserPreferencesRead(UserPreferencesBase):
    user_id: int

# --- Notification Schemas ---
class NotificationBase(SQLModel):
    type: str
    title: str
    message: str
    link: Optional[str] = None
    is_read: bool = False

class NotificationCreate(NotificationBase):
    user_id: int

class NotificationRead(NotificationBase):
    id: int
    created_at: datetime

# --- Tag Schemas ---
class TagBase(SQLModel):
    name: str
    slug: str

class TagCreate(TagBase):
    pass

class TagRead(TagBase):
    id: int
    slug: str


# Circular refs
ShowRead.model_rebuild()
PerformanceDetailRead.model_rebuild()

# --- Reaction Schemas ---
class ReactionBase(SQLModel):
    entity_type: str
    entity_id: int
    emoji: str

class ReactionCreate(ReactionBase):
    pass

class ReactionRead(ReactionBase):
    id: int
    user_id: int
    created_at: datetime

# --- Profile Schemas ---

class SocialHandles(SQLModel):
    bluesky: Optional[str] = None
    mastodon: Optional[str] = None
    instagram: Optional[str] = None

class HeadlinerBand(SQLModel):
    name: str
    slug: str
    tier: str # headliner, main_stage, supporting
    logo_url: Optional[str] = None 

class PublicProfileRead(SQLModel):
    id: int
    username: str
    display_name: str
    bio: Optional[str] = None
    avatar: Optional[str] = None
    avatar_bg_color: Optional[str] = None
    avatar_text: Optional[str] = None
    location: Optional[str] = None
    
    # Socials
    social_handles: SocialHandles
    
    # The Lineup
    headliners: List[HeadlinerBand]
    supporting_acts: List[HeadlinerBand]
    
    # Stats
    stats: Dict[str, int]
    
    joined_at: datetime
