"""
SEO Campaign State Schema
Defines TypedDict state definitions for LangGraph workflows
"""

from typing import TypedDict, List, Optional, Literal, Any
from datetime import datetime
from enum import Enum


class CampaignPhase(str, Enum):
    """Campaign phase tracking"""
    RESEARCH = "research"
    CONTENT = "content"
    TECHNICAL = "technical"
    SERP_FEATURES = "serp_features"
    LINK_OPPS = "link_opps"
    HUMAN_REVIEW = "human_review"
    EXECUTION = "execution"
    REPORT = "report"
    COMPLETED = "completed"
    PAUSED = "paused"
    FAILED = "failed"


class LinkOpportunityStatus(str, Enum):
    """Link opportunity approval status"""
    PENDING = "pending"
    APPROVED = "approved"
    REJECTED = "rejected"
    EXECUTED = "executed"
    FAILED = "failed"


class OpportunityType(str, Enum):
    """Types of link building opportunities"""
    HARO = "haro"  # Help A Reporter Out / Connectively
    GUEST_POST = "guest_post"
    BROKEN_LINK = "broken_link"
    UNLINKED_MENTION = "mention"
    RESOURCE_PAGE = "resource_page"
    SKYSCRAPER = "skyscraper"


class SERPFeatureType(str, Enum):
    """Types of SERP features to target"""
    FEATURED_SNIPPET = "snippet"
    PEOPLE_ALSO_ASK = "paa"
    AI_OVERVIEW = "ai_overview"
    LOCAL_PACK = "local_pack"
    KNOWLEDGE_PANEL = "knowledge_panel"
    IMAGE_PACK = "image_pack"
    VIDEO_CAROUSEL = "video_carousel"


class LinkOpportunity(TypedDict):
    """A discovered link building opportunity requiring human approval"""
    id: str
    target_url: str
    source_domain: str
    domain_authority: int
    monthly_traffic: Optional[int]
    relevance_score: float
    opportunity_type: str  # OpportunityType value
    status: str  # LinkOpportunityStatus value

    # Pitch information
    pitch_draft: str
    pitch_approved: Optional[str]

    # Contact information
    contact_email: Optional[str]
    contact_name: Optional[str]

    # Approval tracking
    approved_by: Optional[str]
    approved_at: Optional[str]  # ISO timestamp
    rejection_reason: Optional[str]

    # Execution tracking
    executed_at: Optional[str]  # ISO timestamp
    link_acquired: bool
    acquired_url: Optional[str]

    # Metadata
    discovered_at: str  # ISO timestamp
    notes: Optional[str]


class SERPFeatureData(TypedDict):
    """Data about SERP feature opportunities and captures"""
    keyword: str
    feature_type: str  # SERPFeatureType value
    current_position: Optional[int]
    captured: bool
    captured_at: Optional[str]  # ISO timestamp
    content_hash: Optional[str]

    # AI Overview specific
    ai_overview_mention: bool
    citation_context: Optional[str]

    # Optimization status
    optimized: bool
    optimization_applied: Optional[str]


class ContentQueueItem(TypedDict):
    """Item in the content generation queue"""
    id: str
    keyword: str
    content_type: str  # article, faq, guide, etc.
    target_serp_features: List[str]
    priority: int  # 1-10
    status: str  # pending, in_progress, completed, failed
    page_id: Optional[str]  # Reference to generated SEOPage
    created_at: str


class OptimizationQueueItem(TypedDict):
    """Item in the optimization queue"""
    id: str
    page_id: str
    optimization_type: str  # snippet, paa, ai_overview, schema
    target_keyword: str
    priority: int
    status: str
    completed_at: Optional[str]


class GSCData(TypedDict):
    """Google Search Console data snapshot"""
    property_url: str
    date_range: dict  # start, end
    total_impressions: int
    total_clicks: int
    average_ctr: float
    average_position: float
    top_queries: List[dict]
    top_pages: List[dict]
    fetched_at: str


class CompetitorData(TypedDict):
    """Competitor analysis data"""
    domain: str
    domain_authority: int
    estimated_traffic: int
    top_keywords: List[dict]
    content_gaps: List[dict]
    backlink_sources: List[dict]
    analyzed_at: str


