"""Pydantic models for database entities."""
from datetime import datetime, date, timezone
from enum import Enum
from typing import Optional, Dict, Any, List
from uuid import UUID
from pydantic import BaseModel, Field, ConfigDict


class DBModel(BaseModel):
    """Base model for database entities with extra fields ignored."""
    model_config = ConfigDict(extra='ignore')


# ==================== ENUMS ====================

class AccountType(str, Enum):
    """User account type."""
    GHOSTWRITER = "ghostwriter"
    COMPANY = "company"
    EMPLOYEE = "employee"


class OnboardingStatus(str, Enum):
    """Onboarding status for users."""
    PENDING = "pending"
    PROFILE_SETUP = "profile_setup"
    POSTS_SCRAPED = "posts_scraped"
    CATEGORIZING = "categorizing"
    COMPLETED = "completed"


class AuthMethod(str, Enum):
    """Authentication method for users."""
    LINKEDIN_OAUTH = "linkedin_oauth"
    EMAIL_PASSWORD = "email_password"


class InvitationStatus(str, Enum):
    """Status of an invitation."""
    PENDING = "pending"
    ACCEPTED = "accepted"
    EXPIRED = "expired"
    CANCELLED = "cancelled"


# ==================== USER & COMPANY MODELS ====================

class Profile(DBModel):
    """Profile model - extends auth.users with app-specific data.

    The id is the same as auth.users.id (Supabase handles authentication).
    """
    id: Optional[UUID] = None
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None

    # Account Type
    account_type: AccountType = AccountType.GHOSTWRITER

    # Display name
    display_name: Optional[str] = None

    # Onboarding
    onboarding_status: OnboardingStatus = OnboardingStatus.PENDING
    onboarding_data: Dict[str, Any] = Field(default_factory=dict)

    # Links
    company_id: Optional[UUID] = None

    # Fields migrated from customers table
    linkedin_url: Optional[str] = None
    writing_style_notes: Optional[str] = None
    metadata: Dict[str, Any] = Field(default_factory=dict)
    profile_picture: Optional[str] = None
    creator_email: Optional[str] = None
    customer_email: Optional[str] = None
    is_active: bool = True


class LinkedInAccount(DBModel):
    """LinkedIn account connection for auto-posting."""
    id: Optional[UUID] = None
    user_id: UUID
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None

    # LinkedIn Identity
    linkedin_user_id: str
    linkedin_vanity_name: Optional[str] = None
    linkedin_name: Optional[str] = None
    linkedin_picture: Optional[str] = None

    # OAuth Tokens (encrypted)
    access_token: str
    refresh_token: Optional[str] = None
    token_expires_at: datetime
    granted_scopes: List[str] = Field(default_factory=list)

    # Status
    is_active: bool = True
    last_used_at: Optional[datetime] = None
    last_error: Optional[str] = None
    last_error_at: Optional[datetime] = None


class TelegramAccount(DBModel):
    """Telegram account connection for bot access."""
    id: Optional[UUID] = None
    user_id: UUID
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None
    telegram_user_id: str
    telegram_username: Optional[str] = None
    telegram_first_name: Optional[str] = None
    telegram_chat_id: str
    is_active: bool = True
    last_used_at: Optional[datetime] = None
    last_error: Optional[str] = None
    last_error_at: Optional[datetime] = None


class TeamsAccount(DBModel):
    """Microsoft Teams account connection for bot access."""
    id: Optional[UUID] = None
    user_id: UUID
    teams_user_id: Optional[str] = None
    teams_tenant_id: Optional[str] = None
    teams_service_url: str
    teams_conversation_id: str
    is_active: bool = True
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


class User(DBModel):
    """User model - combines auth.users data with profile data.

    This is a view model that combines data from Supabase auth.users
    and our profiles table. Used for compatibility with existing code.
    """
    id: Optional[UUID] = None
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None

    # From auth.users
    email: str = ""
    password_hash: Optional[str] = None  # Not stored, Supabase handles it
    auth_method: AuthMethod = AuthMethod.LINKEDIN_OAUTH

    # LinkedIn OAuth Data (from auth.users.raw_user_meta_data)
    linkedin_sub: Optional[str] = None
    linkedin_vanity_name: Optional[str] = None
    linkedin_name: Optional[str] = None
    linkedin_picture: Optional[str] = None

    # From profiles table
    account_type: AccountType = AccountType.GHOSTWRITER
    display_name: Optional[str] = None
    onboarding_status: OnboardingStatus = OnboardingStatus.PENDING
    onboarding_data: Dict[str, Any] = Field(default_factory=dict)
    company_id: Optional[UUID] = None

    # Fields migrated from customers table
    linkedin_url: Optional[str] = None
    writing_style_notes: Optional[str] = None
    metadata: Dict[str, Any] = Field(default_factory=dict)
    profile_picture: Optional[str] = None
    creator_email: Optional[str] = None
    customer_email: Optional[str] = None
    is_active: bool = True

    # Email verification (from auth.users)
    email_verified: bool = False
    email_verification_token: Optional[str] = None
    email_verification_expires_at: Optional[datetime] = None


