"""
Pydantic schemas for Unified Document Model.

These schemas validate JSONFields for the unified Document model where
everything is a "document" with category-specific behavior (like Notion).

Category configs are defined in field_options.yaml under document_categories.
Each category has its own metadata schema for type-safe JSONField validation.

Usage:
    from lightwave.schema.pydantic.models.documents import (
        get_metadata_schema,
        DocumentMetadataSchema,
        LegalMetadataSchema,
        BlogMetadataSchema,
    )

    # Get schema for category dynamically
    schema_class = get_metadata_schema("legal")
    validated = schema_class(**raw_metadata)
"""

from __future__ import annotations

from typing import Any, Literal

from pydantic import Field

from lightwave.schema.pydantic.core.base import JSONFieldSchema

# =============================================================================
# DOCUMENT CATEGORY CONFIG SCHEMA
# =============================================================================


class DocumentCategoryConfigSchema(JSONFieldSchema):
    """
    Schema for document category configuration from field_options.yaml.

    Each category has config defining its behavior:
    - versioning: optional | required
    - approval_required: bool
    - compliance_audit: bool
    - public_facing: bool
    - immutable_versions: bool (legal only)
    - retention_required: bool (legal only)
    """

    versioning: Literal["optional", "required"] = "optional"
    approval_required: bool = False
    compliance_audit: bool = False
    public_facing: bool = False
    immutable_versions: bool = False
    retention_required: bool = False


# =============================================================================
# BASE DOCUMENT METADATA SCHEMA
# =============================================================================


class BaseDocumentMetadataSchema(JSONFieldSchema):
    """
    Base metadata schema common to all document categories.

    All documents share these core metadata fields. Category-specific
    schemas inherit and extend this base.
    """

    # Content metadata
    title: str = Field(..., min_length=1, max_length=500, description="Document title")
    slug: str = Field(..., min_length=1, max_length=200, description="URL-friendly slug")
    summary: str = Field("", max_length=2000, description="Brief summary/description")
    language: str = Field("en", description="ISO 639-1 language code")

    # Organization
    tags: list[str] = Field(default_factory=list, description="Tags for organization")
    collections: list[str] = Field(default_factory=list, description="Collections this document belongs to")

    # SEO (for public-facing documents)
    seo_title: str | None = Field(None, max_length=70, description="SEO title override")
    seo_description: str | None = Field(None, max_length=160, description="SEO meta description")

    # Author/Attribution
    author_name: str | None = Field(None, description="Display author name")
    author_url: str | None = Field(None, description="Author profile URL")

    # Dates
    published_at: str | None = Field(None, description="ISO 8601 datetime when published")
    last_edited_at: str | None = Field(None, description="ISO 8601 datetime of last edit")

    # Media
    featured_image_url: str | None = Field(None, description="Featured/hero image URL")
    thumbnail_url: str | None = Field(None, description="Thumbnail image URL")

    # Extensible
    custom: dict[str, Any] = Field(default_factory=dict, description="Custom metadata for tenant-specific needs")


# =============================================================================
# KNOWLEDGE BASE METADATA
# =============================================================================


class KnowledgeMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for knowledge/second brain documents.

    Knowledge documents are personal notes, research, references.
    They emphasize linking and organization over publication.
    """

    # Knowledge-specific fields
    source_url: str | None = Field(None, description="Original source URL (if clipped)")
    source_type: str | None = Field(None, description="Type: article, book, video, podcast, conversation")

    # Linking (for graph database support)
    links_to: list[str] = Field(default_factory=list, description="Document IDs this links to")
    backlinks: list[str] = Field(default_factory=list, description="Document IDs linking to this (auto-populated)")

    # Status
    review_status: str = Field("inbox", description="Processing status: inbox, processing, processed, archived")
    importance: int = Field(0, ge=0, le=5, description="Importance rating 0-5")

    # AI processing
    ai_summary: str | None = Field(None, description="AI-generated summary")
    ai_tags: list[str] = Field(default_factory=list, description="AI-generated tags")
    embeddings_generated: bool = Field(False, description="Whether embeddings have been generated")


# =============================================================================
# LEGAL DOCUMENT METADATA
# =============================================================================


class LegalMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for legal documents (terms, privacy, contracts).

    Legal documents require strict compliance tracking:
    - Versioning is REQUIRED (not optional)
    - Approval workflow is REQUIRED
    - Compliance audit trail
    - Immutable version history
    - Re-acceptance tracking
    """

    # Legal-specific required fields
    document_type: str = Field(
        ...,
        description="Type from legal_document_types (terms_of_service, privacy_policy, etc.)",
    )
    version: str = Field(..., description="Semantic version (e.g., '2.1.0')")
    effective_date: str = Field(..., description="ISO 8601 date when document takes effect")

    # Jurisdiction
    jurisdiction: str = Field("us_california", description="Primary jurisdiction (from legal.yaml)")
    jurisdictions_applicable: list[str] = Field(default_factory=list, description="All applicable jurisdictions")

    # Compliance
    compliance_frameworks: list[str] = Field(
        default_factory=list,
        description="Applicable frameworks (gdpr, ccpa, etc.)",
    )
    gdpr_lawful_basis: str | None = Field(None, description="GDPR lawful basis for processing")

    # Dates
    expiration_date: str | None = Field(None, description="ISO 8601 date when document expires")
    last_reviewed_at: str | None = Field(None, description="ISO 8601 date of last legal review")
    next_review_date: str | None = Field(None, description="ISO 8601 date when review is due")

    # Approval tracking
    approved_by: str | None = Field(None, description="User ID who approved")
    approved_at: str | None = Field(None, description="ISO 8601 datetime of approval")
    requires_legal_review: bool = Field(True, description="Whether legal review is required")

    # Version tracking
    previous_version_id: str | None = Field(None, description="Document ID of previous version")
    re_acceptance_required: bool = Field(False, description="Whether users must re-accept after changes")
    change_summary: str = Field("", description="Summary of changes from previous version")
    change_type: str = Field("minor", description="Change type: create, minor, major, legal_update")

    # Translations
    translations: dict[str, str] = Field(
        default_factory=dict,
        description="Map of language code to translated document ID",
    )

    # Sections tracking (for section-level compliance)
    sections_count: int = Field(0, ge=0, description="Number of sections")
    sections_requiring_review: list[str] = Field(default_factory=list, description="Section IDs requiring legal review")


# =============================================================================
# BLOG POST METADATA
# =============================================================================


class BlogMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for blog posts and articles.

    Blog posts are public-facing content with strong SEO
    and social sharing requirements.
    """

    # Blog-specific fields
    category: str = Field("general", description="Blog category")
    reading_time_minutes: int | None = Field(None, ge=1, description="Estimated reading time")

    # Series support
    series_name: str | None = Field(None, description="Name of blog series")
    series_order: int | None = Field(None, ge=1, description="Position in series")

    # Social
    social_image_url: str | None = Field(None, description="Image for social sharing")
    twitter_card_type: str = Field("summary_large_image", description="Twitter card type")

    # Comments
    comments_enabled: bool = Field(True, description="Whether comments are enabled")
    comment_count: int = Field(0, ge=0, description="Number of comments")

    # Engagement metrics (for analytics)
    view_count: int = Field(0, ge=0, description="View count")
    share_count: int = Field(0, ge=0, description="Share count")

    # Scheduling
    scheduled_publish_at: str | None = Field(None, description="ISO 8601 datetime for scheduled publish")

    # RSS
    include_in_rss: bool = Field(True, description="Include in RSS feed")

    # AI assistance
    ai_generated: bool = Field(False, description="Whether AI-assisted in writing")
    ai_disclosure: str | None = Field(None, description="AI usage disclosure statement")


# =============================================================================
# MARKETING CONTENT METADATA
# =============================================================================


class MarketingMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for marketing content (landing pages, campaigns).

    Marketing content emphasizes conversion tracking and
    A/B testing capabilities.
    """

    # Campaign tracking
    campaign_id: str | None = Field(None, description="Associated campaign ID")
    campaign_name: str | None = Field(None, description="Campaign name")
    utm_source: str | None = Field(None, description="UTM source")
    utm_medium: str | None = Field(None, description="UTM medium")
    utm_campaign: str | None = Field(None, description="UTM campaign")

    # Conversion
    cta_text: str | None = Field(None, description="Primary CTA text")
    cta_url: str | None = Field(None, description="Primary CTA destination")
    conversion_goal: str | None = Field(None, description="Goal: signup, purchase, demo, contact")

    # A/B Testing
    variant_id: str | None = Field(None, description="A/B test variant ID")
    variant_name: str | None = Field(None, description="Variant name (A, B, Control)")
    test_id: str | None = Field(None, description="A/B test ID")

    # Audience
    target_audience: str | None = Field(None, description="Target audience segment")
    personalization_rules: dict[str, Any] = Field(default_factory=dict, description="Personalization configuration")

    # Dates
    campaign_start_date: str | None = Field(None, description="Campaign start date")
    campaign_end_date: str | None = Field(None, description="Campaign end date")

    # Performance
    impression_count: int = Field(0, ge=0, description="Impression count")
    click_count: int = Field(0, ge=0, description="Click count")
    conversion_count: int = Field(0, ge=0, description="Conversion count")