class SEOCampaignState(TypedDict):
    """
    Main campaign state for LangGraph SEO workflows

    This state is persisted across workflow executions using Redis checkpointing,
    enabling human-in-the-loop approvals and long-running campaigns.
    """
    # Campaign identity
    site_id: str
    campaign_id: str
    campaign_type: str  # zero_click, link_building, content_matrix, full_campaign

    # Phase tracking
    current_phase: str  # CampaignPhase value
    phase_started_at: Optional[str]
    phases_completed: List[str]

    # Human interrupt checkpoint
    pending_approvals: List[LinkOpportunity]
    requires_human_review: bool
    paused_at: Optional[str]
    pause_reason: Optional[str]

    # Data collected during research phase
    gsc_data: Optional[GSCData]
    competitor_data: List[CompetitorData]
    serp_features_data: List[SERPFeatureData]

    # Work queues
    content_queue: List[ContentQueueItem]
    optimization_queue: List[OptimizationQueueItem]
    link_opportunities: List[LinkOpportunity]

    # SERP features targeted
    serp_features_targeted: List[str]  # SERPFeatureType values

    # Execution tracking
    pages_generated: int
    pages_optimized: int
    snippets_captured: int
    paa_captured: int
    ai_overview_mentions: int
    links_approved: int
    links_acquired: int

    # Error tracking
    errors: List[dict]  # {phase, message, timestamp}
    warnings: List[dict]

    # Timestamps
    started_at: str
    updated_at: str
    completed_at: Optional[str]

    # Configuration
    config: dict  # Campaign-specific configuration


def create_initial_state(
    site_id: str,
    campaign_id: str,
    campaign_type: str = "zero_click",
    config: Optional[dict] = None
) -> SEOCampaignState:
    """Create a new campaign state with defaults"""
    now = datetime.utcnow().isoformat()

    return SEOCampaignState(
        site_id=site_id,
        campaign_id=campaign_id,
        campaign_type=campaign_type,
        current_phase=CampaignPhase.RESEARCH.value,
        phase_started_at=now,
        phases_completed=[],
        pending_approvals=[],
        requires_human_review=False,
        paused_at=None,
        pause_reason=None,
        gsc_data=None,
        competitor_data=[],
        serp_features_data=[],
        content_queue=[],
        optimization_queue=[],
        link_opportunities=[],
        serp_features_targeted=[
            SERPFeatureType.FEATURED_SNIPPET.value,
            SERPFeatureType.PEOPLE_ALSO_ASK.value,
            SERPFeatureType.AI_OVERVIEW.value,
        ],
        pages_generated=0,
        pages_optimized=0,
        snippets_captured=0,
        paa_captured=0,
        ai_overview_mentions=0,
        links_approved=0,
        links_acquired=0,
        errors=[],
        warnings=[],
        started_at=now,
        updated_at=now,
        completed_at=None,
        config=config or {},
    )


def transition_phase(
    state: SEOCampaignState,
    new_phase: CampaignPhase
) -> SEOCampaignState:
    """Transition campaign to a new phase"""
    now = datetime.utcnow().isoformat()

    # Add current phase to completed list
    completed = state.get("phases_completed", []).copy()
    current = state.get("current_phase")
    if current and current not in completed:
        completed.append(current)

    state["phases_completed"] = completed
    state["current_phase"] = new_phase.value
    state["phase_started_at"] = now
    state["updated_at"] = now

    return state


def add_error(
    state: SEOCampaignState,
    phase: str,
    message: str
) -> SEOCampaignState:
    """Add an error to the state"""
    errors = state.get("errors", []).copy()
    errors.append({
        "phase": phase,
        "message": message,
        "timestamp": datetime.utcnow().isoformat()
    })
    state["errors"] = errors
    state["updated_at"] = datetime.utcnow().isoformat()
    return state


def add_warning(
    state: SEOCampaignState,
    phase: str,
    message: str
) -> SEOCampaignState:
    """Add a warning to the state"""
    warnings = state.get("warnings", []).copy()
    warnings.append({
        "phase": phase,
        "message": message,
        "timestamp": datetime.utcnow().isoformat()
    })
    state["warnings"] = warnings
    state["updated_at"] = datetime.utcnow().isoformat()
    return state
