from __future__ import annotations

import argparse
from typing import Callable, Dict, List


def add_tasks_subcommands(
    tasks_sub: argparse._SubParsersAction,
    *,
    add_api_common_arguments: Callable[[argparse.ArgumentParser], None],
    add_actor_override_argument: Callable[[argparse.ArgumentParser], None],
    task_recipe_types: List[str],
    handlers: Dict[str, Callable],
) -> None:
    ptaskrecipe = tasks_sub.add_parser("recipe", help="Print task payload recipes")
    ptaskrecipe.add_argument("--type", choices=["all", *task_recipe_types], default="all")
    ptaskrecipe.add_argument("--out-file", help="Optional path to save the selected payload JSON")
    add_api_common_arguments(ptaskrecipe)
    ptaskrecipe.set_defaults(func=handlers["recipe"])

    ptq = tasks_sub.add_parser("query", help="Query tasks with a TaskQueryRequest payload")
    ptq.add_argument("--data-json", help="TaskQueryRequest payload JSON")
    ptq.add_argument("--data-file", help="Path to TaskQueryRequest payload JSON file")
    add_api_common_arguments(ptq)
    ptq.set_defaults(func=handlers["query"])

    ptqc = tasks_sub.add_parser("count", help="Count tasks matching a TaskQueryRequest payload")
    ptqc.add_argument("--data-json", help="TaskQueryRequest payload JSON")
    ptqc.add_argument("--data-file", help="Path to TaskQueryRequest payload JSON file")
    add_api_common_arguments(ptqc)
    ptqc.set_defaults(func=handlers["count"])

    ptqa = tasks_sub.add_parser("assignee-counts", help="Aggregate assignee counts for a TaskQueryRequest payload")
    ptqa.add_argument("--data-json", help="TaskQueryRequest payload JSON")
    ptqa.add_argument("--data-file", help="Path to TaskQueryRequest payload JSON file")
    add_api_common_arguments(ptqa)
    ptqa.set_defaults(func=handlers["assignee_counts"])

    ptg = tasks_sub.add_parser("get", help="Get one task by id")
    ptg.add_argument("--task-id", required=True)
    add_api_common_arguments(ptg)
    ptg.set_defaults(func=handlers["get"])

    pts = tasks_sub.add_parser("stats", help="Get task summary stats")
    add_api_common_arguments(pts)
    pts.set_defaults(func=handlers["stats"])

    ptc = tasks_sub.add_parser("create", help="Create tasks from a JSON payload")
    ptc.add_argument("--data-json", help="TaskQueueCreate payload JSON")
    ptc.add_argument("--data-file", help="Path to TaskQueueCreate payload JSON file")
    add_actor_override_argument(ptc)
    add_api_common_arguments(ptc)
    ptc.set_defaults(func=handlers["create"])

    ptu = tasks_sub.add_parser("update", help="Update one task from a JSON payload")
    ptu.add_argument("--task-id", required=True)
    ptu.add_argument("--data-json", help="TaskQueueUpdate payload JSON")
    ptu.add_argument("--data-file", help="Path to TaskQueueUpdate payload JSON file")
    add_actor_override_argument(ptu)
    add_api_common_arguments(ptu)
    ptu.set_defaults(func=handlers["update"])

    ptd = tasks_sub.add_parser("delete", help="Delete one task (soft delete to skipped)")
    ptd.add_argument("--task-id", required=True)
    add_actor_override_argument(ptd)
    add_api_common_arguments(ptd)
    ptd.set_defaults(func=handlers["delete"])

    ptbu = tasks_sub.add_parser("bulk-update", help="Bulk update tasks from a JSON payload")
    ptbu.add_argument("--data-json", help="BulkTaskUpdateRequest payload JSON")
    ptbu.add_argument("--data-file", help="Path to BulkTaskUpdateRequest payload JSON file")
    add_actor_override_argument(ptbu)
    add_api_common_arguments(ptbu)
    ptbu.set_defaults(func=handlers["bulk_update"])

    ptbd = tasks_sub.add_parser("bulk-delete", help="Bulk delete tasks from a JSON payload")
    ptbd.add_argument("--data-json", help="BulkTaskDeleteRequest payload JSON")
    ptbd.add_argument("--data-file", help="Path to BulkTaskDeleteRequest payload JSON file")
    add_actor_override_argument(ptbd)
    add_api_common_arguments(ptbd)
    ptbd.set_defaults(func=handlers["bulk_delete"])

    ptdr = tasks_sub.add_parser("draft", help="Generate an AI draft for one task")
    ptdr.add_argument("--task-id", required=True)
    ptdr.add_argument("--force", action="store_true", help="Force re-draft even if content already exists")
    ptdr.add_argument("--data-json", help="Optional TaskDraftRequest payload JSON")
    ptdr.add_argument("--data-file", help="Optional TaskDraftRequest payload JSON file")
    add_actor_override_argument(ptdr)
    add_api_common_arguments(ptdr)
    ptdr.set_defaults(func=handlers["draft"])

    ptse = tasks_sub.add_parser(
        "schedule-email",
        aliases=["email-schedule"],
        help="Schedule or send an email task from a JSON payload",
    )
    ptse.add_argument("--task-id", required=True)
    ptse.add_argument("--data-json", help="TaskEmailScheduleRequest payload JSON")
    ptse.add_argument("--data-file", help="Path to TaskEmailScheduleRequest payload JSON file")
    add_actor_override_argument(ptse)
    add_api_common_arguments(ptse)
    ptse.set_defaults(func=handlers["schedule_email"])


