#!/usr/bin/env python3
"""SUPER-SKILL Platform — Claude Code ecosystem manager."""

import sys
from pathlib import Path

# Ensure _superskill package is importable
_HERE = Path(__file__).resolve().parent
if str(_HERE) not in sys.path:
    sys.path.insert(0, str(_HERE))

if sys.version_info < (3, 10):
    print(f"Error: Python 3.10+ requerido (actual: {sys.version.split()[0]})", file=sys.stderr)
    sys.exit(3)

try:
    import typer
    import rich  # noqa: F401
except ImportError as e:
    print(f"Dependencia faltante: {e}", file=sys.stderr)
    print("Instala con: pip install typer rich --user --break-system-packages", file=sys.stderr)
    sys.exit(3)

from typing import Optional
from typing_extensions import Annotated

from _superskill import VERSION
from _superskill import config as _config
from _superskill.ui.output import console
import _superskill.commands.status as _status_cmd
import _superskill.commands.doctor as _doctor_cmd
import _superskill.commands.profile as _profile_cmd
import _superskill.commands.catalog as _catalog_cmd
import _superskill.commands.audit as _audit_cmd
import _superskill.commands.project as _project_cmd
import _superskill.commands.workspace as _workspace_cmd
import _superskill.commands.discover as _discover_cmd
import _superskill.commands.health as _health_cmd
import _superskill.commands.blueprint as _blueprint_cmd
import _superskill.commands.projects as _projects_cmd
import _superskill.commands.feedback as _feedback_cmd
import _superskill.commands.assistant as _assistant_cmd
import _superskill.commands.daily as _daily_cmd
import _superskill.commands.home as _home_cmd
import _superskill.commands.do as _do_cmd
import _superskill.commands.update as _update_cmd
import _superskill.commands.scaffold as _scaffold_cmd
import _superskill.commands.compare as _compare_cmd
import _superskill.commands.skill as _skill_cmd

# ─── App ──────────────────────────────────────────────────────────────────────
app = typer.Typer(
    name="ss",
    help="SUPER-SKILL — Administra tu ecosistema Claude Code",
    no_args_is_help=False,
    invoke_without_command=True,
    add_completion=False,
    rich_markup_mode="rich",
)

profile_app = typer.Typer(help="Gestiona perfiles de Claude Code", no_args_is_help=True)
app.add_typer(profile_app, name="profile")


def _cfg():
    return _config.load()


# ─── Home callback (ss without arguments) ─────────────────────────────────────

@app.callback(invoke_without_command=True)
def cmd_home(ctx: typer.Context):
    """Menú principal interactivo cuando se invoca sin subcomando."""
    if ctx.invoked_subcommand is None:
        raise typer.Exit(_home_cmd.run_home(_cfg()))


# ─── Daily workflow commands (PHASE_30) ───────────────────────────────────────

@app.command("today")
def cmd_today():
    """Dashboard diario: proyectos, blueprints activos, alertas, salud."""
    raise typer.Exit(_daily_cmd.run_today(_cfg()))


@app.command("continue")
def cmd_continue():
    """Reanuda el último workspace activo con todo el contexto."""
    raise typer.Exit(_daily_cmd.run_continue(_cfg()))


@app.command("new")
def cmd_new(
    objective: Annotated[Optional[str], typer.Argument(
        help="Objetivo del proyecto (ej: \"crear una web WordPress\")"
    )] = None,
):
    """Asistente guiado: objetivo → plan → workspace → proyecto listo."""
    raise typer.Exit(_daily_cmd.run_new(_cfg(), objective=objective))


@app.command("close")
def cmd_close():
    """Cierra el workspace activo y muestra el resumen de sesión."""
    raise typer.Exit(_workspace_cmd.run_close(_cfg()))


@app.command("apply")
def cmd_apply():
    """Aplica el plan de activación del workspace activo (atajo de ss workspace --apply)."""
    raise typer.Exit(_workspace_cmd.run_apply(_cfg()))


@app.command("do")
def cmd_do(
    text: Annotated[Optional[str], typer.Argument(
        help="Intención en lenguaje natural (ej: \"mejorar SEO de rovnek\")"
    )] = None,
):
    """Entrada inteligente: detecta tu intención y ejecuta el flujo correcto."""
    raise typer.Exit(_do_cmd.run_do(_cfg(), text=text))


