"""
Content automation schemas from content-automation.yaml.

Defines the structure for weekly content pipelines:
- Website copy audits
- Blog interview rounds
- Newsletter compilation
- Performance metrics

SST File: lightwave/schema/definitions/content-automation.yaml
"""

from datetime import datetime
from pathlib import Path
from typing import Any, ClassVar, Literal

import yaml
from pydantic import Field

from lightwave.schema.pydantic.core.base import LightwaveBaseSchema, SSTSchema

# =============================================================================
# SCHEDULE SCHEMAS
# =============================================================================


class ScheduledTaskSchema(LightwaveBaseSchema):
    """Scheduled content automation task."""

    name: str = Field(..., description="Task identifier")
    cron: str = Field(..., description="Cron expression")
    description: str = Field(..., description="Task description")
    agent: str = Field(..., description="Agent that runs this task")
    timeout_minutes: int = Field(30, description="Task timeout")
    requires_input: bool = Field(False, description="Whether human input is required")


# =============================================================================
# AUDIT SCHEMAS
# =============================================================================


class AuditTargetFileSchema(LightwaveBaseSchema):
    """File to be audited."""

    path: str = Field(..., description="File path relative to project root")
    priority: Literal["critical", "high", "medium", "low"] = Field("medium", description="Audit priority")


class AuditRuleSchema(LightwaveBaseSchema):
    """Audit rule definition."""

    name: str = Field(..., description="Rule name")
    description: str = Field(..., description="Rule description")
    severity: Literal["error", "warning", "info"] = Field(..., description="Rule severity")
    auto_fix: bool = Field(False, description="Whether rule can be auto-fixed")


class AuditScoringWeightsSchema(LightwaveBaseSchema):
    """Weights for audit scoring."""

    banned_words: int = Field(30, ge=0, le=100)
    voice_alignment: int = Field(25, ge=0, le=100)
    competitor_patterns: int = Field(20, ge=0, le=100)
    paragraph_length: int = Field(10, ge=0, le=100)
    passive_voice: int = Field(5, ge=0, le=100)
    transformation_promise: int = Field(10, ge=0, le=100)


class AuditGradeSchema(LightwaveBaseSchema):
    """Audit grade threshold."""

    min_score: int = Field(..., ge=0, le=100, alias="min")
    grade: Literal["A", "B", "C", "F"] = Field(..., description="Letter grade")
    action: str = Field(..., description="Recommended action")


class ContentAuditConfig(LightwaveBaseSchema):
    """Configuration for website copy audits."""

    target_files: dict[str, list[AuditTargetFileSchema]] = Field(
        default_factory=dict, description="Files to audit by category"
    )
    rules: list[AuditRuleSchema] = Field(default_factory=list, description="Audit rules")
    scoring_weights: AuditScoringWeightsSchema = Field(
        default_factory=AuditScoringWeightsSchema, description="Scoring weights"
    )
    grades: list[AuditGradeSchema] = Field(default_factory=list, description="Grade thresholds")

    def get_grade(self, score: int) -> AuditGradeSchema | None:
        """Get grade for a given score."""
        for grade in sorted(self.grades, key=lambda g: g.min_score, reverse=True):
            if score >= grade.min_score:
                return grade
        return None


# =============================================================================
# BLOG INTERVIEW SCHEMAS
# =============================================================================


class InterviewInputSourceSchema(LightwaveBaseSchema):
    """Input source for interview round."""

    type: Literal["founder_input", "rss_feeds", "support_tickets"] = Field(..., description="Source type")
    required: bool = Field(False, description="Whether source is required")
    prompt: str | None = Field(None, description="Prompt for founder input")
    feeds: list[str] | None = Field(None, description="RSS feed URLs")
    filter: str | None = Field(None, description="Filter query")


class InterviewRoundSchema(LightwaveBaseSchema):
    """Interview round definition."""

    id: str = Field(..., description="Round identifier")
    order: int = Field(..., ge=1, le=10, description="Round order")
    name: str = Field(..., description="Round name")
    agent: str = Field(..., description="Agent conducting this round")
    voice_model: str = Field(..., description="Voice model to use")
    questions: list[str] = Field(default_factory=list, description="Interview questions")
    guidelines: list[str] = Field(default_factory=list, description="Round guidelines")
    input_sources: list[InterviewInputSourceSchema] = Field(default_factory=list, description="Input sources")
    task: str | None = Field(None, description="Task description for synthesis round")


