from __future__ import annotations

from fastapi import APIRouter, Request, Query
from fastapi.responses import HTMLResponse
from typing import Any
import json
from urllib.parse import urlparse
from html import escape as _esc
from ..app import templates
from ..services.tasks import get_session, new_sid
from ..services.telemetry import log_commander_create_deck


def _merge_hx_trigger(response: Any, payload: dict[str, Any]) -> None:
    if not payload or response is None:
        return
    try:
        existing = response.headers.get("HX-Trigger") if hasattr(response, "headers") else None
    except Exception:
        existing = None
    try:
        if existing:
            try:
                data = json.loads(existing)
            except Exception:
                data = {}
            if isinstance(data, dict):
                data.update(payload)
                response.headers["HX-Trigger"] = json.dumps(data)
                return
        response.headers["HX-Trigger"] = json.dumps(payload)
    except Exception:
        try:
            response.headers["HX-Trigger"] = json.dumps(payload)
        except Exception:
            pass


def _step5_summary_placeholder_html(token: int, *, message: str | None = None) -> str:
    text = message or "Deck summary will appear after the build completes."
    return (
        f'<div id="deck-summary" data-summary '
        f'hx-get="/build/step5/summary?token={token}" '
        'hx-trigger="step5:refresh from:body" hx-swap="outerHTML">'
        f'<div class="muted" style="margin-top:1rem;">{_esc(text)}</div>'
        '</div>'
    )


def _current_builder_summary(sess: dict) -> Any | None:
    try:
        ctx = sess.get("build_ctx") or {}
        builder = ctx.get("builder") if isinstance(ctx, dict) else None
        if builder is None:
            return None
        summary_fn = getattr(builder, "build_deck_summary", None)
        if callable(summary_fn):
            summary_data = summary_fn()
            # Also save to session for consistency
            if summary_data:
                sess["summary"] = summary_data
            return summary_data
    except Exception:
        return None
    return None


router = APIRouter(prefix="/build")


@router.get("/", response_class=HTMLResponse)
async def build_index(request: Request) -> HTMLResponse:
    sid = request.cookies.get("sid") or new_sid()
    sess = get_session(sid)
    # Seed commander from query string when arriving from commander browser
    q_commander = None
    try:
        q_commander = request.query_params.get("commander")
        if q_commander:
            # Persist a human-friendly commander name into session for the wizard
            sess["commander"] = str(q_commander)
            # Set flag to indicate this is a quick-build scenario
            sess["quick_build"] = True
    except Exception:
        pass
    return_url = None
    try:
        raw_return = request.query_params.get("return")
        if raw_return:
            parsed = urlparse(raw_return)
            if not parsed.scheme and not parsed.netloc and parsed.path:
                safe_path = parsed.path if parsed.path.startswith("/") else f"/{parsed.path}"
                safe_return = safe_path
                if parsed.query:
                    safe_return += f"?{parsed.query}"
                if parsed.fragment:
                    safe_return += f"#{parsed.fragment}"
                return_url = safe_return
    except Exception:
        return_url = None
    if q_commander:
        try:
            log_commander_create_deck(
                request,
                commander=str(q_commander),
                return_url=return_url,
            )
        except Exception:
            pass
    # Determine last step (fallback heuristics if not set)
    last_step = sess.get("last_step")
    if not last_step:
        if sess.get("build_ctx"):
            last_step = 5
        elif sess.get("ideals"):
            last_step = 4
        elif sess.get("bracket"):
            last_step = 3
        elif sess.get("commander"):
            last_step = 2
        else:
            last_step = 1
    # Only pass commander to template if coming from commander browser (?commander= query param)
    # This prevents stale commander from being pre-filled on subsequent builds
    # The query param only exists on initial navigation from commander browser
    should_auto_fill = q_commander is not None
    
    resp = templates.TemplateResponse(
        request,
        "build/index.html",
        {
            "sid": sid,
            "commander": sess.get("commander") if should_auto_fill else None,
            "tags": sess.get("tags", []),
            "name": sess.get("custom_export_base"),
            "last_step": last_step,
            "return_url": return_url,
        },
    )
    resp.set_cookie("sid", sid, httponly=True, samesite="lax")
    return resp


# Support /build without trailing slash
@router.get("", response_class=HTMLResponse)
async def build_index_alias(request: Request) -> HTMLResponse:
    return await build_index(request)


@router.get("/batch-progress")
def batch_build_progress(request: Request, batch_id: str = Query(...)):
    """Poll endpoint for Batch Build progress. Returns either progress indicator or redirect to comparison."""
    import logging
    logger = logging.getLogger(__name__)
    
    sid = request.cookies.get("sid") or new_sid()
    sess = get_session(sid)
    
    from ..services.build_cache import BuildCache
    
    batch_status = BuildCache.get_batch_status(sess, batch_id)
    logger.info(f"[Batch Progress Poll] batch_id={batch_id}, status={batch_status}")
    
    if not batch_status:
        return HTMLResponse('<div class="error">Batch not found. Please refresh.</div>')
    
    if batch_status["status"] == "completed":
        # All builds complete - redirect to comparison page
        response = HTMLResponse(f'<script>window.location.href = "/compare/{batch_id}";</script>')
        response.set_cookie("sid", sid, httponly=True, samesite="lax")
        return response
    
    # Get config to determine color count for time estimate
    config = BuildCache.get_batch_config(sess, batch_id)
    commander_name = config.get("commander", "") if config else ""
    
    # Estimate time based on color count (from testing data)
    time_estimate = "1-3 minutes"
    if commander_name and config:
        # Try to get commander's color identity
        try:
            from ..services import orchestrator as orch
            cmd_data = orch.load_commander(commander_name)
            if cmd_data and "colorIdentity" in cmd_data:
                color_count = len(cmd_data.get("colorIdentity", []))
                if color_count <= 2:
                    time_estimate = "1-3 minutes"
                elif color_count == 3:
                    time_estimate = "2-4 minutes"
                else:  # 4-5 colors
                    time_estimate = "3-5 minutes"
        except Exception:
            pass  # Default to 1-3 if we can't determine
    
    # Build still running - return progress content partial only
    ctx = {
        "request": request,
        "batch_id": batch_id,
        "build_count": batch_status["count"],
        "completed": batch_status["completed"],
        "progress_pct": batch_status["progress_pct"],
        "status": f"Building deck {batch_status['completed'] + 1} of {batch_status['count']}..." if batch_status['completed'] < batch_status['count'] else "Finalizing...",
        "has_errors": batch_status["has_errors"],
        "error_count": batch_status["error_count"],
        "time_estimate": time_estimate
    }
    response = templates.TemplateResponse("build/_batch_progress_content.html", ctx)
    response.set_cookie("sid", sid, httponly=True, samesite="lax")
    return response


# ==============================================================================
# Phase 5 Routes Moved to Focused Modules (Roadmap 9 M1)
# ==============================================================================
# Permalinks and Lock Management → build_permalinks.py:
#   - POST /build/lock - Card lock toggle
#   - GET /build/permalink - State serialization
#   - GET /build/from - State restoration
#
# Alternatives → build_alternatives.py:
#   - GET /build/alternatives - Role-based card suggestions
#
# Compliance and Replacement → build_compliance.py:
#   - POST /build/replace - Inline card replacement
#   - POST /build/replace/undo - Undo replacement
#   - GET /build/compare - Batch comparison stub
#   - GET /build/compliance - Compliance panel
#   - POST /build/enforce/apply - Apply enforcement
#   - GET /build/enforcement - Full-page enforcement
# ==============================================================================