def add_webhooks_subcommands(
    wh_sub: argparse._SubParsersAction,
    *,
    add_api_common_arguments: Callable[[argparse.ArgumentParser], None],
    webhook_recipe_types: List[str],
    handlers: Dict[str, Callable],
) -> None:
    pwhrecipe = wh_sub.add_parser("recipe", help="Print webhook payload recipes")
    pwhrecipe.add_argument("--type", choices=["all", *webhook_recipe_types], default="all")
    pwhrecipe.add_argument("--out-file", help="Optional path to save the selected payload JSON")
    add_api_common_arguments(pwhrecipe)
    pwhrecipe.set_defaults(func=handlers["recipe"])

    pwhg = wh_sub.add_parser("get", help="Get webhook config for a table")
    pwhg.add_argument("--table-id", required=True)
    add_api_common_arguments(pwhg)
    pwhg.set_defaults(func=handlers["get"])

    pwhr = wh_sub.add_parser("rotate", help="Create/rotate webhook token for a table")
    pwhr.add_argument("--table-id", required=True)
    add_api_common_arguments(pwhr)
    pwhr.set_defaults(func=handlers["rotate"])

    pwhi = wh_sub.add_parser("ingest", help="Ingest records using table webhook token")
    pwhi.add_argument("--table-id", required=True)
    pwhi.add_argument("--webhook-token", help="x-autotouch-token (or AUTOTOUCH_WEBHOOK_TOKEN)")
    pwhi.add_argument("--records-json", help="Object, list, or {records:[...]} payload JSON")
    pwhi.add_argument("--records-file", help="Path to JSON file containing records payload")
    add_api_common_arguments(pwhi)
    pwhi.set_defaults(func=handlers["ingest"])

    _MATCH_STRATEGIES = ["email", "domain", "linkedin_url", "external_id", "exact_text"]
    _DUPLICATE_MODES = ["allow", "skip", "upsert"]
    _MERGE_MODES = ["fill_empty", "overwrite_mapped"]

    pwhci = wh_sub.add_parser("configure-ingest", help="Persist ingest identity settings on a table's webhook config")
    pwhci.add_argument("--table-id", required=True)
    pwhci.add_argument("--match-rule-id", default=None, help="Use a pre-configured table identity rule by ID")
    pwhci.add_argument("--match-column", default=None, help="Column key to match on (when no rule-id)")
    pwhci.add_argument(
        "--match-strategy",
        choices=_MATCH_STRATEGIES,
        default=None,
        help="Normalisation strategy for the match column",
    )
    pwhci.add_argument(
        "--duplicate-mode",
        choices=_DUPLICATE_MODES,
        default="upsert",
        help="Duplicate handling: allow / skip / upsert (default: upsert)",
    )
    pwhci.add_argument(
        "--merge-mode",
        choices=_MERGE_MODES,
        default="fill_empty",
        help="Cell merge strategy when upserting (default: fill_empty)",
    )
    add_api_common_arguments(pwhci)
    pwhci.set_defaults(func=handlers["configure_ingest"])

    pwhs = wh_sub.add_parser("subscriptions", help="Manage outbound webhook subscriptions")
    whs_sub = pwhs.add_subparsers(dest="webhooks_subscriptions_cmd", required=True)

    pwhsl = whs_sub.add_parser("list", help="List webhook subscriptions")
    pwhsl.add_argument("--include-disabled", action="store_true", help="Include paused/disabled subscriptions")
    pwhsl.add_argument("--limit", type=int, default=100, help="Max subscriptions to return (1-500)")
    add_api_common_arguments(pwhsl)
    pwhsl.set_defaults(func=handlers["subscriptions_list"])

    pwhsc = whs_sub.add_parser("create", help="Create a webhook subscription")
    pwhsc.add_argument("--url", help="Webhook endpoint URL")
    pwhsc.add_argument("--events", nargs="*", help="Event names or families (for example bulk_job.*)")
    pwhsc.add_argument("--paused", action="store_true", help="Create subscription as paused/disabled")
    pwhsc.add_argument("--filters-json", help="Optional filters JSON")
    pwhsc.add_argument("--filters-file", help="Optional filters JSON file")
    pwhsc.add_argument("--metadata-json", help="Optional metadata JSON")
    pwhsc.add_argument("--metadata-file", help="Optional metadata JSON file")
    pwhsc.add_argument("--retry-policy-json", help="Optional retryPolicy JSON")
    pwhsc.add_argument("--retry-policy-file", help="Optional retryPolicy JSON file")
    pwhsc.add_argument("--data-json", help="Full request payload JSON")
    pwhsc.add_argument("--data-file", help="Full request payload JSON file")
    add_api_common_arguments(pwhsc)
    pwhsc.set_defaults(func=handlers["subscriptions_create"])

    pwhsg = whs_sub.add_parser("get", help="Get a webhook subscription")
    pwhsg.add_argument("--subscription-id", required=True)
    add_api_common_arguments(pwhsg)
    pwhsg.set_defaults(func=handlers["subscriptions_get"])

    pwhsu = whs_sub.add_parser("update", help="Update a webhook subscription")
    pwhsu.add_argument("--subscription-id", required=True)
    pwhsu.add_argument("--data-json", help="Patch payload JSON")
    pwhsu.add_argument("--data-file", help="Patch payload JSON file")
    add_api_common_arguments(pwhsu)
    pwhsu.set_defaults(func=handlers["subscriptions_update"])

    pwhsd = whs_sub.add_parser("delete", help="Delete a webhook subscription")
    pwhsd.add_argument("--subscription-id", required=True)
    add_api_common_arguments(pwhsd)
    pwhsd.set_defaults(func=handlers["subscriptions_delete"])

    pwhsp = whs_sub.add_parser("pause", help="Pause a webhook subscription")
    pwhsp.add_argument("--subscription-id", required=True)
    add_api_common_arguments(pwhsp)
    pwhsp.set_defaults(func=handlers["subscriptions_pause"])

    pwhsr = whs_sub.add_parser("resume", help="Resume a paused webhook subscription")
    pwhsr.add_argument("--subscription-id", required=True)
    add_api_common_arguments(pwhsr)
    pwhsr.set_defaults(func=handlers["subscriptions_resume"])

    pwhsrs = whs_sub.add_parser("rotate-secret", help="Rotate webhook subscription signing secret")
    pwhsrs.add_argument("--subscription-id", required=True)
    add_api_common_arguments(pwhsrs)
    pwhsrs.set_defaults(func=handlers["subscriptions_rotate_secret"])

    pwhst = whs_sub.add_parser("test", help="Fire a test event for a subscription")
    pwhst.add_argument("--subscription-id", required=True)
    pwhst.add_argument("--event-type", help="Optional event type (for example lead.created)")
    pwhst.add_argument("--data-json", help="Optional test payload JSON")
    pwhst.add_argument("--data-file", help="Optional test payload JSON file")
    add_api_common_arguments(pwhst)
    pwhst.set_defaults(func=handlers["subscriptions_test"])

    pwhd = wh_sub.add_parser("deliveries", help="Inspect webhook delivery outcomes")
    whd_sub = pwhd.add_subparsers(dest="webhooks_deliveries_cmd", required=True)

    pwhdl = whd_sub.add_parser("list", help="List webhook deliveries")
    pwhdl.add_argument("--subscription-id", help="Filter by subscription id")
    pwhdl.add_argument("--status", help="Filter by status (queued/retry_scheduled/succeeded/failed)")
    pwhdl.add_argument("--event-type", help="Filter by event type")
    pwhdl.add_argument("--limit", type=int, default=100, help="Max deliveries to return (1-500)")
    add_api_common_arguments(pwhdl)
    pwhdl.set_defaults(func=handlers["deliveries_list"])

    pwhda = whd_sub.add_parser("attempts", help="List delivery attempts for one delivery id")
    pwhda.add_argument("--delivery-id", required=True)
    pwhda.add_argument("--limit", type=int, default=100, help="Max attempts to return (1-500)")
    add_api_common_arguments(pwhda)
    pwhda.set_defaults(func=handlers["deliveries_attempts"])