class BlogOutputSchema(LightwaveBaseSchema):
    """Blog post output schema."""

    title: str = Field(..., max_length=60, description="Blog title")
    subtitle: str = Field(..., max_length=120, description="Blog subtitle")
    body: str = Field(..., min_length=800, max_length=1500, description="Blog body (markdown)")
    cta: str | None = Field(None, max_length=100, description="Call to action")
    meta_description: str = Field(..., max_length=160, description="SEO meta description")
    tags: list[str] = Field(default_factory=list, max_length=5, description="Blog tags")


class BlogInterviewConfig(LightwaveBaseSchema):
    """Configuration for blog interview process."""

    rounds: list[InterviewRoundSchema] = Field(default_factory=list, description="Interview rounds")

    def get_round(self, round_id: str) -> InterviewRoundSchema | None:
        """Get a round by ID."""
        for r in self.rounds:
            if r.id == round_id:
                return r
        return None

    def get_rounds_in_order(self) -> list[InterviewRoundSchema]:
        """Get rounds sorted by order."""
        return sorted(self.rounds, key=lambda r: r.order)


# =============================================================================
# NEWSLETTER SCHEMAS
# =============================================================================


class NewsletterItemTemplate(LightwaveBaseSchema):
    """Template for newsletter list items."""

    title: str = Field(..., description="Item title format")
    url: str = Field(..., description="Item URL format")
    why: str | None = Field(None, description="Reason/description format")


class NewsletterSectionSchema(LightwaveBaseSchema):
    """Newsletter section definition."""

    id: str = Field(..., description="Section identifier")
    name: str = Field(..., description="Section name")
    voice_model: str | None = Field(None, description="Voice model for this section")
    source: str | None = Field(None, description="Data source")
    max_length: int | None = Field(None, description="Max character length")
    max_items: int | None = Field(None, description="Max items for list sections")
    optional: bool = Field(False, description="Whether section is optional")
    template: str | None = Field(None, description="Section template/guidance")
    item_template: NewsletterItemTemplate | None = Field(None, description="Template for list items")


class NewsletterConfig(LightwaveBaseSchema):
    """Configuration for newsletter compilation."""

    sections: list[NewsletterSectionSchema] = Field(default_factory=list, description="Newsletter sections")

    def get_section(self, section_id: str) -> NewsletterSectionSchema | None:
        """Get a section by ID."""
        for s in self.sections:
            if s.id == section_id:
                return s
        return None


# =============================================================================
# METRICS SCHEMAS
# =============================================================================


class MetricDefinitionSchema(LightwaveBaseSchema):
    """Metric definition."""

    name: str = Field(..., description="Metric name")
    type: Literal["integer", "float", "string"] = Field(..., description="Metric data type")
    description: str = Field(..., description="Metric description")
    period: str | None = Field(None, description="Measurement period")
    range: tuple[int, int] | list[int] | None = Field(None, description="Valid range for numeric metrics")
    unit: str | None = Field(None, description="Unit of measurement")
    target: int | float | None = Field(None, description="Target value")
    enum: list[str] | None = Field(None, description="Valid values for string metrics")


class ContentMetricsConfig(LightwaveBaseSchema):
    """Configuration for content metrics."""

    audit: list[MetricDefinitionSchema] = Field(default_factory=list, description="Audit metrics")
    content: list[MetricDefinitionSchema] = Field(default_factory=list, description="Content metrics")
    quality: list[MetricDefinitionSchema] = Field(default_factory=list, description="Quality metrics")
    cache_path: str = Field(".claude/cache/content_metrics.json", description="Metrics cache file path")
    retention_weeks: int = Field(12, description="Weeks of history to retain")


