"use client";

import { useState } from "react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { Send } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input, Textarea } from "@/components/ui/input";
import { FormField } from "@/components/ui/form-field";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { CaptainPicker } from "@/features/push/captain-picker";
import { sendTestPush } from "@/services/push";
import { queryKeys } from "@/lib/query-keys";
import { friendlyErrorMessage } from "@/lib/errors";
import { useFieldErrors } from "@/lib/use-field-errors";
import { useT } from "@/i18n";

/**
 * Prove a captain's handset end-to-end: pick one captain and push a message they
 * can read. Title and body are optional — the service falls back to its own
 * translated defaults. The form state lives inside the dialog content, so it is
 * fresh every time the dialog opens.
 */
function TestPushForm({ onDone }: { onDone: () => void }) {
  const t = useT();
  const queryClient = useQueryClient();
  const [driverUuid, setDriverUuid] = useState("");
  const [title, setTitle] = useState("");
  const [body, setBody] = useState("");

  // What the server refused, per field, so a rejected captain or an over-long title is shown where
  // it was typed instead of only in a toast that names nothing.
  const fields = useFieldErrors({ only: ["driver_uuid", "title", "body"] });

  const mutation = useMutation({
    mutationFn: sendTestPush,
    onSuccess: (response) => {
      toast.success(response.Message || t("push.testSent"));
      onDone();
      void queryClient.invalidateQueries({ queryKey: queryKeys.push.stats });
      void queryClient.invalidateQueries({ queryKey: ["push", "deliveries"] });
    },
    onMutate: fields.reset,
    onError: (error) => {
      // A refusal this dialog cannot place — no device registered, a permission — still has to be
      // said out loud.
      if (!fields.capture(error)) toast.error(friendlyErrorMessage(error, t));
    },
  });

  function submit() {
    if (!driverUuid) return;
    mutation.mutate({
      driver_uuid: driverUuid,
      title: title.trim() || undefined,
      body: body.trim() || undefined,
    });
  }

  return (
    <>
      <div className="grid gap-4">
        <FormField
          label={t("push.recipient")}
          htmlFor="test-captain"
          required
          error={fields.get("driver_uuid")}
        >
          <CaptainPicker
            value={driverUuid ? [driverUuid] : []}
            onChange={(uuids) => setDriverUuid(uuids[0] ?? "")}
          />
        </FormField>
        <FormField
          label={`${t("push.titleField")} (${t("common.optional")})`}
          htmlFor="test-title"
          error={fields.get("title")}
        >
          <Input
            id="test-title"
            value={title}
            onChange={(event) => setTitle(event.target.value)}
            maxLength={100}
            placeholder={t("push.testTitlePlaceholder")}
          />
        </FormField>
        <FormField
          label={`${t("push.bodyField")} (${t("common.optional")})`}
          htmlFor="test-body"
          error={fields.get("body")}
        >
          <Textarea
            id="test-body"
            rows={2}
            value={body}
            onChange={(event) => setBody(event.target.value)}
            maxLength={255}
            placeholder={t("push.testBodyPlaceholder")}
          />
        </FormField>
      </div>

      <DialogFooter>
        <Button variant="outline" onClick={onDone} disabled={mutation.isPending}>
          {t("common.cancel")}
        </Button>
        <Button onClick={submit} loading={mutation.isPending} disabled={!driverUuid}>
          <Send className="h-4 w-4" aria-hidden />
          {t("push.sendTest")}
        </Button>
      </DialogFooter>
    </>
  );
}

export function TestPushDialog({
  open,
  onOpenChange,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
}) {
  const t = useT();
  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-lg">
        <DialogHeader>
          <DialogTitle>{t("push.testTitle")}</DialogTitle>
          <DialogDescription>{t("push.testSubtitle")}</DialogDescription>
        </DialogHeader>
        <TestPushForm onDone={() => onOpenChange(false)} />
      </DialogContent>
    </Dialog>
  );
}