"""
Pydantic schemas for createOS Django model JSONFields.

DEPRECATION NOTICE:
    This module path (models/createos.py) is maintained for backward compatibility.
    PREFERRED: Import from the app-mirrored path instead:

        from lightwave.schema.pydantic.domains.platform.createos import PersonaSchema

    This path will continue to work but is considered deprecated.

These schemas validate data stored in PostgreSQL JSONB columns
for createOS models (UserStory, TestSpecification, ImplementationPlan, Debrief).

All schemas inherit from JSONFieldSchema which:
- Allows extra fields for backwards compatibility
- Uses Pydantic v2 configuration
- Supports Django model validation via clean()

Usage in Django models:
    # PREFERRED: Use app-mirrored import
    from lightwave.schema.pydantic.domains.platform.createos import PersonaSchema

    # DEPRECATED: Direct models import (still works)
    from lightwave.schema.pydantic.models.createos import PersonaSchema

    from pydantic import ValidationError as PydanticValidationError

    class UserStory(BaseModel):
        personas = models.JSONField(default=list)

        def clean(self):
            super().clean()
            try:
                # Validate each persona in the list
                for persona in self.personas:
                    PersonaSchema(**persona)
            except PydanticValidationError as e:
                raise ValidationError({"personas": e.errors()})

        @property
        def personas_typed(self) -> list[PersonaSchema]:
            return [PersonaSchema(**p) for p in self.personas]
"""

from datetime import date, datetime
from typing import Literal

from pydantic import Field

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

# =============================================================================
# USER STORY SCHEMAS
# =============================================================================


class PersonaSchema(JSONFieldSchema):
    """
    Schema for a user persona in UserStory.personas JSONField.

    Personas are discovered during user story interviews and represent
    distinct user types that interact with the feature.

    Example:
        {
            "name": "Team Admin",
            "description": "Manages team settings and billing",
            "goals": ["View invoices", "Manage subscriptions"],
            "pain_points": ["Complex billing UI", "Too many clicks"],
            "permissions": ["billing:read", "billing:write"]
        }
    """

    name: str = Field(..., description="Persona name (e.g., 'Team Admin')")
    description: str = Field("", description="Brief description of this persona")
    goals: list[str] = Field(default_factory=list, description="What they want to achieve")
    pain_points: list[str] = Field(default_factory=list, description="Current frustrations")
    permissions: list[str] = Field(
        default_factory=list,
        description="Required permissions in format 'resource:action' (e.g., 'billing:read')",
    )
    frequency: str = Field("", description="How often they use this feature")
    technical_level: Literal["low", "medium", "high", ""] = Field("", description="Technical sophistication")


class UserFlowSchema(JSONFieldSchema):
    """
    Schema for a user flow in UserStory.user_flows JSONField.

    Flows describe step-by-step user journeys through the feature.
    They map to SST user_flows.yaml format.

    Example:
        {
            "name": "View Billing Dashboard",
            "persona": "Team Admin",
            "steps": [
                {"action": "Navigate to /billing", "expected": "Dashboard loads"},
                {"action": "Click invoice row", "expected": "Invoice detail opens"}
            ],
            "preconditions": ["User is authenticated", "User has billing permission"],
            "happy_path": true
        }
    """

    class FlowStep(JSONFieldSchema):
        """Individual step in a user flow."""

        action: str = Field(..., description="User action (e.g., 'Click submit button')")
        expected: str = Field(..., description="Expected result")
        notes: str = Field("", description="Additional context")

    name: str = Field(..., description="Flow name")
    persona: str = Field("", description="Primary persona for this flow")
    steps: list[FlowStep] = Field(default_factory=list, description="Ordered steps")
    preconditions: list[str] = Field(default_factory=list, description="Required state before flow")
    postconditions: list[str] = Field(default_factory=list, description="Expected state after flow")
    happy_path: bool = Field(True, description="Is this the happy path?")


class EdgeCaseSchema(JSONFieldSchema):
    """
    Schema for an edge case in UserStory.edge_cases JSONField.

    Edge cases are discovered during interviews and represent
    non-happy-path scenarios that need handling.

    Example:
        {
            "scenario": "User without billing permission tries to access /billing",
            "expected_behavior": "Show 403 with contact admin message",
            "priority": "high",
            "test_required": true
        }
    """

    scenario: str = Field(..., description="Description of the edge case scenario")
    expected_behavior: str = Field(..., description="How the system should respond")
    priority: Literal["low", "medium", "high", "critical"] = Field(
        "medium", description="Importance of handling this case"
    )
    test_required: bool = Field(True, description="Should this be a test case?")
    notes: str = Field("", description="Additional context or considerations")