# ─── Commands ─────────────────────────────────────────────────────────────────

@app.command("version")
def cmd_version():
    """Muestra la versión de SUPER-SKILL."""
    console.print(f"SUPER-SKILL v{VERSION}")


@app.command("status")
def cmd_status():
    """Resumen del ecosistema (perfiles, pool, alertas)."""
    raise typer.Exit(_status_cmd.run(_cfg()))


@app.command("doctor")
def cmd_doctor(
    fix: Annotated[bool, typer.Option("--fix", help="Aplica correcciones automáticas seguras")] = False,
):
    """Diagnostica el ecosistema y sugiere correcciones."""
    raise typer.Exit(_doctor_cmd.run(_cfg(), fix=fix))


@app.command("catalog")
def cmd_catalog():
    """Abre el catálogo HTML de skills en el navegador."""
    raise typer.Exit(_catalog_cmd.run(_cfg()))


@app.command("audit")
def cmd_audit(
    fix: Annotated[bool, typer.Option("--fix", help="Aplica correcciones automáticas seguras")] = False,
):
    """Auditoría completa de integridad del ecosistema."""
    raise typer.Exit(_audit_cmd.run(_cfg(), fix=fix))


@app.command("project")
def cmd_project(
    path: Annotated[str, typer.Argument(help="Ruta o nombre del proyecto (ej: rovnek)")],
):
    """Analiza un proyecto y genera un plan de ejecución (dry-run)."""
    raise typer.Exit(_project_cmd.run(_cfg(), path))


@app.command("workspace")
def cmd_workspace(
    path: Annotated[Optional[str], typer.Argument(
        help="Proyecto (ej: rovnek, .) o lifecycle: sync | status | close"
    )] = None,
    list_all: Annotated[bool, typer.Option(
        "--list", "-l", help="Lista todos los workspaces registrados"
    )] = False,
    apply: Annotated[bool, typer.Option(
        "--apply", help="Ejecuta el plan de forma controlada (requiere confirmación)"
    )] = False,
    sync: Annotated[bool, typer.Option(
        "--sync", help="Fuerza re-análisis completo (ignora cache)"
    )] = False,
    status: Annotated[bool, typer.Option(
        "--status", help="Estado compacto desde cache (sin re-análisis)"
    )] = False,
    close: Annotated[bool, typer.Option(
        "--close", help="Cierra la sesión y guarda el resumen"
    )] = False,
    brief: Annotated[bool, typer.Option(
        "--brief", "-b", help="Vista compacta de 5-10 líneas (para consultas rápidas)"
    )] = False,
    mode: Annotated[Optional[str], typer.Option(
        "--mode", "-m",
        help="Modo operativo: development | production | expert"
    )] = None,
    profile: Annotated[Optional[str], typer.Option(
        "--profile", "-p",
        help="Perfil profesional (ej: desarrollo-web, seo-geo, ia-generativa)"
    )] = None,
):
    """Panel de trabajo del workspace: open · sync · status · close · brief."""
    # ── Lifecycle keywords as positional argument (ss workspace sync) ──────────
    if path in ("sync", "status", "close"):
        if path == "sync":
            raise typer.Exit(_workspace_cmd.run_sync(_cfg(), None, mode_override=mode))
        if path == "status":
            raise typer.Exit(_workspace_cmd.run_status(_cfg(), None))
        if path == "close":
            raise typer.Exit(_workspace_cmd.run_close(_cfg(), None))

    # ── No path given (or --list) ──────────────────────────────────────────────
    if list_all or path is None:
        if sync:
            raise typer.Exit(_workspace_cmd.run_sync(_cfg(), None, mode_override=mode))
        if status:
            raise typer.Exit(_workspace_cmd.run_status(_cfg(), None))
        if close:
            raise typer.Exit(_workspace_cmd.run_close(_cfg(), None))
        raise typer.Exit(_workspace_cmd.run_list(_cfg()))

    # ── Explicit path given ────────────────────────────────────────────────────
    if apply:
        raise typer.Exit(_workspace_cmd.run_apply(_cfg(), path, mode_override=mode))
    if sync:
        raise typer.Exit(_workspace_cmd.run_sync(_cfg(), path, mode_override=mode))
    if status:
        raise typer.Exit(_workspace_cmd.run_status(_cfg(), path))
    if close:
        raise typer.Exit(_workspace_cmd.run_close(_cfg(), path))
    raise typer.Exit(_workspace_cmd.run(_cfg(), path, mode_override=mode, profile_override=profile, brief=brief))


