"use client";

import * as React from "react";
import { useRouter } from "next/navigation";
import { useActionState } from "react";
import { AlertCircle, MessageSquarePlus, Send } from "lucide-react";
import { toast } from "sonner";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { Spinner } from "@/components/ui/spinner";
import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { createTicketAction } from "@/lib/actions/tickets";
import { ticketsTexts as tx } from "@/lib/i18n/tickets";
import {
  TICKET_CATEGORIES,
  TICKET_SUBCATEGORIES,
  buildSubject,
  hasSubcategories,
  requiresOrderId,
  usesOrderId,
  type TicketActionState,
} from "@/lib/validation/tickets";
import { AttachmentPicker } from "./attachment-picker";
import type { TicketAttachmentDTO } from "./types";

const SELECT_CLASS = "w-full [&_select]:h-10";

function FieldError({ message }: { message?: string }) {
  if (!message) return null;
  return (
    <p className="flex items-center gap-1.5 text-xs text-destructive">
      <AlertCircle className="size-3.5 shrink-0" />
      {message}
    </p>
  );
}

export function NewTicketCard({ recentOrderIds }: { recentOrderIds: number[] }) {
  const router = useRouter();
  const [state, formAction, pending] = useActionState<TicketActionState, FormData>(
    createTicketAction,
    null,
  );

  const [category, setCategory] = React.useState("");
  const [subcategory, setSubcategory] = React.useState("");
  const [orderId, setOrderId] = React.useState("");
  const [message, setMessage] = React.useState("");
  const [attachments, setAttachments] = React.useState<TicketAttachmentDTO[]>([]);
  const handled = React.useRef<TicketActionState>(null);

  React.useEffect(() => {
    if (!state || state === handled.current) return;
    handled.current = state;
    if (state.ok) {
      toast.success(tx.ticketCreated);
      const id = state.data?.ticketId;
      if (id) router.push(`/tickets/${id}`);
      else router.refresh();
    } else {
      toast.error(state.error);
    }
  }, [state, router]);

  const failure = state && state.ok === false ? state : null;
  const fieldErrors = failure?.fieldErrors ?? {};

  const showSubcategory = hasSubcategories(category);
  const showOrderId = usesOrderId(category);
  const orderRequired = requiresOrderId(category, subcategory);
  const subject = buildSubject(
    category,
    showSubcategory ? subcategory : null,
    showOrderId ? orderId : null,
  );

  function onCategoryChange(next: string) {
    setCategory(next);
    if (!hasSubcategories(next)) {
      setSubcategory("");
      setOrderId("");
    }
  }

  return (
    <Card className="rounded-2xl border shadow-sm ring-0">
      <CardHeader className="gap-1.5">
        <CardTitle className="flex items-center gap-2 font-display text-base font-semibold">
          <span className="flex size-8 items-center justify-center rounded-xl bg-primary/10 text-primary">
            <MessageSquarePlus className="size-4" />
          </span>
          {tx.newTicketTitle}
        </CardTitle>
        <CardDescription className="text-sm">{tx.newTicketHint}</CardDescription>
      </CardHeader>

      <CardContent>
        <form action={formAction} className="space-y-5">
          <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
            <div className="space-y-1.5">
              <Label htmlFor="ticket-category">{tx.categoryLabel}</Label>
              <NativeSelect
                className={SELECT_CLASS}
                id="ticket-category"
                name="category"
                value={category}
                disabled={pending}
                aria-invalid={fieldErrors.category ? true : undefined}
                onChange={(event) => onCategoryChange(event.target.value)}
              >
                <NativeSelectOption value="">{tx.categoryPlaceholder}</NativeSelectOption>
                {TICKET_CATEGORIES.map((item) => (
                  <NativeSelectOption key={item} value={item}>
                    {item}
                  </NativeSelectOption>
                ))}
              </NativeSelect>
              <FieldError message={fieldErrors.category} />
            </div>

            {showSubcategory ? (
              <div className="space-y-1.5">
                <Label htmlFor="ticket-subcategory">{tx.subcategoryLabel}</Label>
                <NativeSelect
                  className={SELECT_CLASS}
                  id="ticket-subcategory"
                  name="subcategory"
                  value={subcategory}
                  disabled={pending}
                  aria-invalid={fieldErrors.subcategory ? true : undefined}
                  onChange={(event) => setSubcategory(event.target.value)}
                >
                  <NativeSelectOption value="">
                    {tx.subcategoryPlaceholder}
                  </NativeSelectOption>
                  {TICKET_SUBCATEGORIES.map((item) => (
                    <NativeSelectOption key={item} value={item}>
                      {item}
                    </NativeSelectOption>
                  ))}
                </NativeSelect>
                <FieldError message={fieldErrors.subcategory} />
              </div>
            ) : null}

            {showOrderId ? (
              <div className="space-y-1.5">
                <Label htmlFor="ticket-order-id">
                  {tx.orderIdLabel}
                  {orderRequired ? null : (
                    <span className="ml-1 text-xs font-normal text-muted-foreground">
                      (optional)
                    </span>
                  )}
                </Label>
                <Input
                  id="ticket-order-id"
                  name="orderId"
                  inputMode="numeric"
                  autoComplete="off"
                  list="ticket-recent-orders"
                  placeholder={tx.orderIdPlaceholder}
                  className="h-10 font-mono"
                  value={orderId}
                  disabled={pending}
                  aria-invalid={fieldErrors.orderId ? true : undefined}
                  onChange={(event) =>
                    setOrderId(event.target.value.replace(/[^\d]/g, "").slice(0, 12))
                  }
                />
                <datalist id="ticket-recent-orders">
                  {recentOrderIds.map((id) => (
                    <option key={id} value={String(id)} />
                  ))}
                </datalist>
                <FieldError message={fieldErrors.orderId} />
                {!fieldErrors.orderId ? (
                  <p className="text-xs text-muted-foreground">{tx.orderIdHint}</p>
                ) : null}
              </div>
            ) : null}
          </div>

          <div className="space-y-1.5">
            <Label>{tx.subjectLabel}</Label>
            <div
              className={cn(
                "flex h-10 items-center rounded-lg border border-dashed bg-muted/40 px-3 text-sm",
                subject ? "font-medium" : "text-muted-foreground",
              )}
            >
              <span className="truncate font-mono">{subject || tx.subjectEmpty}</span>
            </div>
            <p className="text-xs text-muted-foreground">{tx.subjectAutoHint}</p>
          </div>

          <div className="space-y-1.5">
            <Label htmlFor="ticket-message">{tx.messageLabel}</Label>
            <Textarea
              id="ticket-message"
              name="message"
              rows={5}
              placeholder={tx.messagePlaceholder}
              className="min-h-32 resize-y"
              value={message}
              disabled={pending}
              aria-invalid={fieldErrors.message ? true : undefined}
              onChange={(event) => setMessage(event.target.value)}
            />
            <FieldError message={fieldErrors.message} />
          </div>

          <div className="space-y-1.5">
            <Label>{tx.attachmentsLabel}</Label>
            <AttachmentPicker
              value={attachments}
              onChange={setAttachments}
              disabled={pending}
            />
            <FieldError message={fieldErrors.attachments} />
          </div>

          <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
            {failure ? (
              <p className="flex items-center gap-1.5 text-sm text-destructive">
                <AlertCircle className="size-4 shrink-0" />
                {failure.error}
              </p>
            ) : (
              <span />
            )}
            <Button
              type="submit"
              disabled={pending}
              aria-busy={pending}
              className="h-10 gap-2 rounded-lg px-5 font-semibold sm:w-auto"
            >
              {pending ? <Spinner className="size-4" /> : <Send className="size-4" />}
              {pending ? tx.submitTicketPending : tx.submitTicket}
            </Button>
          </div>
        </form>
      </CardContent>
    </Card>
  );
}

export default NewTicketCard;
