from __future__ import annotations

import argparse
from dataclasses import dataclass
from typing import Any, Callable, Dict, Optional

from autotouch_cli.exceptions import AutotouchInputError

from autotouch_cli.templates import TemplateRuntime


@dataclass(frozen=True)
class TaskCommandRuntime:
    resolve_token: Callable[[Optional[str], bool], Optional[str]]
    request_api: Callable[..., Any]
    print_json: Callable[[Any, bool], None]
    load_required_object_payload: Callable[..., Dict[str, Any]]
    load_json_input: Callable[..., Any]
    emit_tasks_recipe: Callable[[argparse.Namespace, TemplateRuntime], None]
    template_runtime_factory: Callable[[], TemplateRuntime]


def _task_mutation_params(args: argparse.Namespace) -> Optional[Dict[str, Any]]:
    actor_user_id = str(getattr(args, "actor_user_id", "") or "").strip()
    if actor_user_id:
        return {"actorUserId": actor_user_id}
    return None


def cmd_tasks_recipe(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    runtime.emit_tasks_recipe(args, runtime.template_runtime_factory())


def cmd_tasks_query(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    token = runtime.resolve_token(args.token, required=True)
    payload = runtime.load_required_object_payload(args, noun="tasks query")
    data = runtime.request_api(
        "POST",
        "/api/task-queue/query",
        base_url=args.base_url,
        token=token,
        use_x_api_key=args.use_x_api_key,
        payload=payload,
        timeout=args.timeout,
        verbose=args.verbose,
    )
    runtime.print_json(data, args.compact)


def cmd_tasks_count(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    token = runtime.resolve_token(args.token, required=True)
    payload = runtime.load_required_object_payload(args, noun="tasks count")
    data = runtime.request_api(
        "POST",
        "/api/task-queue/query/count",
        base_url=args.base_url,
        token=token,
        use_x_api_key=args.use_x_api_key,
        payload=payload,
        timeout=args.timeout,
        verbose=args.verbose,
    )
    runtime.print_json(data, args.compact)


def cmd_tasks_assignee_counts(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    token = runtime.resolve_token(args.token, required=True)
    payload = runtime.load_required_object_payload(args, noun="tasks assignee-counts")
    data = runtime.request_api(
        "POST",
        "/api/task-queue/assignee-counts",
        base_url=args.base_url,
        token=token,
        use_x_api_key=args.use_x_api_key,
        payload=payload,
        timeout=args.timeout,
        verbose=args.verbose,
    )
    runtime.print_json(data, args.compact)


def cmd_tasks_get(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    token = runtime.resolve_token(args.token, required=True)
    data = runtime.request_api(
        "GET",
        f"/api/task-queue/{args.task_id}",
        base_url=args.base_url,
        token=token,
        use_x_api_key=args.use_x_api_key,
        timeout=args.timeout,
        verbose=args.verbose,
    )
    runtime.print_json(data, args.compact)


def cmd_tasks_stats(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    token = runtime.resolve_token(args.token, required=True)
    data = runtime.request_api(
        "GET",
        "/api/task-queue/stats/summary",
        base_url=args.base_url,
        token=token,
        use_x_api_key=args.use_x_api_key,
        timeout=args.timeout,
        verbose=args.verbose,
    )
    runtime.print_json(data, args.compact)


def cmd_tasks_create(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    token = runtime.resolve_token(args.token, required=True)
    payload = runtime.load_required_object_payload(args, noun="task create")
    data = runtime.request_api(
        "POST",
        "/api/task-queue/create",
        base_url=args.base_url,
        token=token,
        use_x_api_key=args.use_x_api_key,
        params=_task_mutation_params(args),
        payload=payload,
        timeout=args.timeout,
        verbose=args.verbose,
    )
    runtime.print_json(data, args.compact)


def cmd_tasks_update(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    token = runtime.resolve_token(args.token, required=True)
    payload = runtime.load_required_object_payload(args, noun="task update")
    data = runtime.request_api(
        "PUT",
        f"/api/task-queue/{args.task_id}",
        base_url=args.base_url,
        token=token,
        use_x_api_key=args.use_x_api_key,
        params=_task_mutation_params(args),
        payload=payload,
        timeout=args.timeout,
        verbose=args.verbose,
    )
    runtime.print_json(data, args.compact)


def cmd_tasks_delete(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    token = runtime.resolve_token(args.token, required=True)
    data = runtime.request_api(
        "DELETE",
        f"/api/task-queue/{args.task_id}",
        base_url=args.base_url,
        token=token,
        use_x_api_key=args.use_x_api_key,
        params=_task_mutation_params(args),
        timeout=args.timeout,
        verbose=args.verbose,
    )
    runtime.print_json(data, args.compact)


def cmd_tasks_bulk_update(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    token = runtime.resolve_token(args.token, required=True)
    payload = runtime.load_required_object_payload(args, noun="task bulk update")
    data = runtime.request_api(
        "POST",
        "/api/task-queue/bulk-update",
        base_url=args.base_url,
        token=token,
        use_x_api_key=args.use_x_api_key,
        params=_task_mutation_params(args),
        payload=payload,
        timeout=args.timeout,
        verbose=args.verbose,
    )
    runtime.print_json(data, args.compact)


def cmd_tasks_bulk_delete(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    token = runtime.resolve_token(args.token, required=True)
    payload = runtime.load_required_object_payload(args, noun="task bulk delete")
    data = runtime.request_api(
        "POST",
        "/api/task-queue/bulk-delete",
        base_url=args.base_url,
        token=token,
        use_x_api_key=args.use_x_api_key,
        params=_task_mutation_params(args),
        payload=payload,
        timeout=args.timeout,
        verbose=args.verbose,
    )
    runtime.print_json(data, args.compact)


def cmd_tasks_draft(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    token = runtime.resolve_token(args.token, required=True)
    payload = runtime.load_json_input(
        inline_json=getattr(args, "data_json", None),
        file_path=getattr(args, "data_file", None),
        context="data",
        default=None,
    )
    if payload is None and bool(getattr(args, "force", False)):
        payload = {"force": True}
    if payload is not None and not isinstance(payload, dict):
        raise AutotouchInputError("task draft payload must be a JSON object")
    data = runtime.request_api(
        "POST",
        f"/api/task-queue/{args.task_id}/draft",
        base_url=args.base_url,
        token=token,
        use_x_api_key=args.use_x_api_key,
        params=_task_mutation_params(args),
        payload=payload,
        timeout=args.timeout,
        verbose=args.verbose,
    )
    runtime.print_json(data, args.compact)


def cmd_tasks_schedule_email(args: argparse.Namespace, *, runtime: TaskCommandRuntime) -> None:
    token = runtime.resolve_token(args.token, required=True)
    payload = runtime.load_required_object_payload(args, noun="task email schedule")
    data = runtime.request_api(
        "POST",
        f"/api/task-queue/{args.task_id}/email/schedule",
        base_url=args.base_url,
        token=token,
        use_x_api_key=args.use_x_api_key,
        params=_task_mutation_params(args),
        payload=payload,
        timeout=args.timeout,
        verbose=args.verbose,
    )
    runtime.print_json(data, args.compact)