@app.command("mode")
def cmd_mode(
    value: Annotated[Optional[str], typer.Argument(
        help="Nuevo modo global: development | production | expert"
    )] = None,
):
    """Muestra o configura el modo operativo global."""
    if value is None:
        raise typer.Exit(_workspace_cmd.run_show_mode(_cfg()))
    raise typer.Exit(_workspace_cmd.run_set_mode(_cfg(), value))


@app.command("discover")
def cmd_discover(
    workspace: Annotated[Optional[str], typer.Option(
        "--workspace", "-w",
        help="Workspace específico (ej: rovnek, .) — default: workspace activo"
    )] = None,
    profile: Annotated[Optional[str], typer.Option(
        "--profile", "-p",
        help="Perfil profesional (ej: desarrollo-web, seo-geo)"
    )] = None,
    summary: Annotated[bool, typer.Option(
        "--summary", "-s",
        help="Inventario global del ecosistema (sin workspace)"
    )] = False,
    refresh: Annotated[bool, typer.Option(
        "--refresh",
        help="Fuerza re-análisis ignorando la caché"
    )] = False,
    apply: Annotated[bool, typer.Option(
        "--apply",
        help="Activa los recursos más recomendados en el perfil activo"
    )] = False,
    fix: Annotated[bool, typer.Option(
        "--fix",
        help="Repara recursos rotos (symlinks, caches corruptas)"
    )] = False,
    explain: Annotated[Optional[str], typer.Option(
        "--explain",
        help="Explica por qué se recomienda un recurso (ej: --explain seo-optimizer)"
    )] = None,
    remote: Annotated[bool, typer.Option(
        "--remote",
        help="Busca recursos en fuentes externas (GitHub, Smithery) — requiere internet"
    )] = False,
):
    """Descubre y puntúa recursos disponibles para un workspace o perfil."""
    if explain:
        raise typer.Exit(_discover_cmd.run_explain(_cfg(), explain, workspace))
    if fix:
        raise typer.Exit(_discover_cmd.run_fix(_cfg()))
    if apply:
        raise typer.Exit(_discover_cmd.run_apply(_cfg(), workspace))
    if summary:
        raise typer.Exit(_discover_cmd.run_summary(_cfg()))
    if profile:
        raise typer.Exit(_discover_cmd.run_profile(_cfg(), profile))
    if remote:
        raise typer.Exit(_discover_cmd.run_remote(_cfg(), workspace, force_refresh=refresh))
    raise typer.Exit(_discover_cmd.run_workspace(_cfg(), workspace, force_refresh=refresh))


@app.command("health")
def cmd_health(
    repair: Annotated[bool, typer.Option(
        "--repair",
        help="Aplica reparaciones automáticas seguras"
    )] = False,
):
    """Puntuación de salud del ecosistema y reparación automática."""
    if repair:
        raise typer.Exit(_health_cmd.run_repair(_cfg()))
    raise typer.Exit(_health_cmd.run(_cfg()))


