"""
UI Page Routes for CodeContext server.

HTML page routes that render Jinja2 templates.
"""

import json
import time
from pathlib import Path

from fastapi import APIRouter, Request, Query
from fastapi.responses import HTMLResponse

from ..services.store_manager import get_store, list_projects, ALL_PROJECTS
from ..utils.formatting import format_memories_datetime
from ..memory_consolidator import find_clusters, tier_clusters
from ..services.summary_generator import SummaryManager, calculate_total_tokens
from ..cli_utils import PROJECTS_DIR


router = APIRouter()


def get_templates(request: Request):
    """Get templates from app state."""
    return request.app.state.templates


def get_embedder(request: Request):
    """Get embedder from app state."""
    return request.app.state.embedder


def get_device(request: Request):
    """Get device from app state."""
    return request.app.state.device


def get_config(request: Request):
    """Get server config from app state."""
    return request.app.state.server_config


def get_base_path(request: Request):
    """Get base path from app state."""
    return request.app.state.base_path


def get_default_config(request: Request):
    """Get default config from app state."""
    return request.app.state.default_config


@router.get("/", response_class=HTMLResponse)
async def dashboard(request: Request, project: str = Query(default="")):
    """Main dashboard - list memories for a project."""
    templates = get_templates(request)
    embedder = get_embedder(request)
    device = get_device(request)
    server_config = get_config(request)

    projects = list_projects()

    # Default to ALL_PROJECTS if not specified
    if not project:
        project = ALL_PROJECTS

    memories = []
    info = {"device": device, "embedding_dim": 384, "memory_count": 0, "pending_conflicts": 0}
    total_count = 0

    if project == ALL_PROJECTS:
        # Aggregate memories from all projects
        all_memories = []
        total_memory_count = 0
        total_pending_conflicts = 0
        total_token_count = 0

        for p in projects:
            store = get_store(p)
            p_memories = store.list_all(limit=30, offset=0)
            for m in p_memories:
                m["project"] = p
            all_memories.extend(p_memories)
            total_memory_count += store.count()
            total_pending_conflicts += store.count_pending_conflicts()
            all_proj_memories = store.list_all(limit=10000)
            total_token_count += calculate_total_tokens(all_proj_memories)

        all_memories.sort(key=lambda x: x.get("created_at", ""), reverse=True)
        memories = all_memories[:20]
        memories = format_memories_datetime(memories)

        info = {
            "device": device,
            "embedding_dim": embedder.get_sentence_embedding_dimension() if embedder else 384,
            "memory_count": total_memory_count,
            "pending_conflicts": total_pending_conflicts,
            "token_count": total_token_count
        }
        total_count = total_memory_count
    elif project:
        store = get_store(project)
        memories = store.list_all(limit=20, offset=0)
        for m in memories:
            m["project"] = project
        memories = format_memories_datetime(memories)
        info = store.get_info()
        all_memories = store.list_all(limit=10000)
        info["token_count"] = calculate_total_tokens(all_memories)
        total_count = info.get("memory_count", 0)

    return templates.TemplateResponse("index.html", {
        "request": request,
        "memories": memories,
        "info": info,
        "projects": projects,
        "current_project": project,
        "all_projects_value": ALL_PROJECTS,
        "total_count": total_count,
        "debug_mode": server_config.get("debug_mode", False)
    })


@router.get("/search", response_class=HTMLResponse)
async def search_page(
    request: Request,
    q: str = Query(default=""),
    project: str = Query(default=""),
    type: str = Query(default=""),
    file: str = Query(default=""),
    sort: str = Query(default="relevance")
):
    """Search page with results and filtering/sorting options."""
    templates = get_templates(request)
    embedder = get_embedder(request)
    device = get_device(request)

    projects = list_projects()

    if not project:
        project = ALL_PROJECTS

    type_filter = [t.strip() for t in type.split(",") if t.strip()] if type else None
    file_filter = file.strip() if file else None
    sort_order = sort if sort in ("relevance", "newest", "oldest") else "relevance"

    results = []
    search_time = 0
    info = {"device": device, "embedding_dim": 384, "pending_conflicts": 0}

    if q:
        start = time.time()

        if project == ALL_PROJECTS:
            all_results = []
            total_pending_conflicts = 0

            for p in projects:
                store = get_store(p)
                p_results = store.query_filtered(
                    q,
                    top_k=60,
                    type_filter=type_filter,
                    file_filter=file_filter,
                    sort_order="relevance"
                )
                all_results.extend(p_results)
                total_pending_conflicts += store.count_pending_conflicts()

            if sort_order == "newest":
                all_results.sort(key=lambda x: x.get("created_at", ""), reverse=True)
            elif sort_order == "oldest":
                all_results.sort(key=lambda x: x.get("created_at", ""))
            else:
                all_results.sort(key=lambda x: x.get("distance", float('inf')))

            results = all_results[:20]
            results = format_memories_datetime(results)

            info = {
                "device": device,
                "embedding_dim": embedder.get_sentence_embedding_dimension() if embedder else 384,
                "pending_conflicts": total_pending_conflicts
            }
        elif project:
            store = get_store(project)
            results = store.query_filtered(
                q,
                top_k=20,
                type_filter=type_filter,
                file_filter=file_filter,
                sort_order=sort_order
            )
            results = format_memories_datetime(results)
            info = store.get_info()

        search_time = round((time.time() - start) * 1000, 2)

    return templates.TemplateResponse("search.html", {
        "request": request,
        "query": q,
        "results": results,
        "search_time": search_time,
        "info": info,
        "projects": projects,
        "current_project": project,
        "all_projects_value": ALL_PROJECTS,
        "selected_types": type_filter or [],
        "file_filter": file_filter or "",
        "sort_order": sort_order
    })