class TechnicalConstraintSchema(JSONFieldSchema):
    """
    Schema for a technical constraint in UserStory.technical_constraints JSONField.

    Constraints are non-functional requirements or limitations discovered
    during planning.

    Example:
        {
            "constraint": "Must work offline",
            "rationale": "Users may have intermittent connectivity",
            "impact": "high",
            "workaround": "Use service worker with IndexedDB cache"
        }
    """

    constraint: str = Field(..., description="The constraint")
    rationale: str = Field("", description="Why this constraint exists")
    impact: Literal["low", "medium", "high"] = Field("medium", description="Impact on implementation")
    workaround: str = Field("", description="Possible workaround or solution")
    category: str = Field("", description="Category (performance, security, compatibility, etc.)")


class RBACRequirementSchema(JSONFieldSchema):
    """
    Schema for RBAC requirement in UserStory.rbac_requirements JSONField.

    Maps to teams.Membership.role and permission checks.

    Example:
        {
            "role": "team_admin",
            "resource": "billing",
            "actions": ["read", "write"],
            "conditions": ["team_id matches user's team"]
        }
    """

    role: str = Field(..., description="Role from teams.Membership.role")
    resource: str = Field(..., description="Resource being accessed")
    actions: list[str] = Field(default_factory=list, description="Allowed actions")
    conditions: list[str] = Field(default_factory=list, description="Additional conditions")
    deny_message: str = Field("", description="Message shown when denied")


class InterviewMessageSchema(JSONFieldSchema):
    """
    Schema for a message in UserStory.interview_transcript JSONField.

    Captures the Q&A between user-story-interviewer and the user.

    Example:
        {
            "role": "assistant",
            "content": "What types of users will interact with this feature?",
            "round": "round_1",
            "timestamp": "2024-01-15T10:30:00Z"
        }
    """

    role: Literal["system", "assistant", "user"] = Field(..., description="Message sender")
    content: str = Field(..., description="Message content")
    round: str = Field("", description="Interview round (round_1, round_2, etc.)")
    timestamp: datetime | None = Field(None, description="When message was sent")
    extracted_data: dict | None = Field(None, description="Data extracted from this message")


class AcceptanceCriterionSchema(JSONFieldSchema):
    """
    Schema for acceptance criteria in Given/When/Then format.

    Used in UserStory.acceptance_criteria and TestSpecification.acceptance_criteria.

    Example:
        {
            "given": "User is a team admin",
            "when": "User navigates to /billing",
            "then": "User sees billing dashboard with invoices",
            "notes": "Dashboard should load in <2 seconds"
        }
    """

    given: str = Field(..., description="Precondition (Given)")
    when: str = Field(..., description="Action (When)")
    then: str = Field(..., description="Expected result (Then)")
    notes: str = Field("", description="Additional notes")
    priority: Literal["must", "should", "could", "wont"] = Field("must", description="MoSCoW priority")


# =============================================================================
# TEST SPECIFICATION SCHEMAS
# =============================================================================


class TestScenarioSchema(JSONFieldSchema):
    """
    Schema for a test scenario in TestSpecification.test_scenarios JSONField.

    Defines inputs, expected outputs, and test context.

    Example:
        {
            "name": "Admin views billing",
            "inputs": {"user_role": "admin", "path": "/billing"},
            "expected": {"status_code": 200, "contains": "invoices"},
            "tags": ["billing", "permissions"]
        }
    """

    name: str = Field(..., description="Scenario name")
    description: str = Field("", description="Scenario description")
    inputs: dict = Field(default_factory=dict, description="Input parameters")
    expected: dict = Field(default_factory=dict, description="Expected outputs")
    tags: list[str] = Field(default_factory=list, description="Tags for categorization")
    priority: Literal["low", "medium", "high", "critical"] = Field("medium", description="Test priority")


# =============================================================================
# IMPLEMENTATION PLAN SCHEMAS
# =============================================================================


