from __future__ import annotations

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

from ..base import ZoneOperation, ParamSpec


OP_UI_UPLOAD_DOCS = "ui_upload_user_documents"


def get_operations() -> List[ZoneOperation]:
    return [
        ZoneOperation(
            code=OP_UI_UPLOAD_DOCS,
            label="UI Upload User Documents",
            description="Sube documentos al usuario via UI automation (Users -> Documents & Photos).",
            http_method="UI",
            side_effect="write",
            idempotent=False,
            default_params={
                "timesheet_bu": None,
                "user_email": None,
                "docs": None,
                "dry_run": False,
                "raw": False,
            },
            params=[
                ParamSpec("timesheet_bu", "string", True, "Business Unit a seleccionar en AroFlo."),
                ParamSpec("user_email", "string", True, "Email del usuario."),
                ParamSpec(
                    "docs",
                    "array",
                    True,
                    "Lista de documentos. Cada item: file=...;comment=...;filter=...",
                    items_schema={"type": "string"},
                ),
                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="users",
            use_cases=["Subir documentos por UI", "Evidencias y adjuntos de usuario"],
            risk_level="high",
            requires_confirmation=True,
        ),
    ]


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


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))

    user_email = str(params.get("user_email") or params.get("user-email") or "").strip()
    if not user_email:
        raise ValueError("user_email es requerido (ej: cpenuela@usg.com.au).")

    docs = params.get("docs") or []
    if not isinstance(docs, list) or not docs:
        raise ValueError("docs es requerido y debe ser una lista no vacía de strings --doc.")

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

    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"

    tenant_id = str(params.get("tenant_id") or params.get("tenant-id") or "").strip()

    payload = {
        "tenant_id": tenant_id,
        "timesheet_bu": timesheet_bu,
        "user_email": user_email,
        "docs": [str(d).strip() for d in docs if str(d).strip()],
    }

    if dry_run:
        return {
            "dry_run": True,
            "invocation": "http",
            "url": f"{worker_url}/ui/users/upload-docs",
            "payload": payload,
        }

    req = urllib.request.Request(
        f"{worker_url}/ui/users/upload-docs",
        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}