class Company(DBModel):
    """Company model for company accounts."""
    id: Optional[UUID] = None
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None

    # Company Data
    name: str
    description: Optional[str] = None
    website: Optional[str] = None
    industry: Optional[str] = None

    # Strategy
    company_strategy: Dict[str, Any] = Field(default_factory=dict)

    owner_user_id: UUID
    onboarding_completed: bool = False

    # License key reference (limits are stored in license_keys table)
    license_key_id: Optional[UUID] = None


class Invitation(DBModel):
    """Invitation model for employee invitations."""
    id: Optional[UUID] = None
    created_at: Optional[datetime] = None

    email: str
    token: str
    expires_at: datetime

    company_id: UUID
    invited_by_user_id: UUID

    status: InvitationStatus = InvitationStatus.PENDING
    accepted_at: Optional[datetime] = None
    accepted_by_user_id: Optional[UUID] = None


class ExamplePost(DBModel):
    """Example post model for manual posts during onboarding."""
    id: Optional[UUID] = None
    user_id: UUID
    created_at: Optional[datetime] = None

    post_text: str
    source: str = "manual"  # 'manual' | 'reference_profile'
    source_linkedin_url: Optional[str] = None
    post_type_id: Optional[UUID] = None


class ReferenceProfile(DBModel):
    """Reference profile for scraping alternative LinkedIn profiles."""
    id: Optional[UUID] = None
    user_id: UUID
    created_at: Optional[datetime] = None

    linkedin_url: str
    name: Optional[str] = None
    posts_scraped: int = 0


# ==================== CONTENT MODELS ====================


class PostType(DBModel):
    """Post type model for categorizing different types of posts."""
    id: Optional[UUID] = None
    user_id: UUID
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None
    name: str
    description: Optional[str] = None
    identifying_hashtags: List[str] = Field(default_factory=list)
    identifying_keywords: List[str] = Field(default_factory=list)
    semantic_properties: Dict[str, Any] = Field(default_factory=dict)
    analysis: Optional[Dict[str, Any]] = None
    analysis_generated_at: Optional[datetime] = None
    analyzed_post_count: int = 0
    is_active: bool = True
    strategy_weight: float = 0.5


class LinkedInProfile(DBModel):
    """LinkedIn profile model."""
    id: Optional[UUID] = None
    user_id: UUID
    scraped_at: Optional[datetime] = None
    profile_data: Dict[str, Any]
    name: Optional[str] = None
    headline: Optional[str] = None
    summary: Optional[str] = None
    location: Optional[str] = None
    industry: Optional[str] = None


class LinkedInPost(DBModel):
    """LinkedIn post model."""
    id: Optional[UUID] = None
    user_id: UUID
    scraped_at: Optional[datetime] = None
    post_url: Optional[str] = None
    post_text: str
    post_date: Optional[datetime] = None
    likes: int = 0
    comments: int = 0
    shares: int = 0
    raw_data: Optional[Dict[str, Any]] = None
    # Post type classification fields
    post_type_id: Optional[UUID] = None
    classification_method: Optional[str] = None  # 'hashtag', 'keyword', 'semantic'
    classification_confidence: Optional[float] = None


class LinkedInPostInsightPost(DBModel):
    """LinkedIn post record for insights (separate from linkedin_posts)."""
    id: Optional[UUID] = None
    user_id: UUID
    linkedin_account_id: Optional[UUID] = None
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None

    post_urn: str
    post_url: Optional[str] = None
    post_text: Optional[str] = None
    post_date: Optional[datetime] = None
    author_username: Optional[str] = None

    total_reactions: int = 0
    likes: int = 0
    comments: int = 0
    shares: int = 0
    reactions_breakdown: Dict[str, Any] = Field(default_factory=dict)

    raw_data: Optional[Dict[str, Any]] = None
    first_seen_at: Optional[datetime] = None


class LinkedInPostInsightDaily(DBModel):
    """Daily snapshot of LinkedIn post insights."""
    id: Optional[UUID] = None
    user_id: UUID
    post_id: UUID
    snapshot_date: date
    total_reactions: int = 0
    likes: int = 0
    comments: int = 0
    shares: int = 0
    reactions_breakdown: Dict[str, Any] = Field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