@app.command("blueprint")
def cmd_blueprint(
    workspace: Annotated[Optional[str], typer.Option(
        "--workspace", "-w",
        help="Workspace (ej: rovnek, .) — default: workspace activo"
    )] = None,
    profile: Annotated[Optional[str], typer.Option(
        "--profile", "-p",
        help="Perfil profesional (ej: desarrollo-web)"
    )] = None,
    summary: Annotated[bool, typer.Option(
        "--summary", "-s",
        help="Vista global de todos los blueprints del ecosistema"
    )] = False,
    export: Annotated[Optional[str], typer.Option(
        "--export",
        help="Exportar en formato: json | markdown"
    )] = None,
    compact: Annotated[bool, typer.Option(
        "--compact",
        help="Vista compacta (fases sin detalle de tareas)"
    )] = False,
    # ── PHASE_24: Execution controls ──────────────────────────────────────────
    execute: Annotated[bool, typer.Option(
        "--execute",
        help="Ejecuta las tareas AUTO y solicita confirmación para CONFIRM"
    )] = False,
    dry_run: Annotated[bool, typer.Option(
        "--dry-run",
        help="Simula la ejecución sin modificar el filesystem (úsalo con --execute)"
    )] = False,
    track: Annotated[bool, typer.Option(
        "--track",
        help="Muestra el dashboard de seguimiento de la ejecución"
    )] = False,
    complete: Annotated[Optional[str], typer.Option(
        "--complete",
        help="Marca una tarea como completada (ej: --complete t001)"
    )] = None,
    skip: Annotated[Optional[str], typer.Option(
        "--skip",
        help="Marca una tarea como omitida (ej: --skip t003)"
    )] = None,
    pause: Annotated[bool, typer.Option(
        "--pause",
        help="Pausa la ejecución actual"
    )] = False,
    resume: Annotated[bool, typer.Option(
        "--resume",
        help="Reanuda una ejecución pausada"
    )] = False,
    cancel: Annotated[bool, typer.Option(
        "--cancel",
        help="Cancela la ejecución (el progreso previo se conserva)"
    )] = False,
    diff: Annotated[bool, typer.Option(
        "--diff",
        help="Compara el blueprint actual con la versión anterior"
    )] = False,
):
    """Plan de ejecución estructurado — analiza, ejecuta y sigue el progreso."""
    # ── Execution controls (PHASE_24) ─────────────────────────────────────────
    if diff:
        raise typer.Exit(_blueprint_cmd.run_diff(_cfg(), workspace))
    if cancel:
        raise typer.Exit(_blueprint_cmd.run_cancel(_cfg(), workspace))
    if pause:
        raise typer.Exit(_blueprint_cmd.run_pause(_cfg(), workspace))
    if resume:
        raise typer.Exit(_blueprint_cmd.run_resume(_cfg(), workspace))
    if complete:
        raise typer.Exit(_blueprint_cmd.run_complete(_cfg(), complete, workspace))
    if skip:
        raise typer.Exit(_blueprint_cmd.run_skip_task(_cfg(), skip, workspace))
    if track:
        raise typer.Exit(_blueprint_cmd.run_track(_cfg(), workspace))
    if execute:
        raise typer.Exit(_blueprint_cmd.run_execute(_cfg(), workspace, dry_run=dry_run))
    # ── View controls (PHASE_23) ──────────────────────────────────────────────
    if export:
        raise typer.Exit(_blueprint_cmd.run_export(_cfg(), workspace, export))
    if summary:
        raise typer.Exit(_blueprint_cmd.run_summary(_cfg()))
    if profile:
        raise typer.Exit(_blueprint_cmd.run_profile(_cfg(), profile))
    raise typer.Exit(_blueprint_cmd.run(_cfg(), workspace, compact=compact))


@app.command("projects")
def cmd_projects(
    status: Annotated[bool, typer.Option(
        "--status",
        help="Vista de estado de todos los proyectos"
    )] = False,
    health: Annotated[bool, typer.Option(
        "--health",
        help="Health breakdown por proyecto + salud global"
    )] = False,
    sync: Annotated[bool, typer.Option(
        "--sync",
        help="Actualiza cachés de discovery expiradas"
    )] = False,
    priority: Annotated[bool, typer.Option(
        "--priority",
        help="Vista de prioridades con señales explicadas"
    )] = False,
    summary: Annotated[bool, typer.Option(
        "--summary", "-s",
        help="Resumen ejecutivo del portfolio"
    )] = False,
    set_priority: Annotated[Optional[str], typer.Option(
        "--set-priority",
        help="Establece prioridad manual (ej: --set-priority rovnek critical)"
    )] = None,
    priority_value: Annotated[Optional[str], typer.Option(
        "--priority-value",
        help="Valor de prioridad para --set-priority: critical | high | normal | low",
        hidden=True,
    )] = None,
):
    """Dashboard global del portfolio de proyectos."""
    if set_priority:
        pv = priority_value or "normal"
        raise typer.Exit(_projects_cmd.run_set_priority(_cfg(), set_priority, pv))
    if sync:
        raise typer.Exit(_projects_cmd.run_sync(_cfg()))
    if health:
        raise typer.Exit(_projects_cmd.run_health(_cfg()))
    if priority:
        raise typer.Exit(_projects_cmd.run_priority(_cfg()))
    if summary:
        raise typer.Exit(_projects_cmd.run_summary(_cfg()))
    if status:
        raise typer.Exit(_projects_cmd.run_status(_cfg()))
    raise typer.Exit(_projects_cmd.run(_cfg()))