@router.get("/consolidation", response_class=HTMLResponse)
async def consolidation_page(
    request: Request,
    project: str = Query(default=""),
    threshold: float = Query(default=0.5),
    scan: bool = Query(default=False),
    view: str = Query(default="scan")
):
    """Group consolidation dashboard - find and merge duplicate clusters."""
    templates = get_templates(request)
    embedder = get_embedder(request)
    device = get_device(request)

    projects = list_projects()

    if not project:
        project = projects[0] if projects else ""

    clusters = []
    tiers = {"auto": 0, "llm_small": 0, "llm_large": 0}
    total_memories = 0
    history_entries = []
    info = {"device": device, "embedding_dim": 384, "memory_count": 0, "pending_conflicts": 0}

    # Load history if on history view
    if view == "history":
        from cli_utils import get_logs_dir

        log_files = []
        if project and project != ALL_PROJECTS:
            log_file = get_logs_dir(project) / "consolidation.log"
            if log_file.exists():
                log_files.append(log_file)
        else:
            for proj_dir in PROJECTS_DIR.iterdir():
                if proj_dir.is_dir():
                    log_file = proj_dir / "logs" / "consolidation.log"
                    if log_file.exists():
                        log_files.append(log_file)

        for log_file in log_files:
            with open(log_file, "r", encoding="utf-8") as f:
                for line in f:
                    if line.strip():
                        try:
                            entry = json.loads(line)
                            history_entries.append(entry)
                        except json.JSONDecodeError:
                            continue

        history_entries.sort(key=lambda x: x.get("timestamp", ""), reverse=True)

    if project == ALL_PROJECTS:
        total_memory_count = sum(get_store(p).count() for p in projects)
        total_pending = sum(get_store(p).count_pending_conflicts() for p in projects)
        info = {
            "device": device,
            "embedding_dim": embedder.get_sentence_embedding_dimension() if embedder else 384,
            "memory_count": total_memory_count,
            "pending_conflicts": total_pending
        }

        if scan:
            for p in projects:
                store = get_store(p)
                p_clusters = find_clusters(store, threshold)
                p_tiered = tier_clusters(p_clusters)

                for c in p_clusters:
                    cluster_dict = c.to_dict()
                    cluster_dict["project"] = p
                    clusters.append(cluster_dict)
                    total_memories += c.size

                tiers["auto"] += len(p_tiered["auto"])
                tiers["llm_small"] += len(p_tiered["llm_small"])
                tiers["llm_large"] += len(p_tiered["llm_large"])

            clusters.sort(key=lambda c: -c["size"])

    elif project:
        store = get_store(project)
        info = store.get_info()

        if scan:
            p_clusters = find_clusters(store, threshold)
            p_tiered = tier_clusters(p_clusters)

            clusters = [c.to_dict() for c in p_clusters]
            total_memories = sum(c["size"] for c in clusters)

            tiers = {
                "auto": len(p_tiered["auto"]),
                "llm_small": len(p_tiered["llm_small"]),
                "llm_large": len(p_tiered["llm_large"])
            }

    return templates.TemplateResponse("consolidation.html", {
        "request": request,
        "clusters": clusters,
        "tiers": tiers,
        "total_memories": total_memories,
        "threshold": threshold,
        "info": info,
        "projects": projects,
        "current_project": project,
        "all_projects_value": ALL_PROJECTS,
        "current_view": view,
        "history_entries": history_entries
    })


@router.get("/summaries", response_class=HTMLResponse)
async def summaries_page(
    request: Request,
    project: str = Query(default="")
):
    """Summary history and management page."""
    templates = get_templates(request)
    embedder = get_embedder(request)
    device = get_device(request)
    server_config = get_config(request)
    base_path = get_base_path(request)
    default_config = get_default_config(request)

    projects = list_projects()

    if not project:
        project = projects[0] if projects else ""

    summary_data = None
    history = []
    stats = {}
    info = {"device": device, "embedding_dim": 384, "memory_count": 0, "pending_conflicts": 0}

    if project and project != ALL_PROJECTS:
        store = get_store(project)
        manager = SummaryManager(base_path, project, store)

        summary_data = manager.load_current()
        history = manager.get_history(50)
        stats = manager.get_stats()
        info = store.get_info()

        memories = store.list_all(limit=10000)
        stats["memory_token_count"] = calculate_total_tokens(memories)

    summary_settings = server_config.get("summary", default_config["summary"])

    return templates.TemplateResponse("summaries.html", {
        "request": request,
        "summary": summary_data,
        "history": history,
        "stats": stats,
        "settings": summary_settings,
        "info": info,
        "projects": projects,
        "current_project": project,
        "all_projects_value": ALL_PROJECTS
    })