class Topic(DBModel):
    """Topic model."""
    id: Optional[UUID] = None
    user_id: UUID
    created_at: Optional[datetime] = None
    title: str
    description: Optional[str] = None
    category: Optional[str] = None
    extracted_from_post_id: Optional[UUID] = None
    extraction_confidence: Optional[float] = None
    is_used: bool = False
    used_at: Optional[datetime] = None
    target_post_type_id: Optional[UUID] = None


class ProfileAnalysis(DBModel):
    """Profile analysis model."""
    id: Optional[UUID] = None
    user_id: UUID
    created_at: Optional[datetime] = None
    writing_style: Dict[str, Any]
    tone_analysis: Dict[str, Any]
    topic_patterns: Dict[str, Any]
    audience_insights: Dict[str, Any]
    full_analysis: Dict[str, Any]


class ResearchResult(DBModel):
    """Research result model."""
    id: Optional[UUID] = None
    user_id: UUID
    created_at: Optional[datetime] = None
    query: str
    results: Dict[str, Any]
    suggested_topics: List[Dict[str, Any]]
    source: str = "perplexity"
    target_post_type_id: Optional[UUID] = None


class ApiUsageLog(DBModel):
    """API usage log for tracking token usage and costs."""
    id: Optional[UUID] = None
    user_id: Optional[UUID] = None
    provider: str  # 'openai' | 'perplexity'
    model: str  # 'gpt-4o', 'gpt-4o-mini', 'sonar'
    operation: str  # 'post_creation', 'research', 'profile_analysis', etc.
    prompt_tokens: int = 0
    completion_tokens: int = 0
    total_tokens: int = 0
    estimated_cost_usd: float = 0.0
    created_at: Optional[datetime] = None


class MediaItem(BaseModel):
    """Single media item (image or video) for a post."""
    type: str  # "image" | "video"
    url: str
    order: int
    content_type: str  # MIME type (e.g., 'image/jpeg', 'video/mp4')
    uploaded_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
    metadata: Optional[Dict[str, Any]] = None


class GeneratedPost(DBModel):
    """Generated post model."""
    id: Optional[UUID] = None
    user_id: UUID
    created_at: Optional[datetime] = None
    topic_id: Optional[UUID] = None
    topic_title: str
    post_content: str
    iterations: int = 0
    writer_versions: List[str] = Field(default_factory=list)
    critic_feedback: List[Dict[str, Any]] = Field(default_factory=list)
    status: str = "draft"  # draft, approved, ready, scheduled, published, rejected
    approved_at: Optional[datetime] = None
    published_at: Optional[datetime] = None
    post_type_id: Optional[UUID] = None
    # Media (multi-media support)
    media_items: List[MediaItem] = Field(default_factory=list)
    # DEPRECATED: Image (kept for backward compatibility)
    image_url: Optional[str] = None
    # Scheduling fields
    scheduled_at: Optional[datetime] = None
    scheduled_by_user_id: Optional[UUID] = None
    # Metadata for additional info (e.g., LinkedIn post URL, auto-posting status)
    metadata: Optional[Dict[str, Any]] = None

    @property
    def has_media(self) -> bool:
        """Check if post has any media items."""
        return len(self.media_items) > 0


# ==================== LICENSE KEY MODELS ====================


class LicenseKey(DBModel):
    """License key for company registration."""
    id: Optional[UUID] = None
    key: str
    description: Optional[str] = None

    # Limits
    max_employees: int = 5
    daily_token_limit: Optional[int] = None  # None = unlimited

    # Usage
    used: bool = False
    company_id: Optional[UUID] = None
    used_at: Optional[datetime] = None

    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


class LicenseKeyOffer(DBModel):
    """MOCO offer created for a license key."""
    id: Optional[UUID] = None
    license_key_id: UUID
    moco_offer_id: int
    moco_offer_identifier: Optional[str] = None
    moco_offer_url: Optional[str] = None
    offer_title: Optional[str] = None
    company_name: Optional[str] = None
    price: Optional[float] = None
    payment_frequency: Optional[str] = None
    status: str = "draft"
    created_at: Optional[datetime] = None


class CompanyDailyQuota(DBModel):
    """Daily usage quota for a company."""
    id: Optional[UUID] = None
    company_id: UUID
    date: date
    tokens_used: int = 0
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


class EmployeeCompanyPermissions(DBModel):
    """Permissions granted by an employee to their company."""
    id: Optional[UUID] = None
    user_id: UUID
    company_id: UUID
    can_create_posts: bool = True
    can_view_posts: bool = True
    can_edit_posts: bool = True
    can_schedule_posts: bool = True
    can_manage_post_types: bool = True
    can_do_research: bool = True
    can_see_in_calendar: bool = True
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None