@app.command("update")
def cmd_update(
    skill: Annotated[Optional[str], typer.Argument(
        help="Nombre del skill a actualizar (omitir para ver todos)"
    )] = None,
    check: Annotated[bool, typer.Option(
        "--check",
        help="Lista recursos con actualizaciones disponibles (sin cambios)"
    )] = False,
    rollback: Annotated[bool, typer.Option(
        "--rollback",
        help="Restaura el backup más reciente del skill indicado"
    )] = False,
):
    """Resource Lifecycle — detecta, informa y gestiona actualizaciones de skills."""
    if rollback:
        if not skill:
            console.print("  [err]Error:[/err]  Indica el nombre del skill: ss update --rollback <nombre>\n")
            raise typer.Exit(1)
        raise typer.Exit(_update_cmd.run_rollback(_cfg(), skill))
    if skill and not check:
        raise typer.Exit(_update_cmd.run_update(_cfg(), skill))
    raise typer.Exit(_update_cmd.run_check(_cfg()))


@app.command("compare")
def cmd_compare(
    resource_a: Annotated[str, typer.Argument(help="Primer recurso a comparar")],
    resource_b: Annotated[str, typer.Argument(help="Segundo recurso a comparar")],
):
    """Comparación lado a lado de dos recursos (capacidades, estado, versión, recomendación)."""
    raise typer.Exit(_compare_cmd.run_compare(_cfg(), resource_a, resource_b))


@app.command("skill")
def cmd_skill(
    fork: Annotated[Optional[str], typer.Option(
        "--fork",
        help="Nombre del skill fuente a bifurcar"
    )] = None,
    to: Annotated[Optional[str], typer.Option(
        "--to",
        help="Nombre del skill destino (nuevo fork)"
    )] = None,
    show: Annotated[Optional[str], typer.Option(
        "--show",
        help="Muestra detalles de un skill del pool"
    )] = None,
):
    """Gestión de skills: fork, show."""
    if fork:
        if not to:
            console.print("  [err]Error:[/err]  Indica el destino: ss skill --fork <nombre> --to <nuevo>\n")
            raise typer.Exit(1)
        raise typer.Exit(_skill_cmd.run_fork(_cfg(), fork, to))
    if show:
        raise typer.Exit(_skill_cmd.run_show(_cfg(), show))
    console.print("  [muted]Uso: ss skill --fork <nombre> --to <nuevo>  |  ss skill --show <nombre>[/muted]\n")
    raise typer.Exit(0)


@app.command("scaffold")
def cmd_scaffold(
    kind: Annotated[Optional[str], typer.Argument(
        help="Tipo de recurso a crear: skill"
    )] = None,
    name: Annotated[Optional[str], typer.Argument(
        help="Nombre del recurso (ej: seo-local-reviews)"
    )] = None,
    dry_run: Annotated[bool, typer.Option(
        "--dry-run",
        help="Muestra el contenido generado sin escribir en disco"
    )] = False,
    list_templates: Annotated[bool, typer.Option(
        "--list", "-l",
        help="Lista los templates de scaffold disponibles"
    )] = False,
):
    """Skill Construction Engine — genera el skeleton de una nueva skill desde template."""
    if list_templates:
        raise typer.Exit(_scaffold_cmd.run_list(_cfg()))
    if kind == "skill":
        if not name:
            console.print("  [err]Error:[/err]  Indica el nombre: ss scaffold skill <nombre>\n")
            raise typer.Exit(1)
        raise typer.Exit(_scaffold_cmd.run_scaffold_skill(_cfg(), name, dry_run=dry_run))
    console.print("  [muted]Uso: ss scaffold skill <nombre>  |  ss scaffold --list[/muted]\n")
    raise typer.Exit(0)


