"use client";

import { useState } from "react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { Megaphone } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input, Textarea } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
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 { createPushBroadcast } 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";
import type { PushBroadcastAudienceValue } from "@/types/push";

const MAX_NAMED_CAPTANS = 500;

const AUDIENCES: PushBroadcastAudienceValue[] = ["all", "online", "captains"];

/**
 * Compose a broadcast: what it says and who it reaches. All / Online target
 * every eligible captain; Selected targets exactly the captains picked here,
 * delivered in the background by the backend queue. The form state lives inside
 * the dialog content, so it is fresh every time the dialog opens.
 */
function BroadcastForm({ onDone }: { onDone: () => void }) {
  const t = useT();
  const queryClient = useQueryClient();
  const [title, setTitle] = useState("");
  const [body, setBody] = useState("");
  const [audience, setAudience] = useState<PushBroadcastAudienceValue>("all");
  const [captains, setCaptains] = useState<string[]>([]);

  // The captain list is refused by position (`driver_uuids.0`), and it is one control here, so
  // those collapse onto it.
  const fields = useFieldErrors({
    only: ["title", "body", "audience", "driver_uuids"],
    collapse: ["driver_uuids"],
  });

  const mutation = useMutation({
    mutationFn: createPushBroadcast,
    onSuccess: (response) => {
      toast.success(response.Message || t("push.broadcastQueued"));
      onDone();
      void queryClient.invalidateQueries({ queryKey: ["push", "broadcasts"] });
      void queryClient.invalidateQueries({ queryKey: queryKeys.push.stats });
    },
    onMutate: fields.reset,
    onError: (error) => {
      if (!fields.capture(error)) toast.error(friendlyErrorMessage(error, t));
    },
  });

  function submit() {
    mutation.mutate({
      title: title.trim(),
      body: body.trim(),
      audience,
      driver_uuids: audience === "captains" ? captains : undefined,
    });
  }

  const canSubmit =
    title.trim().length > 0 && body.trim().length > 0 && (audience !== "captains" || captains.length > 0);

  return (
    <>
      <div className="grid gap-4">
        <FormField
          label={t("push.titleField")}
          htmlFor="broadcast-title"
          required
          error={fields.get("title")}
        >
          <Input
            id="broadcast-title"
            value={title}
            onChange={(event) => setTitle(event.target.value)}
            maxLength={100}
            placeholder={t("push.titlePlaceholder")}
          />
        </FormField>
        <FormField
          label={t("push.bodyField")}
          htmlFor="broadcast-body"
          required
          error={fields.get("body")}
        >
          <Textarea
            id="broadcast-body"
            rows={3}
            value={body}
            onChange={(event) => setBody(event.target.value)}
            maxLength={500}
            placeholder={t("push.bodyPlaceholder")}
          />
        </FormField>
        <FormField
          label={t("push.audience")}
          htmlFor="broadcast-audience"
          required
          error={fields.get("audience")}
        >
          <Select value={audience} onValueChange={(value) => setAudience(value as PushBroadcastAudienceValue)}>
            <SelectTrigger id="broadcast-audience">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              {AUDIENCES.map((value) => (
                <SelectItem key={value} value={value}>
                  {t(`push.audience.${value}`)}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <p className="mt-1.5 text-xs text-muted-foreground">{t("push.broadcastAudienceHint")}</p>
        </FormField>

        {audience === "captains" ? (
          <FormField
            label={t("push.recipient")}
            htmlFor="broadcast-captains"
            required
            error={fields.get("driver_uuids")}
          >
            <CaptainPicker
              value={captains}
              onChange={setCaptains}
              multiple
              max={MAX_NAMED_CAPTANS}
            />
            <p className="mt-1.5 text-xs text-muted-foreground">
              {t("push.captainsSelected", { count: captains.length })}
            </p>
          </FormField>
        ) : null}
      </div>

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

export function NewBroadcastDialog({
  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.broadcastTitle")}</DialogTitle>
          <DialogDescription>{t("push.broadcastSubtitle")}</DialogDescription>
        </DialogHeader>
        <BroadcastForm onDone={() => onOpenChange(false)} />
      </DialogContent>
    </Dialog>
  );
}