# =============================================================================
# FEATURE/PRODUCT METADATA
# =============================================================================


class FeatureMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for feature/product content (copywriting, sales).

    Feature content describes product capabilities and is used
    across multiple touchpoints (website, docs, sales).
    """

    # Product association
    product_id: str | None = Field(None, description="Associated product ID")
    product_name: str | None = Field(None, description="Product name")
    feature_id: str | None = Field(None, description="Feature ID in product")

    # Categorization
    feature_category: str | None = Field(None, description="Category: core, premium, enterprise, addon")
    pricing_tier: str | None = Field(None, description="Tier: free, starter, pro, enterprise")

    # Content variants
    headline: str | None = Field(None, max_length=100, description="Short headline")
    tagline: str | None = Field(None, max_length=200, description="Marketing tagline")
    benefit_statement: str | None = Field(None, description="Key benefit statement")
    use_cases: list[str] = Field(default_factory=list, description="Use case examples")

    # Comparison
    competitors_compared: list[str] = Field(default_factory=list, description="Competitor names for comparison")
    differentiators: list[str] = Field(default_factory=list, description="Key differentiators")

    # Status
    availability: str = Field("available", description="Status: available, beta, coming_soon, deprecated")
    release_date: str | None = Field(None, description="Feature release date")


# =============================================================================
# SUPPORT/HELP METADATA
# =============================================================================


class SupportMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for support/help documentation.

    Help docs emphasize discoverability, versioning by product version,
    and feedback collection.
    """

    # Help-specific categorization
    help_category: str = Field("general", description="Help category")
    difficulty_level: str = Field("beginner", description="Level: beginner, intermediate, advanced")

    # Product versioning
    product_version: str | None = Field(None, description="Product version this applies to")
    applies_to_versions: list[str] = Field(default_factory=list, description="All applicable versions")

    # Related content
    prerequisites: list[str] = Field(default_factory=list, description="Prerequisite document IDs")
    related_articles: list[str] = Field(default_factory=list, description="Related article IDs")
    next_steps: list[str] = Field(default_factory=list, description="Next step document IDs")

    # Feedback
    helpful_count: int = Field(0, ge=0, description="'Was this helpful' yes count")
    not_helpful_count: int = Field(0, ge=0, description="'Was this helpful' no count")
    feedback_comments: list[dict[str, Any]] = Field(default_factory=list, description="User feedback comments")

    # Search optimization
    search_keywords: list[str] = Field(default_factory=list, description="Additional search keywords")
    common_questions: list[str] = Field(default_factory=list, description="Common questions this answers")

    # Video/media
    video_url: str | None = Field(None, description="Tutorial video URL")
    video_duration_seconds: int | None = Field(None, description="Video duration")


# =============================================================================
# INTERNAL DOCUMENT METADATA
# =============================================================================


class InternalMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for internal documentation (SOPs, team docs).

    Internal docs emphasize access control, ownership,
    and review cycles.
    """

    # Ownership
    owner_team: str | None = Field(None, description="Owning team")
    owner_user_id: str | None = Field(None, description="Primary owner user ID")
    stakeholders: list[str] = Field(default_factory=list, description="Stakeholder user IDs")

    # Access control
    visibility: str = Field("team", description="Visibility: team, department, company, restricted")
    restricted_to_teams: list[str] = Field(default_factory=list, description="Teams with access (if restricted)")
    restricted_to_roles: list[str] = Field(default_factory=list, description="Roles with access (if restricted)")

    # Document type
    internal_type: str = Field("documentation", description="Type: sop, policy, runbook, meeting_notes, decision")

    # Review
    review_cycle_days: int | None = Field(None, ge=1, description="Days between required reviews")
    last_reviewed_by: str | None = Field(None, description="User ID of last reviewer")
    review_due_date: str | None = Field(None, description="Next review due date")

    # Status
    document_status: str = Field("current", description="Status: current, needs_update, deprecated, archived")
    deprecation_reason: str | None = Field(None, description="Why deprecated")
    superseded_by: str | None = Field(None, description="Document ID that replaces this")


# =============================================================================
# EMAIL TEMPLATE METADATA
# =============================================================================


class EmailTemplateMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for email templates.

    Email templates require versioning and approval for compliance,
    plus tracking for campaigns.
    """

    # Email-specific fields
    email_type: str = Field(..., description="Type: transactional, marketing, notification, support")
    subject_line: str = Field(..., max_length=200, description="Email subject line")
    preview_text: str | None = Field(None, max_length=150, description="Email preview text")

    # Sender
    from_name: str = Field(..., description="From name")
    from_email: str = Field(..., description="From email address")
    reply_to: str | None = Field(None, description="Reply-to address")

    # Template variables
    variables: list[str] = Field(
        default_factory=list,
        description="Template variables (e.g., ['first_name', 'company'])",
    )
    required_variables: list[str] = Field(default_factory=list, description="Required variables")

    # Compliance
    unsubscribe_required: bool = Field(True, description="Whether unsubscribe link is required")
    contains_marketing: bool = Field(False, description="Whether template contains marketing content")
    can_spam_compliant: bool = Field(True, description="CAN-SPAM compliance status")

    # Testing
    test_recipients: list[str] = Field(default_factory=list, description="Test recipient emails")
    last_tested_at: str | None = Field(None, description="Last test send datetime")