class RoadmapMilestoneSchema(JSONFieldSchema):
    """
    Schema for roadmap milestone in ImplementationPlan.roadmap_milestones JSONField.

    Links the plan to broader roadmap context.

    Example:
        {
            "name": "Q1 Billing Overhaul",
            "target_date": "2024-03-31",
            "relevance": "This plan implements the billing dashboard feature"
        }
    """

    name: str = Field(..., description="Milestone name")
    target_date: date | None = Field(None, description="Target completion date")
    relevance: str = Field("", description="How this plan relates to the milestone")
    epic_id: str = Field("", description="Related epic short_id")


class PastAchievementSchema(JSONFieldSchema):
    """
    Schema for past achievement in ImplementationPlan.past_achievements JSONField.

    References prior work that informs this plan.

    Example:
        {
            "description": "Implemented Stripe webhook handling",
            "task_id": "e420fe89",
            "learnings": "Need to handle webhook retries"
        }
    """

    description: str = Field(..., description="What was achieved")
    task_id: str = Field("", description="Related task short_id")
    learnings: str = Field("", description="Key learnings from this work")


class CriticalFileSchema(JSONFieldSchema):
    """
    Schema for critical file in ImplementationPlan.critical_files JSONField.

    Identifies files that will be significantly modified.

    Example:
        {
            "path": "apps/billing/views.py",
            "changes": "Add billing dashboard view",
            "risk": "medium"
        }
    """

    path: str = Field(..., description="File path relative to project root")
    changes: str = Field("", description="Description of changes")
    risk: Literal["low", "medium", "high"] = Field("low", description="Risk level of changes")


class DependencySchema(JSONFieldSchema):
    """
    Schema for dependency in ImplementationPlan.dependencies JSONField.

    External dependencies required for implementation.

    Example:
        {
            "name": "stripe",
            "version": ">=5.0.0",
            "purpose": "Payment processing",
            "installed": true
        }
    """

    name: str = Field(..., description="Dependency name")
    version: str = Field("", description="Version constraint")
    purpose: str = Field("", description="Why this is needed")
    installed: bool = Field(False, description="Whether already installed")


class ImplementationPlanRiskSchema(JSONFieldSchema):
    """
    Schema for risk in ImplementationPlan.risks JSONField.

    Identified risks and mitigation strategies.

    Example:
        {
            "risk": "Stripe API rate limits",
            "likelihood": "medium",
            "impact": "high",
            "mitigation": "Implement request queuing with exponential backoff"
        }
    """

    risk: str = Field(..., description="Risk description")
    likelihood: Literal["low", "medium", "high"] = Field("medium", description="Probability")
    impact: Literal["low", "medium", "high"] = Field("medium", description="Severity")
    mitigation: str = Field("", description="Mitigation strategy")


# =============================================================================
# DEBRIEF SCHEMAS
# =============================================================================


class PatternSchema(JSONFieldSchema):
    """
    Schema for pattern in Debrief.patterns_used or patterns_discovered JSONField.

    Design patterns or approaches used/discovered during implementation.

    Example:
        {
            "name": "Repository Pattern",
            "context": "Used for data access abstraction",
            "files": ["apps/billing/repositories.py"],
            "notes": "Consider extracting to lightwave-core"
        }
    """

    name: str = Field(..., description="Pattern name")
    context: str = Field("", description="How/why it was used")
    files: list[str] = Field(default_factory=list, description="Files where pattern is used")
    notes: str = Field("", description="Additional notes")
    recommend_for_reuse: bool = Field(False, description="Should this be standardized?")


class DebriefInsightSchema(JSONFieldSchema):
    """
    Schema for insight in DebriefMessage.extracted_insights JSONField.

    Insights extracted from debrief conversation.

    Example:
        {
            "type": "lesson",
            "content": "Always validate webhook signatures",
            "category": "security",
            "actionable": true,
            "action": "Add to security checklist"
        }
    """

    type: Literal["lesson", "pattern", "issue", "improvement", "observation"] = Field(
        "observation", description="Type of insight"
    )
    content: str = Field(..., description="The insight")
    category: str = Field("", description="Category (security, performance, DX, etc.)")
    actionable: bool = Field(False, description="Can this be acted upon?")
    action: str = Field("", description="Suggested action if actionable")
