from pydantic import BaseModel, Field
from typing import Optional, List, Dict
from datetime import datetime
from uuid import UUID


# ============================================
# User Schemas
# ============================================
class UserBase(BaseModel):
    email: str


class UserCreate(UserBase):
    pass


class User(UserBase):
    id: UUID
    created_at: datetime

    class Config:
        from_attributes = True


# ============================================
# Event Schemas
# ============================================
class EventBase(BaseModel):
    name: str
    date: Optional[datetime] = None
    location: Optional[str] = None
    partner1_name: Optional[str] = None
    partner2_name: Optional[str] = None
    venue: Optional[str] = None
    event_time: Optional[str] = None
    guest_link: Optional[str] = None
    invitation_image_url: Optional[str] = None
    guest_form_fields: Optional[str] = None


class EventCreate(EventBase):
    pass


class EventUpdate(BaseModel):
    name: Optional[str] = None
    date: Optional[datetime] = None
    location: Optional[str] = None
    partner1_name: Optional[str] = None
    partner2_name: Optional[str] = None
    venue: Optional[str] = None
    event_time: Optional[str] = None
    guest_link: Optional[str] = None
    invitation_image_url: Optional[str] = None
    guest_form_fields: Optional[str] = None


class Event(EventBase):
    id: UUID
    created_at: datetime
    updated_at: Optional[datetime] = None

    class Config:
        from_attributes = True


class EventWithMembers(Event):
    members: List["EventMember"] = []


# ============================================
# Event Member Schemas
# ============================================
class EventMemberBase(BaseModel):
    role: str = "admin"  # admin, editor, viewer
    display_name: Optional[str] = None


class EventMemberCreate(BaseModel):
    user_email: str = Field(..., description="Email address of the user to invite")
    role: str = "admin"
    display_name: Optional[str] = None


class EventMember(EventMemberBase):
    id: UUID
    event_id: UUID
    user_id: UUID
    created_at: datetime
    user: Optional[User] = None

    class Config:
        from_attributes = True


# ============================================
# Guest Schemas
# ============================================
class GuestBase(BaseModel):
    first_name: str
    last_name: str
    email: Optional[str] = None
    phone_number: Optional[str] = None
    rsvp_status: str = "invited"  # invited, confirmed, declined
    meal_preference: Optional[str] = None
    has_plus_one: bool = False
    plus_one_name: Optional[str] = None
    companion_count: Optional[int] = 0
    table_number: Optional[str] = None
    side: Optional[str] = None  # e.g., "groom side", "bride side"
    notes: Optional[str] = None


class GuestCreate(GuestBase):
    pass


class GuestUpdate(BaseModel):
    first_name: Optional[str] = None
    last_name: Optional[str] = None
    email: Optional[str] = None
    phone_number: Optional[str] = None
    rsvp_status: Optional[str] = None
    meal_preference: Optional[str] = None
    has_plus_one: Optional[bool] = None
    plus_one_name: Optional[str] = None
    companion_count: Optional[int] = None
    table_number: Optional[str] = None
    side: Optional[str] = None
    notes: Optional[str] = None


class Guest(GuestBase):
    id: UUID
    event_id: UUID
    added_by_user_id: UUID
    owner_email: Optional[str] = None
    source: str = "manual"
    created_at: datetime
    updated_at: Optional[datetime] = None

    class Config:
        from_attributes = True


# ============================================
# Bulk Import Schemas
# ============================================
class GuestImportItem(BaseModel):
    first_name: str
    last_name: str
    email: Optional[str] = None
    phone_number: Optional[str] = None
    side: Optional[str] = None
    notes: Optional[str] = None


class GuestBulkImport(BaseModel):
    guests: List[GuestImportItem]


class GuestBulkDelete(BaseModel):
    guest_ids: List[UUID]


# ============================================
# Filter/Search Schemas
# ============================================
class GuestFilter(BaseModel):
    search: Optional[str] = None
    side: Optional[str] = None
    status: Optional[str] = None
    added_by: Optional[str] = None  # "me" for current user


# ============================================
# WhatsApp Schemas
# ============================================
class WhatsAppMessage(BaseModel):
    message: str
    phone: Optional[str] = None  # Optional: override guest's phone


class WhatsAppStatus(BaseModel):
    message_id: str
    status: str
    timestamp: datetime


class WhatsAppWeddingInviteRequest(BaseModel):
    """Request to send wedding invitation template to guest(s)"""
    guest_ids: Optional[List[str]] = None          # For bulk sending
    phone_override: Optional[str] = None           # Optional: override phone number
    template_key: Optional[str] = "wedding_invitation"  # Registry key for template selection
    # Optional form data overrides (frontend form values take priority over DB)
    partner1_name: Optional[str] = None            # First partner / groom name
    partner2_name: Optional[str] = None            # Second partner / bride name
    venue: Optional[str] = None                    # Hall / venue name
    event_date: Optional[str] = None               # YYYY-MM-DD or DD/MM
    event_time: Optional[str] = None               # HH:mm
    guest_link: Optional[str] = None               # RSVP link
    extra_params: Optional[Dict[str, str]] = None  # Custom/extra param values keyed by param name

    class Config:
        from_attributes = True


