"""
Session context builder.

Main entry point for building complete session context from the current environment.
"""

import hashlib
import os
import subprocess
from pathlib import Path
from typing import Optional

from lightwave.context.context_models import (
    EnvironmentContext,
    KnowledgeContext,
    PlanContext,
    PlanStatus,
    SessionContext,
    SprintContext,
)
from lightwave.context.createos import fetch_plans_for_task, fetch_sprint, fetch_task_context
from lightwave.context.git import get_git_context


def get_python_version() -> str:
    """Get Python version string."""
    try:
        result = subprocess.run(
            ["python", "--version"],
            capture_output=True,
            text=True,
            check=True,
        )
        return result.stdout.strip().replace("Python ", "")
    except subprocess.CalledProcessError:
        return "unknown"


def get_node_version() -> Optional[str]:
    """Get Node.js version string if available."""
    try:
        result = subprocess.run(
            ["node", "--version"],
            capture_output=True,
            text=True,
            check=True,
        )
        return result.stdout.strip()
    except (subprocess.CalledProcessError, FileNotFoundError):
        return None


def get_uv_lock_hash(workspace_root: Path) -> Optional[str]:
    """Get hash of uv.lock file to detect dependency changes."""
    lock_file = workspace_root / "uv.lock"
    if lock_file.exists():
        content = lock_file.read_bytes()
        return hashlib.sha256(content).hexdigest()
    return None


def get_active_services(workspace_root: Path) -> list[str]:
    """Detect active services via docker-compose or other means."""
    services = []

    # Check for docker-compose
    compose_file = workspace_root / "docker-compose.yml"
    if compose_file.exists():
        try:
            result = subprocess.run(
                ["docker-compose", "ps", "--services", "--filter", "status=running"],
                cwd=workspace_root,
                capture_output=True,
                text=True,
                check=True,
            )
            services.extend(result.stdout.strip().split("\n"))
        except (subprocess.CalledProcessError, FileNotFoundError):
            pass

    return [s for s in services if s]  # Filter empty strings


def find_plan_file(workspace_root: Path, task_id: str) -> Optional[Path]:
    """Find implementation plan markdown file for a task.

    Searches .claude/plans/ directory for files matching the task ID.

    Args:
        workspace_root: Root of the workspace
        task_id: Task short ID

    Returns:
        Path to plan file if found, None otherwise
    """
    plans_dir = workspace_root / ".claude" / "plans"
    if not plans_dir.exists():
        return None

    # Look for files with task ID in name
    for plan_file in plans_dir.glob(f"*{task_id}*.md"):
        if plan_file.is_file():
            return plan_file

    return None


def build_environment_context(workspace_root: Path) -> EnvironmentContext:
    """Build environment context."""
    return EnvironmentContext(
        workspace_root=workspace_root,
        python_version=get_python_version(),
        node_version=get_node_version(),
        uv_lock_hash=get_uv_lock_hash(workspace_root),
        active_services=get_active_services(workspace_root),
        aws_profile=os.getenv("AWS_PROFILE"),
    )


def build_plan_context(task_id: str, workspace_root: Path) -> Optional[PlanContext]:
    """Build plan context for a task.

    Args:
        task_id: Task ID
        workspace_root: Workspace root path

    Returns:
        PlanContext if plan found, None otherwise
    """
    # Fetch plans from createOS
    plans = fetch_plans_for_task(task_id)
    if not plans:
        return None

    # Get the most recent non-superseded plan
    active_plans = [p for p in plans if p.status != "superseded"]
    if not active_plans:
        return None

    # Sort by version descending
    active_plans.sort(key=lambda p: p.version, reverse=True)
    plan = active_plans[0]

    # Find plan file on disk
    plan_file_path = find_plan_file(workspace_root, task_id)

    # Build plan status
    # TODO: Parse plan file to determine current step and completed steps
    # For now, use placeholder logic
    current_step = None
    completed_steps: list[int] = []
    total_steps = len(plan.critical_files) if plan.critical_files else 1

    plan_status = PlanStatus(
        status=plan.status,  # type: ignore
        version=plan.version,
        current_step=current_step,
        total_steps=total_steps,
        completed_steps=completed_steps,
    )

    # Get active risks
    risks_active = [r for r in plan.risks if r.is_active]

    return PlanContext(
        plan=plan,
        current_step=current_step,
        completed_steps=completed_steps,
        status=plan_status,
        risks_active=risks_active,
        plan_file_path=plan_file_path,
    )


def build_sprint_context(sprint_id: str) -> Optional[SprintContext]:
    """Build sprint context.

    Args:
        sprint_id: Sprint ID

    Returns:
        SprintContext if sprint found, None otherwise
    """
    sprint = fetch_sprint(sprint_id)
    if not sprint:
        return None

    # TODO: Fetch sprint tasks and calculate progress
    # For now, return basic sprint info
    return SprintContext(
        sprint=sprint,
        progress=0.0,
        tasks=[],
        objectives=[],
    )


def build_session_context(cwd: Optional[Path] = None) -> SessionContext:
    """Build complete session context from current environment.

    Args:
        cwd: Current working directory (default: current directory)

    Returns:
        Complete SessionContext
    """
    if cwd is None:
        cwd = Path.cwd()

    # Find workspace root (directory containing .git or pyproject.toml)
    workspace_root = cwd
    while workspace_root != workspace_root.parent:
        if (workspace_root / ".git").exists() or (workspace_root / "pyproject.toml").exists():
            break
        workspace_root = workspace_root.parent

    # Build git context
    git_context = get_git_context(cwd)
    if git_context is None:
        raise RuntimeError("Not in a git repository")

    # Build environment context
    environment_context = build_environment_context(workspace_root)

    # Build task context (if task ID found in branch)
    task_context = None
    plan_context = None
    sprint_context = None

    if git_context.task_id_from_branch:
        task_context = fetch_task_context(git_context.task_id_from_branch)

        if task_context:
            # Build plan context
            plan_context = build_plan_context(task_context.task.short_id, workspace_root)

            # Build sprint context
            if task_context.sprint:
                sprint_context = build_sprint_context(task_context.sprint.id)

    # Build knowledge context
    # TODO: Implement knowledge graph queries
    knowledge_context = KnowledgeContext()

    return SessionContext(
        git=git_context,
        task=task_context,
        sprint=sprint_context,
        plan=plan_context,
        knowledge=knowledge_context,
        environment=environment_context,
    )
