"""
Link Approval Subgraph
Dedicated workflow for link opportunity discovery and human approval
"""

from typing import Literal
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.base import BaseCheckpointSaver

from state.campaign_state import (
    SEOCampaignState,
    CampaignPhase,
    LinkOpportunity,
    LinkOpportunityStatus,
    transition_phase,
)
from nodes.link_discovery_node import (
    link_discovery_phase,
    is_quality_opportunity,
    generate_pitch,
    LINK_QUALITY_THRESHOLDS,
)


async def score_opportunities(state: SEOCampaignState) -> SEOCampaignState:
    """
    Score and filter link opportunities

    Applies strict quality filters:
    - Domain Authority >= 40
    - Monthly Traffic >= 5,000
    - Relevance Score >= 0.8
    - No blacklisted patterns
    """
    print(f"[ScoreOpportunities] Scoring {len(state.get('link_opportunities', []))} opportunities")

    opportunities = state.get("link_opportunities", [])
    scored = []
    rejected = []

    for opp in opportunities:
        # Calculate composite score
        da_score = min(opp.get("domain_authority", 0) / 100, 1.0)
        traffic_score = min(opp.get("monthly_traffic", 0) / 50000, 1.0)
        relevance = opp.get("relevance_score", 0)

        composite_score = (da_score * 0.3) + (traffic_score * 0.3) + (relevance * 0.4)

        # Check quality thresholds
        if is_quality_opportunity(opp):
            opp["composite_score"] = round(composite_score, 3)
            scored.append(opp)
        else:
            opp["status"] = LinkOpportunityStatus.REJECTED.value
            opp["rejection_reason"] = "Did not meet quality thresholds"
            rejected.append(opp)

    # Sort by composite score
    scored.sort(key=lambda x: x.get("composite_score", 0), reverse=True)

    print(f"[ScoreOpportunities] Qualified: {len(scored)}, Rejected: {len(rejected)}")

    state["link_opportunities"] = scored + rejected
    state["pending_approvals"] = scored  # Only qualified ones need approval

    return state


async def generate_pitches(state: SEOCampaignState) -> SEOCampaignState:
    """
    Generate personalized pitches for qualified opportunities
    """
    print(f"[GeneratePitches] Generating pitches for {len(state.get('pending_approvals', []))} opportunities")

    site_info = {
        "domain": "eventheodds.ai",
        "topic": "sports betting analytics",
        "value_prop": "Free sports analytics tools with data from 50,000+ games analyzed",
    }

    for opp in state.get("pending_approvals", []):
        if not opp.get("pitch_draft"):
            pitch = await generate_pitch(opp, site_info)
            opp["pitch_draft"] = pitch

    print(f"[GeneratePitches] Pitches generated")

    return state


async def await_approval(state: SEOCampaignState) -> SEOCampaignState:
    """
    Human approval interrupt point

    Waits for human to:
    - Approve opportunities (optionally edit pitch)
    - Reject opportunities (provide reason)
    """
    print(f"[AwaitApproval] Waiting for approval of {len(state.get('pending_approvals', []))} opportunities")

    # Process any approvals that came through
    pending = state.get("pending_approvals", [])
    approved = [o for o in pending if o.get("status") == LinkOpportunityStatus.APPROVED.value]
    rejected = [o for o in pending if o.get("status") == LinkOpportunityStatus.REJECTED.value]
    still_pending = [o for o in pending if o.get("status") == LinkOpportunityStatus.PENDING.value]

    state["links_approved"] = len(approved)
    state["pending_approvals"] = still_pending

    if not still_pending:
        state["requires_human_review"] = False

    return state


def check_approval_status(state: SEOCampaignState) -> Literal["execute", "pending", "done"]:
    """Check if we should execute, wait, or finish"""
    pending = state.get("pending_approvals", [])
    approved = [o for o in state.get("link_opportunities", [])
                if o.get("status") == LinkOpportunityStatus.APPROVED.value]

    if pending:
        return "pending"
    elif approved:
        return "execute"
    else:
        return "done"


async def execute_approved(state: SEOCampaignState) -> SEOCampaignState:
    """
    Execute outreach for approved opportunities

    In a full implementation, this would:
    - Send emails via the email service
    - Track delivery status
    - Log to compliance system
    """
    print(f"[ExecuteApproved] Executing approved outreach")

    from datetime import datetime
    now = datetime.utcnow().isoformat()

    for opp in state.get("link_opportunities", []):
        if opp.get("status") == LinkOpportunityStatus.APPROVED.value:
            # Mark as executed
            opp["status"] = LinkOpportunityStatus.EXECUTED.value
            opp["executed_at"] = now

            # TODO: Actual email sending via EmailService
            # await send_outreach_email(opp)

    return state


def create_link_approval_graph(checkpointer: BaseCheckpointSaver | None = None):
    """
    Create the link approval subgraph

    Flow:
    1. Discover - Find link opportunities
    2. Score - Apply quality filters
    3. Pitch - Generate personalized pitches
    4. Approval (INTERRUPT) - Wait for human approval
    5. Execute - Send approved outreach

    This graph can be used standalone or as a subgraph within the main campaign.
    """
    graph = StateGraph(SEOCampaignState)

    # Add nodes
    graph.add_node("discover", link_discovery_phase)
    graph.add_node("score", score_opportunities)
    graph.add_node("generate_pitches", generate_pitches)
    graph.add_node("await_approval", await_approval)
    graph.add_node("execute", execute_approved)

    # Linear flow to approval
    graph.add_edge(START, "discover")
    graph.add_edge("discover", "score")
    graph.add_edge("score", "generate_pitches")
    graph.add_edge("generate_pitches", "await_approval")

    # Conditional after approval
    graph.add_conditional_edges(
        "await_approval",
        check_approval_status,
        {
            "execute": "execute",
            "pending": END,  # Pause for more approvals
            "done": END,
        }
    )

    graph.add_edge("execute", END)

    # Compile with interrupt before approval
    compiled = graph.compile(
        checkpointer=checkpointer,
        interrupt_before=["await_approval"],
    )

    return compiled