class WhatsAppSendResult(BaseModel):
    """Result of sending WhatsApp message to a guest"""
    guest_id: str
    guest_name: Optional[str] = None
    phone: str
    status: str  # "sent", "failed"
    message_id: Optional[str] = None
    error: Optional[str] = None
    
    class Config:
        from_attributes = True


class WhatsAppBulkResult(BaseModel):
    """Result of bulk WhatsApp sending"""
    total: int
    succeeded: int
    failed: int
    results: List[WhatsAppSendResult]
    
    class Config:
        from_attributes = True


# ============================================
# Google Contacts Import Schema
# ============================================
class GoogleContactsImport(BaseModel):
    access_token: str
    owner: Optional[str] = "Google Import"


# ============================================
# Public Guest Self-Service Schema
# ============================================
class GuestPublicUpdate(BaseModel):
    """Schema for public guest self-service updates (phone-based lookup)"""
    first_name: Optional[str] = None
    last_name: Optional[str] = None
    rsvp_status: Optional[str] = None
    meal_preference: Optional[str] = None
    has_plus_one: Optional[bool] = None
    plus_one_name: Optional[str] = None


# ============================================
# Event-Scoped RSVP Schemas  (/public/events/:id)
# ============================================

class EventPublicInfo(BaseModel):
    """Public event details returned on the RSVP landing page"""
    event_id: str
    name: str
    date: Optional[str] = None
    venue: Optional[str] = None
    partner1_name: Optional[str] = None
    partner2_name: Optional[str] = None
    event_time: Optional[str] = None


class EventScopedRsvpUpdate(BaseModel):
    """
    Guest submits RSVP for a specific event.
    Identified by phone; update is scoped exclusively to that (event, phone) pair.
    """
    phone: str
    first_name: Optional[str] = None
    last_name: Optional[str] = None
    rsvp_status: Optional[str] = None
    meal_preference: Optional[str] = None
    companion_count: Optional[int] = None


# ============================================
# RSVP Token Schemas
# ============================================

class RsvpResolveResponse(BaseModel):
    """Returned when a guest opens their personal RSVP link via token"""
    valid: bool
    token: str
    event_id: Optional[str] = None
    event_name: Optional[str] = None
    event_date: Optional[str] = None
    venue: Optional[str] = None
    partner1_name: Optional[str] = None
    partner2_name: Optional[str] = None
    guest_id: Optional[str] = None
    guest_first_name: Optional[str] = None
    guest_last_name: Optional[str] = None
    current_rsvp_status: Optional[str] = None
    current_meal_preference: Optional[str] = None
    current_has_plus_one: Optional[bool] = None
    current_plus_one_name: Optional[str] = None
    error: Optional[str] = None


class RsvpSubmit(BaseModel):
    """Guest submits their RSVP via token"""
    token: str
    rsvp_status: str  # "attending", "not_attending", "maybe"
    meal_preference: Optional[str] = None
    has_plus_one: Optional[bool] = None
    plus_one_name: Optional[str] = None
    first_name: Optional[str] = None
    last_name: Optional[str] = None


class RsvpSubmitResponse(BaseModel):
    success: bool
    message: str
    guest_id: Optional[str] = None


# ============================================
# Contact Import Schemas
# ============================================
class ImportContactRow(BaseModel):
    """Represents a single row from an uploaded CSV / JSON import file."""
    first_name: Optional[str] = None
    last_name: Optional[str] = None
    full_name: Optional[str] = None  # alternative: "Full Name" column
    phone: Optional[str] = None
    phone_number: Optional[str] = None
    email: Optional[str] = None
    rsvp_status: Optional[str] = None
    meal_preference: Optional[str] = None
    notes: Optional[str] = None
    side: Optional[str] = None
    table_number: Optional[str] = None
    has_plus_one: Optional[bool] = None
    plus_one_name: Optional[str] = None


class ImportRowResult(BaseModel):
    """Per-row result returned in the import response."""
    row: int
    action: str          # "created" | "updated" | "skipped" | "error"
    name: Optional[str] = None
    phone: Optional[str] = None
    reason: Optional[str] = None  # for errors / skips


class ImportContactsResponse(BaseModel):
    """Full response from POST /admin/import/contacts."""
    dry_run: bool
    total: int
    created: int
    updated: int
    skipped: int
    errors: int
    rows: List[ImportRowResult]