class ContentMetricsSnapshot(LightwaveBaseSchema):
    """Snapshot of content metrics for a given week."""

    generated_at: datetime = Field(..., description="When snapshot was generated")
    week_of: str = Field(..., description="Week start date (ISO format)")
    audit: dict[str, Any] = Field(default_factory=dict, description="Audit metrics")
    content: dict[str, Any] = Field(default_factory=dict, description="Content metrics")
    quality: dict[str, Any] = Field(default_factory=dict, description="Quality metrics")


# =============================================================================
# APPROVAL WORKFLOW SCHEMAS
# =============================================================================


class ContentApproverSchema(LightwaveBaseSchema):
    """Content approver definition."""

    content_type: str = Field(..., description="Content type (website_copy, blog_post, newsletter)")
    name: str = Field(..., description="Content type display name")
    approvers: list[str] = Field(default_factory=list, description="Allowed approvers")
    auto_approve_conditions: list[str] | None = Field(None, description="Conditions for auto-approval")


class ContentOutboxItem(LightwaveBaseSchema):
    """Content item in approval queue."""

    content_type: Literal["website_copy", "blog_post", "newsletter"] = Field(..., description="Content type")
    title: str = Field(..., description="Content title")
    body: str = Field(..., description="Content body")
    diff: str | None = Field(None, description="Diff for website_copy changes")
    source_agent: str = Field(..., description="Agent that created this")
    interview_transcript: str | None = Field(None, description="Interview transcript for blogs")
    metrics: dict[str, Any] = Field(default_factory=dict, description="Relevant metrics")
    status: Literal["pending", "approved", "rejected", "published"] = Field("pending", description="Approval status")
    created_at: datetime = Field(default_factory=datetime.utcnow, description="Creation timestamp")


# =============================================================================
# MAIN CONFIG SCHEMA
# =============================================================================