@router.get("/archive", response_class=HTMLResponse)
async def archive_page(
    request: Request,
    project: str = Query(default=""),
    reason: str = Query(default="")
):
    """Archive page - view and manage deleted memories."""
    templates = get_templates(request)
    device = get_device(request)

    projects = list_projects()

    if not project:
        project = projects[0] if projects else ALL_PROJECTS

    archived_memories = []
    stats = {"total": 0, "by_reason": {}}
    info = {"device": device, "embedding_dim": 384}

    if project == ALL_PROJECTS:
        for p in projects:
            store = get_store(p)
            p_memories = store.list_archived(limit=100, reason_filter=reason if reason else None)
            for m in p_memories:
                m["project"] = p
                if isinstance(m.get("files"), str):
                    try:
                        m["files"] = json.loads(m["files"])
                    except:
                        m["files"] = []
            archived_memories.extend(p_memories)
            p_stats = store.get_archive_stats()
            stats["total"] += p_stats.get("total", 0)
            for r, count in p_stats.get("by_reason", {}).items():
                stats["by_reason"][r] = stats["by_reason"].get(r, 0) + count

        archived_memories.sort(key=lambda x: x.get("deleted_at", ""), reverse=True)
        archived_memories = archived_memories[:50]
    else:
        store = get_store(project)
        archived_memories = store.list_archived(limit=50, reason_filter=reason if reason else None)
        stats = store.get_archive_stats()
        for m in archived_memories:
            if isinstance(m.get("files"), str):
                try:
                    m["files"] = json.loads(m["files"])
                except:
                    m["files"] = []

    return templates.TemplateResponse("archive.html", {
        "request": request,
        "archived_memories": archived_memories,
        "stats": stats,
        "reason_filter": reason,
        "has_more": len(archived_memories) >= 50,
        "info": info,
        "projects": projects,
        "current_project": project,
        "all_projects_value": ALL_PROJECTS
    })


@router.get("/conflicts", response_class=HTMLResponse)
async def conflicts_page(
    request: Request,
    project: str = Query(default=""),
    status: str = Query(default="pending")
):
    """Conflict resolution dashboard."""
    templates = get_templates(request)
    embedder = get_embedder(request)
    device = get_device(request)
    server_config = get_config(request)

    projects = list_projects()

    if not project:
        project = ALL_PROJECTS

    conflicts = []
    info = {"device": device, "embedding_dim": 384, "pending_conflicts": 0}
    pending_count = 0
    resolved_count = 0

    if project == ALL_PROJECTS:
        all_conflicts = []
        total_pending_conflicts = 0
        total_resolved_conflicts = 0

        confidence_priority = {"auto": 0, "high": 1, "medium": 2, "low": 3}

        for p in projects:
            store = get_store(p)
            p_conflicts = store.list_conflicts(status=status)
            for c in p_conflicts:
                c["project"] = p
            all_conflicts.extend(p_conflicts)
            total_pending_conflicts += store.count_pending_conflicts()
            total_resolved_conflicts += len(store.list_conflicts(status="resolved"))

        all_conflicts.sort(
            key=lambda x: (
                confidence_priority.get(x.get("confidence", "low"), 3),
                x.get("created_at", "") or ""
            ),
            reverse=False
        )
        all_conflicts.sort(
            key=lambda x: (
                confidence_priority.get(x.get("confidence", "low"), 3),
                -(hash(x.get("created_at", "")) if x.get("created_at") else 0)
            )
        )

        conflicts = all_conflicts
        conflicts = format_memories_datetime(conflicts)
        for c in conflicts:
            if c.get("conflict_with"):
                c["conflict_with"] = format_memories_datetime([c["conflict_with"]])[0]

        info = {
            "device": device,
            "embedding_dim": embedder.get_sentence_embedding_dimension() if embedder else 384,
            "pending_conflicts": total_pending_conflicts
        }
        pending_count = total_pending_conflicts
        resolved_count = total_resolved_conflicts
    elif project:
        store = get_store(project)
        conflicts = store.list_conflicts(status=status)
        for c in conflicts:
            c["project"] = project
        conflicts = format_memories_datetime(conflicts)
        for c in conflicts:
            if c.get("conflict_with"):
                c["conflict_with"] = format_memories_datetime([c["conflict_with"]])[0]
        info = store.get_info()
        pending_count = info.get("pending_conflicts", 0)
        resolved_count = len(store.list_conflicts(status="resolved"))

    return templates.TemplateResponse("conflicts.html", {
        "request": request,
        "conflicts": conflicts,
        "info": info,
        "projects": projects,
        "current_project": project,
        "all_projects_value": ALL_PROJECTS,
        "current_status": status,
        "pending_count": pending_count,
        "resolved_count": resolved_count,
        "auto_resolve_enabled": server_config.get("auto_resolve_enabled", False)
    })