@app.command("feedback")
def cmd_feedback(
    workspace: Annotated[Optional[str], typer.Option(
        "--workspace", "-w",
        help="Feedback de un workspace específico (ej: rovnek)"
    )] = None,
    summary: Annotated[bool, typer.Option(
        "--summary", "-s",
        help="Resumen ejecutivo de métricas del portfolio"
    )] = False,
    history: Annotated[bool, typer.Option(
        "--history",
        help="Historial de eventos de ejecución"
    )] = False,
    recompute: Annotated[bool, typer.Option(
        "--recompute",
        help="Recalcula los pesos de aprendizaje desde todos los eventos"
    )] = False,
    export: Annotated[bool, typer.Option(
        "--export",
        help="Exporta el informe en formato Markdown"
    )] = False,
):
    """Runtime Feedback Loop — métricas, aprendizaje y calidad de ejecución."""
    if export:
        raise typer.Exit(_feedback_cmd.run_export_markdown(_cfg(), workspace))
    if recompute:
        raise typer.Exit(_feedback_cmd.run_recompute(_cfg()))
    if history:
        raise typer.Exit(_feedback_cmd.run_history(_cfg()))
    if summary:
        raise typer.Exit(_feedback_cmd.run_summary(_cfg()))
    if workspace:
        raise typer.Exit(_feedback_cmd.run_workspace(_cfg(), workspace))
    raise typer.Exit(_feedback_cmd.run(_cfg()))


@app.command("assistant")
def cmd_assistant(
    objective: Annotated[Optional[str], typer.Argument(
        help="Objetivo a conseguir (ej: \"crear una web WordPress\")"
    )] = None,
    level: Annotated[str, typer.Option(
        "--level", "-l",
        help="Nivel de explicación: novato | profesional | experto"
    )] = "profesional",
    output_json: Annotated[bool, typer.Option(
        "--json",
        help="Salida JSON para consumo por Flutter/API"
    )] = False,
    catalog: Annotated[bool, typer.Option(
        "--catalog", "-c",
        help="Muestra el catálogo de objetivos disponibles"
    )] = False,
):
    """AI Workflow Assistant — convierte objetivos en Workflows automáticamente."""
    lv = level if level in ("novato", "profesional", "experto") else "profesional"
    raise typer.Exit(_assistant_cmd.run(
        objective=objective,
        level=lv,
        output_json=output_json,
        show_catalog=catalog,
    ))


# ─── Profile subcommands ───────────────────────────────────────────────────────

@profile_app.command("list")
def cmd_profile_list():
    """Lista todos los perfiles con estadísticas."""
    raise typer.Exit(_profile_cmd.run_list(_cfg()))


@profile_app.command("catalog")
def cmd_profile_catalog(
    match: Annotated[Optional[str], typer.Option(
        "--match", "-m",
        help="Workspace para mostrar compatibilidad (ej: rovnek)"
    )] = None,
):
    """Lista el catálogo de perfiles profesionales y su uso en workspaces."""
    raise typer.Exit(_profile_cmd.run_catalog(_cfg(), match_workspace=match))


@profile_app.command("show")
def cmd_profile_show(
    name: Annotated[Optional[str], typer.Argument(help="Alias del perfil (default: activo)")] = None,
):
    """Muestra detalle de un perfil."""
    raise typer.Exit(_profile_cmd.run_show(_cfg(), name=name))


@profile_app.command("create")
def cmd_profile_create(
    path: Annotated[Path, typer.Argument(help="Ruta del nuevo perfil (ej: ~/.claude-03)")],
    alias: Annotated[Optional[str], typer.Option("--alias", "-a", help="Alias para ~/.bashrc")] = None,
):
    """Crea un nuevo perfil usando el script de bootstrap."""
    raise typer.Exit(_profile_cmd.run_create(_cfg(), profile_path=path, alias=alias))


# ─── Main ─────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
    app()