class ContentAutomationConfig(SSTSchema):
    """
    Content automation configuration from content-automation.yaml.

    Provides typed access to the entire content automation pipeline:
    - Scheduled tasks
    - Audit configuration
    - Blog interview process
    - Newsletter compilation
    - Metrics definitions
    - Approval workflow

    Example:
        config = ContentAutomationConfig.load()
        rounds = config.blog_interview.get_rounds_in_order()
        for round in rounds:
            print(f"Round {round.order}: {round.name}")

    SST Validation:
        config = ContentAutomationConfig.load()
        assert len(config.blog_interview.rounds) == 5
        assert config.audit.get_grade(85).grade == "B"
    """

    SST_KEY: ClassVar[str] = "content_automation"  # Registry key in __index.yaml

    version: str = Field(..., description="Schema version")
    schedule: list[ScheduledTaskSchema] = Field(default_factory=list, description="Scheduled tasks")
    audit: ContentAuditConfig = Field(default_factory=ContentAuditConfig, description="Audit configuration")
    blog_interview: BlogInterviewConfig = Field(
        default_factory=BlogInterviewConfig, description="Blog interview configuration"
    )
    newsletter: NewsletterConfig = Field(default_factory=NewsletterConfig, description="Newsletter configuration")
    metrics: ContentMetricsConfig = Field(default_factory=ContentMetricsConfig, description="Metrics configuration")
    approval: list[ContentApproverSchema] = Field(default_factory=list, description="Approval workflow")

    @classmethod
    def get_sst_path(cls) -> Path:
        """Get path to SST YAML file (from __index.yaml registry)."""
        from lightwave.schema.core.paths import get_sst_path

        return get_sst_path(cls.SST_KEY)

    @classmethod
    def load_sst_data(cls) -> dict[str, Any]:
        """Load SST YAML file."""
        sst_path = cls.get_sst_path()
        if not sst_path.exists():
            raise FileNotFoundError(f"SST file not found: {sst_path}")
        with open(sst_path) as f:
            return yaml.safe_load(f)

    @classmethod
    def load(cls) -> "ContentAutomationConfig":
        """
        Load content automation configuration from SST YAML.

        Returns:
            ContentAutomationConfig instance
        """
        data = cls.load_sst_data()
        meta = data.get("_meta", {})

        # Parse schedule
        schedule = []
        schedule_raw = data.get("schedule", {})
        for task_name, task_data in schedule_raw.items():
            schedule.append(
                ScheduledTaskSchema(
                    name=task_name,
                    cron=task_data.get("cron", ""),
                    description=task_data.get("description", ""),
                    agent=task_data.get("agent", ""),
                    timeout_minutes=task_data.get("timeout_minutes", 30),
                    requires_input=task_data.get("requires_input", False),
                )
            )

        # Parse audit config
        audit_raw = data.get("audit", {})
        target_files = {}
        for category, files in audit_raw.get("target_files", {}).items():
            target_files[category] = [AuditTargetFileSchema(**f) for f in files]

        audit_rules = []
        for rule_name, rule_data in audit_raw.get("rules", {}).items():
            audit_rules.append(
                AuditRuleSchema(
                    name=rule_name,
                    description=rule_data.get("description", ""),
                    severity=rule_data.get("severity", "warning"),
                    auto_fix=rule_data.get("auto_fix", False),
                )
            )

        scoring_raw = audit_raw.get("scoring", {}).get("weights", {})
        scoring_weights = AuditScoringWeightsSchema(**scoring_raw) if scoring_raw else AuditScoringWeightsSchema()

        grades = []
        for grade_data in audit_raw.get("scoring", {}).get("grades", []):
            grades.append(AuditGradeSchema(**grade_data))

        audit = ContentAuditConfig(
            target_files=target_files,
            rules=audit_rules,
            scoring_weights=scoring_weights,
            grades=grades,
        )

        # Parse blog interview config
        blog_raw = data.get("blog_interview", {})
        rounds = []
        for round_data in blog_raw.get("rounds", []):
            input_sources = []
            for src in round_data.get("input_sources", []):
                input_sources.append(InterviewInputSourceSchema(**src))
            rounds.append(
                InterviewRoundSchema(
                    id=round_data.get("id", ""),
                    order=round_data.get("order", 1),
                    name=round_data.get("name", ""),
                    agent=round_data.get("agent", ""),
                    voice_model=round_data.get("voice_model", ""),
                    questions=round_data.get("questions", []),
                    guidelines=round_data.get("guidelines", []),
                    input_sources=input_sources,
                    task=round_data.get("task"),
                )
            )
        blog_interview = BlogInterviewConfig(rounds=rounds)

        # Parse newsletter config
        newsletter_raw = data.get("newsletter", {})
        sections = []
        for section_data in newsletter_raw.get("sections", []):
            sections.append(NewsletterSectionSchema(**section_data))
        newsletter = NewsletterConfig(sections=sections)

        # Parse metrics config
        metrics_raw = data.get("metrics", {})
        audit_metrics = [MetricDefinitionSchema(**m) for m in metrics_raw.get("audit", [])]
        content_metrics = [MetricDefinitionSchema(**m) for m in metrics_raw.get("content", [])]
        quality_metrics = [MetricDefinitionSchema(**m) for m in metrics_raw.get("quality", [])]
        cache_config = metrics_raw.get("cache", {})
        metrics = ContentMetricsConfig(
            audit=audit_metrics,
            content=content_metrics,
            quality=quality_metrics,
            cache_path=cache_config.get("path", ".claude/cache/content_metrics.json"),
            retention_weeks=cache_config.get("retention_weeks", 12),
        )

        # Parse approval workflow
        approval = []
        approval_raw = data.get("approval", {}).get("content_types", [])
        for approver_data in approval_raw:
            approval.append(
                ContentApproverSchema(
                    content_type=approver_data.get("id", ""),
                    name=approver_data.get("name", ""),
                    approvers=approver_data.get("approvers", []),
                    auto_approve_conditions=approver_data.get("auto_approve_if"),
                )
            )

        return cls(
            version=meta.get("version", "1.0.0"),
            schedule=schedule,
            audit=audit,
            blog_interview=blog_interview,
            newsletter=newsletter,
            metrics=metrics,
            approval=approval,
        )


# Convenience function for quick access
def get_content_automation_config() -> ContentAutomationConfig:
    """
    Load and return content automation configuration.

    Example:
        from lightwave.schema.pydantic.models.content_automation import get_content_automation_config

        config = get_content_automation_config()
        for round in config.blog_interview.get_rounds_in_order():
            print(f"{round.order}. {round.name}")
    """
    return ContentAutomationConfig.load()
