from __future__ import annotations

from typing import Any, Dict, List
import json
import os
import urllib.request
import sys
import subprocess

from ..base import ZoneOperation, ParamSpec


OP_UI_DELETE = "ui_delete_timesheet_entries"


def get_operations() -> List[ZoneOperation]:
    return [
        ZoneOperation(
            code=OP_UI_DELETE,
            label="UI Delete Timesheet entries",
            description=(
                "Elimina entradas (hours -> 0 + save) usando UI automation. "
                "Soporta delete_all e include_protected."
            ),
            http_method="UI",
            side_effect="write",
            idempotent=False,
            default_params={
                "timesheet_bu": None,
                "timesheet_user_id": None,
                "timesheet_user_name": None,
                "timesheet_date": None,
                "delete_all": False,
                "include_protected": False,
                "dry_run": False,
                "raw": False,
            },
            params=[
                ParamSpec("timesheet_bu", "string", True, "Business Unit a seleccionar en AroFlo."),
                ParamSpec("timesheet_user_id", "string", False, "AroFlo User ID (preferido, único)."),
                ParamSpec("timesheet_user_name", "string", False, "Nombre completo del usuario (fallback)."),
                ParamSpec("timesheet_date", "string", True, "Fecha objetivo (YYYY-MM-DD)."),
                ParamSpec("delete_all", "boolean", False, "Borra TODO en la fecha (hours->0)."),
                ParamSpec("include_protected", "boolean", False, "Incluye filas protegidas (solo con delete_all)."),
                ParamSpec("dry_run", "boolean", False, "Si true, no ejecuta UI; solo preview del comando."),
                ParamSpec("raw", "boolean", False, "Si true, incluye stdout/stderr completos del runner."),
            ],
            category="timesheets",
            use_cases=["Borrar overheads por UI", "Limpieza de días antes de reinsertar"],
            risk_level="high",
            requires_confirmation=True,
        ),
    ]


def supports(operation_code: str) -> bool:
    return operation_code == OP_UI_DELETE


def _preview(argv: List[str]) -> Dict[str, Any]:
    return {
        "dry_run": True,
        "invocation": "subprocess",
        "argv": argv,
    }


def _run_ui(argv: List[str], *, raw: bool = False) -> Dict[str, Any]:
    proc = subprocess.run(argv, capture_output=True, text=True, check=False)
    if raw:
        return {
            "returncode": proc.returncode,
            "stdout": proc.stdout,
            "stderr": proc.stderr,
            "argv": argv,
        }
    out_tail = (proc.stdout or "").strip().splitlines()[-30:]
    err_tail = (proc.stderr or "").strip().splitlines()[-30:]
    return {
        "returncode": proc.returncode,
        "stdout_tail": "\n".join(out_tail),
        "stderr_tail": "\n".join(err_tail),
        "argv": argv,
    }


def execute(operation_code: str, client: Any, params: Dict[str, Any]) -> Any:
    raw = bool(params.get("raw", False))
    dry_run = bool(params.get("dry_run", False))

    tenant_id = str(params.get("tenant_id") or params.get("tenant-id") or "").strip()
    worker_url = str(params.get("worker_url") or params.get("worker-url") or os.getenv("AROFLO_UI_WORKER_URL") or "").strip()
    if not worker_url:
        worker_url = "http://127.0.0.1:5010"
    timesheet_date = params.get("timesheet_date") or params.get("timesheet-date")
    if not timesheet_date:
        raise ValueError("timesheet_date es requerido (YYYY-MM-DD).")

    timesheet_bu = params.get("timesheet_bu") or params.get("timesheet-bu")
    if not timesheet_bu or not str(timesheet_bu).strip():
        raise ValueError("timesheet_bu es requerido (ej: 'Utility Solutions Group').")

    timesheet_user_id = str(params.get("timesheet_user_id") or params.get("timesheet-user-id") or "").strip()
    timesheet_user_name = str(params.get("timesheet_user_name") or params.get("timesheet-user-name") or "").strip()

    if not timesheet_user_id and not timesheet_user_name:
        raise ValueError("Debes enviar timesheet_user_id o timesheet_user_name (al menos uno).")

    if operation_code == OP_UI_DELETE:
        payload = {
            "tenant_id": tenant_id,
            "timesheet_bu": str(timesheet_bu),
            "timesheet_date": str(timesheet_date),
            "timesheet_user_id": timesheet_user_id,
            "timesheet_user_name": timesheet_user_name,
            "delete_all": bool(params.get("delete_all", False)),
            "include_protected": bool(params.get("include_protected", False)),
        }

        if dry_run:
            return {
                "dry_run": True,
                "invocation": "http",
                "url": f"{worker_url}/ui/timesheets/delete",
                "payload": payload,
            }

        req = urllib.request.Request(
            f"{worker_url}/ui/timesheets/delete",
            data=json.dumps(payload).encode("utf-8"),
            headers={"Content-Type": "application/json"},
            method="POST",
        )
        with urllib.request.urlopen(req, timeout=120) as resp:
            body = resp.read().decode("utf-8")
        return {"returncode": 0, "stdout": body, "stderr": "", "url": req.full_url}

    raise ValueError(f"[Timesheets.mu_ui_delete] Operación no soportada: {operation_code}")