# =============================================================================
# CONSTITUTION SYSTEM METADATA - Programmable Prompts
# =============================================================================


class PromptMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for programmable Claude prompt templates.

    Prompts are database-driven templates that replace static .claude/prompts/*.md
    files. They support variables, priority-based context assembly, and agent targeting.
    """

    # Prompt configuration
    prompt_type: str = Field(
        "system",
        description="Type: system, agent, skill, hook, roadmap",
    )
    version: str = Field("1.0.0", description="Semantic version of the prompt")
    variables: list[str] = Field(
        default_factory=list,
        description="Template variables (e.g., ['task_id', 'sprint_name'])",
    )

    # Context assembly
    priority: int = Field(
        100,
        ge=0,
        le=1000,
        description="Priority in context assembly (higher = more important)",
    )
    max_tokens: int | None = Field(
        None,
        ge=100,
        description="Token budget limit for this prompt",
    )
    applies_to_agents: list[str] = Field(
        default_factory=list,
        description="Agent types this prompt applies to (empty = all)",
    )

    # Enrichment tracking
    last_validated_at: str | None = Field(
        None,
        description="ISO 8601 datetime of last validation by enrichment workflow",
    )
    validation_status: str = Field(
        "pending",
        description="Status: pending, valid, stale, failed, needs_approval",
    )
    linked_files: list[str] = Field(
        default_factory=list,
        description="File paths this prompt references (for validation)",
    )
    linked_documents: list[str] = Field(
        default_factory=list,
        description="Document IDs this prompt links to",
    )

    # Migration tracking
    source_path: str | None = Field(
        None,
        description="Original file path if migrated from .claude/",
    )
    migrated_at: str | None = Field(
        None,
        description="ISO 8601 datetime when migrated to database",
    )


class RuleMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for behavioral rules that constrain Claude.

    Rules are database-driven replacements for .claude/rules/*.md files.
    They define constraints, overrides, and conflict resolution.
    """

    # Rule configuration
    domain: str = Field(
        "general",
        description="Rule domain: general, security, testing, git, sst, agents",
    )
    priority: int = Field(
        100,
        ge=0,
        le=1000,
        description="Priority (higher = more weight in conflicts)",
    )
    applies_to_agents: list[str] = Field(
        default_factory=list,
        description="Agent types this rule applies to (empty = all)",
    )

    # Conflict resolution
    conflicts_with: list[str] = Field(
        default_factory=list,
        description="Rule IDs this conflicts with",
    )
    overrides: list[str] = Field(
        default_factory=list,
        description="Rule IDs this overrides (if both apply)",
    )

    # Validation
    last_validated_at: str | None = Field(
        None,
        description="ISO 8601 datetime of last validation",
    )
    validation_status: str = Field(
        "pending",
        description="Status: pending, valid, stale, failed",
    )
    linked_files: list[str] = Field(
        default_factory=list,
        description="File paths this rule references",
    )

    # Migration tracking
    source_path: str | None = Field(
        None,
        description="Original file path if migrated from .claude/rules/",
    )


class ReferenceMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for reference documentation used by Claude.

    References are database-driven replacements for .claude/reference/*.md files.
    They provide context for specific topics, standards, and troubleshooting.
    """

    # Reference configuration
    reference_type: str = Field(
        "documentation",
        description="Type: documentation, standard, troubleshooting, architecture, api",
    )
    priority: int = Field(
        50,
        ge=0,
        le=1000,
        description="Priority in context assembly",
    )

    # Relevance scoring
    topics: list[str] = Field(
        default_factory=list,
        description="Topics this reference covers (for semantic matching)",
    )
    keywords: list[str] = Field(
        default_factory=list,
        description="Keywords for search and matching",
    )

    # Linking
    linked_files: list[str] = Field(
        default_factory=list,
        description="File paths this reference documents",
    )
    linked_documents: list[str] = Field(
        default_factory=list,
        description="Related document IDs",
    )

    # Validation
    last_validated_at: str | None = Field(None)
    validation_status: str = Field("pending")

    # Migration
    source_path: str | None = Field(None)


class AgentDefinitionMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for agent system prompts and configuration.

    Agent definitions replace .claude/agents/*.md files with database-driven
    configuration that can be updated without code changes.
    """

    # Agent configuration
    agent_type: str = Field(
        ...,
        description="Unique agent identifier (e.g., 'software-architect')",
    )
    model_preference: str = Field(
        "default",
        description="Preferred model: default, sonnet, opus, haiku",
    )

    # Routing
    trigger_patterns: list[str] = Field(
        default_factory=list,
        description="User intent patterns that trigger this agent",
    )
    capabilities: list[str] = Field(
        default_factory=list,
        description="Agent capabilities (for tool access)",
    )
    tools_allowed: list[str] = Field(
        default_factory=list,
        description="Tools this agent can use",
    )

    # Context
    priority: int = Field(
        100,
        description="Priority in agent selection",
    )
    max_context_tokens: int | None = Field(
        None,
        description="Max tokens for this agent's context",
    )

    # Validation
    last_validated_at: str | None = Field(None)
    validation_status: str = Field("pending")
    source_path: str | None = Field(None)


class SkillDefinitionMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for skill/command instructions.

    Skills replace .claude/skills/*.md files with database-driven
    procedural instructions for specific operations.
    """

    # Skill configuration
    command: str = Field(
        ...,
        description="Slash command (e.g., '/ecs-deploy')",
    )
    aliases: list[str] = Field(
        default_factory=list,
        description="Alternative commands",
    )

    # Execution
    steps: list[str] = Field(
        default_factory=list,
        description="Step IDs or descriptions for procedure",
    )
    prerequisites: list[str] = Field(
        default_factory=list,
        description="Required conditions before execution",
    )

    # Context
    priority: int = Field(100)
    applies_to_agents: list[str] = Field(default_factory=list)

    # Validation
    last_validated_at: str | None = Field(None)
    validation_status: str = Field("pending")
    source_path: str | None = Field(None)


# =============================================================================
# TEST BREADCRUMB METADATA
# =============================================================================


class TestBreadcrumbMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for test failure breadcrumbs.

    Breadcrumbs capture context from test failures to guide future Claude sessions.
    They remain until manually resolved, providing continuity across sessions.
    """

    # Test identification
    test_file: str = Field(
        ...,
        description="Path to the failing test file",
    )
    test_function: str = Field(
        ...,
        description="Name of the failing test function",
    )
    test_class: str | None = Field(
        None,
        description="Test class name (if applicable)",
    )

    # Failure details
    failure_type: str = Field(
        "assertion",
        description="Type: assertion, exception, timeout, setup, teardown, import_error, type_error",
    )
    error_message: str = Field(
        "",
        max_length=500,
        description="Captured error message (truncated)",
    )
    stack_trace: str = Field(
        "",
        max_length=2000,
        description="Truncated stack trace",
    )

    # Context
    related_files: list[str] = Field(
        default_factory=list,
        description="Files involved in the failure",
    )
    git_branch: str | None = Field(
        None,
        description="Git branch when failure occurred",
    )
    git_commit: str | None = Field(
        None,
        description="Git commit SHA when failure occurred",
    )

    # Resolution tracking (retained until resolved)
    resolved: bool = Field(
        False,
        description="Whether this breadcrumb has been resolved",
    )
    resolved_at: str | None = Field(
        None,
        description="ISO 8601 datetime when resolved",
    )
    resolved_by: str | None = Field(
        None,
        description="User ID who resolved",
    )
    resolution_notes: str = Field(
        "",
        description="Notes about how the issue was resolved",
    )

    # Linking
    linked_task_id: str | None = Field(
        None,
        description="createOS Task this breadcrumb applies to",
    )
    linked_session_id: str | None = Field(
        None,
        description="Claude session where failure occurred",
    )

    # Guidance for future sessions
    suggested_fixes: list[str] = Field(
        default_factory=list,
        description="AI-suggested fixes for future sessions",
    )
    what_was_tried: list[str] = Field(
        default_factory=list,
        description="Approaches already attempted",
    )


# =============================================================================
# PRODUCT SHOWCASE METADATA
# =============================================================================


class ProductMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for product showcase documents (CineOS, CreateOS, etc.).

    Product documents describe product capabilities and are used across
    marketing, docs, and sales touchpoints.
    """

    # Product identification
    product_id: str = Field(..., description="Unique product identifier (e.g., 'cineos')")
    tagline: str = Field("", max_length=200, description="Marketing tagline")
    logo_url: str | None = Field(None, description="Product logo URL")
    hero_image_url: str | None = Field(None, description="Hero/banner image URL")

    # Features and capabilities
    features: list[str] = Field(default_factory=list, description="Key feature highlights")
    pricing_tier_id: str | None = Field(None, description="Link to pricing_tier document ID")

    # CTA
    cta_text: str = Field("Get Started", max_length=50, description="Primary CTA button text")
    cta_url: str = Field("", description="Primary CTA destination URL")

    # Targeting
    target_audience: str = Field("", description="Target audience description")

    # Status
    product_status: str = Field(
        "active",
        description="Product availability: active, beta, coming_soon, deprecated",
    )


# =============================================================================
# TEAM MEMBER METADATA
# =============================================================================


class TeamMemberMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for team member profile documents.

    Team member documents represent people in the organization for
    about pages, team directories, and author attribution.
    """

    # Role and organization
    role: str = Field(..., description="Job title or role")
    department: str | None = Field(None, description="Department name")
    bio: str = Field("", description="Biography/about text")

    # Media
    avatar_url: str = Field("", description="Profile photo URL")

    # Social links
    linkedin_url: str | None = Field(None, description="LinkedIn profile URL")
    twitter_url: str | None = Field(None, description="Twitter/X profile URL")
    github_url: str | None = Field(None, description="GitHub profile URL")

    # Display order
    order: int = Field(0, ge=0, description="Sort order for display")

    # Status
    is_active: bool = Field(True, description="Whether team member is currently active")


# =============================================================================
# TESTIMONIAL METADATA
# =============================================================================


class TestimonialMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for customer testimonial documents.

    Testimonials capture customer quotes, case studies, and
    social proof for marketing pages.
    """

    # Quote content
    quote: str = Field(..., description="The testimonial quote text")

    # Author information
    author_name: str = Field(..., description="Name of the person giving testimonial")
    author_role: str = Field("", description="Author's job title/role")
    author_company: str = Field("", description="Author's company name")
    author_avatar_url: str | None = Field(None, description="Author's photo URL")

    # Attribution
    product_id: str | None = Field(None, description="Which product this testimonial is for")
    company_logo_url: str | None = Field(None, description="Company logo URL")

    # Rating
    rating: int | None = Field(None, ge=1, le=5, description="Star rating 1-5")

    # Display
    featured: bool = Field(False, description="Whether to feature prominently")
    order: int = Field(0, ge=0, description="Sort order for display")


# =============================================================================
# FAQ ITEM METADATA
# =============================================================================


class FAQItemMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for FAQ (frequently asked question) documents.

    FAQ items are used in help centers, support pages, and
    product documentation.
    """

    # Question and answer
    question: str = Field(..., description="The FAQ question")
    answer: str = Field(..., description="The FAQ answer (Markdown supported)")

    # Organization
    faq_category: str = Field(
        "general",
        description="FAQ category: general, billing, technical, getting-started, account",
    )
    product_id: str | None = Field(None, description="Which product this FAQ is for")

    # Display
    order: int = Field(0, ge=0, description="Sort order within category")

    # Search optimization
    search_keywords: list[str] = Field(
        default_factory=list,
        description="Additional keywords for search",
    )


# =============================================================================
# PRICING TIER METADATA
# =============================================================================


class PricingTierMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for pricing tier documents.

    Pricing tiers define subscription plans and their features
    for pricing pages and checkout flows.
    """

    # Product association
    product_id: str = Field(..., description="Which product this pricing is for")

    # Tier identification
    tier_name: str = Field(..., description="Tier identifier: starter, pro, enterprise")
    tier_display_name: str = Field("", description="Display name for the tier")

    # Pricing
    price_monthly: int | None = Field(None, ge=0, description="Monthly price in cents")
    price_yearly: int | None = Field(None, ge=0, description="Yearly price in cents")
    currency: str = Field("usd", description="Currency code")

    # Features included
    features: list[str] = Field(default_factory=list, description="List of included features")
    limits: dict[str, int | None] = Field(
        default_factory=dict,
        description="Usage limits (e.g., {'users': 10, 'storage_gb': 100})",
    )

    # CTA
    cta_text: str = Field("Get Started", max_length=50, description="CTA button text")
    cta_url: str = Field("", description="CTA destination URL")

    # Display
    highlighted: bool = Field(False, description="Whether to highlight as recommended")
    custom_pricing: bool = Field(False, description="Whether pricing is custom/contact-us")
    badge_text: str | None = Field(None, description="Badge text (e.g., 'Most Popular')")
    order: int = Field(0, ge=0, description="Sort order for display")

    # Stripe integration
    stripe_price_id_monthly: str | None = Field(None, description="Stripe price ID for monthly")
    stripe_price_id_yearly: str | None = Field(None, description="Stripe price ID for yearly")


# =============================================================================
# NEWSLETTER ISSUE METADATA
# =============================================================================


class NewsletterIssueMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for newsletter issue documents.

    Newsletter issues are email campaign content that can be linked
    to Campaign records for delivery tracking.
    """

    # Email content
    subject_line: str = Field(..., max_length=200, description="Email subject line")
    preview_text: str = Field("", max_length=150, description="Email preview/preheader text")

    # Campaign linkage
    campaign_id: str | None = Field(None, description="Linked Campaign record ID")

    # Schedule and delivery
    scheduled_for: str | None = Field(None, description="ISO 8601 datetime for scheduled send")
    sent_at: str | None = Field(None, description="ISO 8601 datetime when sent")

    # Analytics
    recipient_count: int = Field(0, ge=0, description="Number of recipients")
    open_count: int = Field(0, ge=0, description="Number of opens")
    click_count: int = Field(0, ge=0, description="Number of clicks")
    open_rate: float | None = Field(None, ge=0, le=1, description="Open rate (0-1)")
    click_rate: float | None = Field(None, ge=0, le=1, description="Click rate (0-1)")

    # Issue identification
    issue_number: int | None = Field(None, ge=1, description="Newsletter issue number")
    series_name: str | None = Field(None, description="Newsletter series name")


# =============================================================================
# CODE-DERIVED DOCUMENTATION METADATA (Auto-generated from @sst_spec)
# =============================================================================


class APIReferenceMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for auto-generated API documentation.

    API reference documents are automatically generated from code decorated
    with @sst_spec and Django-Ninja OpenAPI schemas. They track source
    file locations for staleness detection.
    """

    # Source tracking (links back to code)
    spec_id: str = Field(..., description="@sst_spec identifier (e.g., 'API-AUTH-001')")
    spec_file: str | None = Field(None, description="SST YAML file this spec references")
    spec_section: str | None = Field(None, description="Section within the spec file")
    source_file: str = Field(..., description="Python source file path")
    source_line: int = Field(..., ge=1, description="Line number in source file")
    source_hash: str = Field(..., description="Hash of source file for staleness detection")

    # API-specific fields
    http_method: str | None = Field(None, description="HTTP method (GET, POST, PUT, DELETE, etc.)")
    endpoint_path: str | None = Field(None, description="API endpoint path (e.g., /api/v1/users)")
    request_schema: dict | None = Field(None, description="Request body schema (JSON Schema)")
    response_schema: dict | None = Field(None, description="Response schema (JSON Schema)")
    openapi_operation_id: str | None = Field(None, description="OpenAPI operationId")
    openapi_tags: list[str] = Field(default_factory=list, description="OpenAPI tags")

    # Generation tracking
    generated_at: str = Field(..., description="ISO 8601 datetime of generation")
    is_stale: bool = Field(False, description="True if source changed since generation")


class IntegrationGuideMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for integration guides.

    Integration guides are how-to documents extracted from @sst_spec
    decorated code, explaining how to use specific integrations.
    """

    # Source tracking
    spec_id: str = Field(..., description="@sst_spec identifier")
    spec_file: str | None = Field(None, description="SST YAML file reference")
    source_file: str = Field(..., description="Python source file path")
    source_hash: str = Field(..., description="Hash for staleness detection")

    # Guide-specific fields
    integration_type: str = Field(..., description="Type of integration (webhook, oauth, api)")
    external_service: str | None = Field(None, description="External service name (e.g., 'Stripe', 'Google')")
    prerequisites: list[str] = Field(default_factory=list, description="Prerequisites for this integration")
    related_guides: list[str] = Field(default_factory=list, description="Related guide document IDs")

    # Generation tracking
    generated_at: str = Field(..., description="ISO 8601 datetime of generation")
    is_stale: bool = Field(False, description="True if source changed since generation")


class DeveloperDocsMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for developer documentation.

    Developer docs are technical documentation extracted from docstrings,
    YAML SST definitions, and code architecture.
    """

    # Source tracking
    spec_id: str | None = Field(None, description="@sst_spec identifier if from decorated code")
    source_file: str | None = Field(None, description="Primary source file path")
    source_module: str | None = Field(None, description="Python module path")
    source_hash: str | None = Field(None, description="Hash for staleness detection")

    # Doc-specific fields
    doc_type: str = Field("general", description="Type: architecture, module, class, function, guide")
    audience: str = Field("developer", description="Target audience: developer, admin, integrator")
    difficulty: str = Field("intermediate", description="Difficulty: beginner, intermediate, advanced")
    related_docs: list[str] = Field(default_factory=list, description="Related document IDs")
    code_examples: list[dict] = Field(default_factory=list, description="Code examples with language and content")

    # Generation tracking
    generated_at: str | None = Field(None, description="ISO 8601 datetime of generation (None if manual)")
    is_stale: bool = Field(False, description="True if source changed since generation")


class AgentReferenceMetadataSchema(BaseDocumentMetadataSchema):
    """
    Metadata for AI agent reference documentation.

    Agent reference docs are optimized for AI agent consumption, with
    structured data about capabilities, tools, and usage patterns.
    """

    # Source tracking
    spec_id: str | None = Field(None, description="@sst_spec identifier")
    source_file: str | None = Field(None, description="Source file path")
    source_hash: str | None = Field(None, description="Hash for staleness detection")

    # Agent-specific fields
    agent_type: str | None = Field(None, description="Agent type this doc is for")
    tool_name: str | None = Field(None, description="Tool or capability being documented")
    input_schema: dict | None = Field(None, description="Input schema (JSON Schema)")
    output_schema: dict | None = Field(None, description="Output schema (JSON Schema)")
    examples: list[dict] = Field(default_factory=list, description="Usage examples with input/output")
    constraints: list[str] = Field(default_factory=list, description="Constraints or limitations")
    related_tools: list[str] = Field(default_factory=list, description="Related tool names")

    # Generation tracking
    generated_at: str | None = Field(None, description="ISO 8601 datetime of generation")
    is_stale: bool = Field(False, description="True if source changed since generation")


# =============================================================================
# SCHEMA FACTORY
# =============================================================================

# Map category values to their schema classes
CATEGORY_SCHEMA_MAP: dict[str, type[BaseDocumentMetadataSchema]] = {
    # Original categories
    "knowledge": KnowledgeMetadataSchema,
    "legal": LegalMetadataSchema,
    "blog": BlogMetadataSchema,
    "marketing": MarketingMetadataSchema,
    "feature": FeatureMetadataSchema,
    "support": SupportMetadataSchema,
    "internal": InternalMetadataSchema,
    "email_template": EmailTemplateMetadataSchema,
    # Constitution System categories (Claude context)
    "prompt": PromptMetadataSchema,
    "rule": RuleMetadataSchema,
    "reference": ReferenceMetadataSchema,
    "agent_definition": AgentDefinitionMetadataSchema,
    "skill_definition": SkillDefinitionMetadataSchema,
    "test_breadcrumb": TestBreadcrumbMetadataSchema,
    # LightWave Media Marketing categories
    "product": ProductMetadataSchema,
    "team_member": TeamMemberMetadataSchema,
    "testimonial": TestimonialMetadataSchema,
    "faq_item": FAQItemMetadataSchema,
    "pricing_tier": PricingTierMetadataSchema,
    "newsletter_issue": NewsletterIssueMetadataSchema,
    # Code-Derived Documentation categories (auto-generated from @sst_spec)
    "api_reference": APIReferenceMetadataSchema,
    "integration_guide": IntegrationGuideMetadataSchema,
    "developer_docs": DeveloperDocsMetadataSchema,
    "agent_reference": AgentReferenceMetadataSchema,
}


def get_metadata_schema(category: str) -> type[BaseDocumentMetadataSchema]:
    """
    Get the metadata schema class for a document category.

    Args:
        category: Document category from document_categories field option.

    Returns:
        The appropriate schema class for the category.

    Raises:
        ValueError: If category is not recognized.

    Example:
        >>> schema_class = get_metadata_schema("legal")
        >>> validated = schema_class(**raw_metadata)
    """
    if category not in CATEGORY_SCHEMA_MAP:
        valid = ", ".join(sorted(CATEGORY_SCHEMA_MAP.keys()))
        raise ValueError(f"Unknown document category: {category}. Valid: {valid}")

    return CATEGORY_SCHEMA_MAP[category]


def validate_document_metadata(category: str, metadata: dict[str, Any]) -> BaseDocumentMetadataSchema:
    """
    Validate metadata dict against the schema for a category.

    Args:
        category: Document category.
        metadata: Raw metadata dictionary.

    Returns:
        Validated metadata schema instance.

    Raises:
        ValueError: If category is invalid.
        pydantic.ValidationError: If metadata is invalid.

    Example:
        >>> validated = validate_document_metadata("blog", {
        ...     "title": "My Post",
        ...     "slug": "my-post",
        ...     "category": "tech",
        ... })
    """
    schema_class = get_metadata_schema(category)
    return schema_class(**metadata)


# Type alias for dynamic metadata
DocumentMetadataSchema = BaseDocumentMetadataSchema
"""Type alias for generic document metadata (use specific schemas when category is known)."""
