"use client";

import * as React from "react";
import { useFormStatus } from "react-dom";
import { AlertCircle, Loader2 } from "lucide-react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { adminTexts } from "@/lib/i18n/admin";
import { cn } from "@/lib/utils";

/**
 * Dialog + form plumbing shared by every /admin/users modal.
 * Server actions return the shared ActionResult shape; a failure keeps the
 * dialog open and shows the message, a success closes it and toasts.
 */

export type ActionResultLike = {
  ok: boolean;
  error?: string;
  fieldErrors?: Record<string, string>;
};

export function UserDialog({
  open,
  onOpenChange,
  title,
  description,
  children,
  size = "md",
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  title: string;
  description?: string;
  children: React.ReactNode;
  size?: "md" | "lg" | "xl";
}) {
  const width =
    size === "xl" ? "sm:max-w-4xl" : size === "lg" ? "sm:max-w-2xl" : "sm:max-w-md";
  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className={cn(width, "max-h-[90vh] overflow-y-auto")}>
        <DialogHeader>
          <DialogTitle className="text-base">{title}</DialogTitle>
          {description ? (
            <DialogDescription className="text-sm">{description}</DialogDescription>
          ) : null}
        </DialogHeader>
        {children}
      </DialogContent>
    </Dialog>
  );
}

function SubmitRow({
  label,
  destructive,
  onCancel,
  extra,
}: {
  label: string;
  destructive?: boolean;
  onCancel: () => void;
  extra?: React.ReactNode;
}) {
  const { pending } = useFormStatus();
  return (
    <DialogFooter className="gap-2 sm:justify-between">
      <div className="flex items-center gap-2">{extra}</div>
      <div className="flex items-center gap-2">
        <Button type="button" variant="outline" size="lg" onClick={onCancel}>
          {adminTexts.common.cancel}
        </Button>
        <Button
          type="submit"
          size="lg"
          variant={destructive ? "destructive" : "default"}
          disabled={pending}
        >
          {pending ? <Loader2 className="size-3.5 animate-spin" /> : null}
          {label}
        </Button>
      </div>
    </DialogFooter>
  );
}

export function FormError({ message }: { message?: string | null }) {
  if (!message) return null;
  return (
    <p className="flex items-start gap-1.5 rounded-lg bg-rose-500/10 px-2.5 py-2 text-xs text-rose-700 dark:text-rose-400">
      <AlertCircle className="mt-px size-3.5 shrink-0" />
      <span>{message}</span>
    </p>
  );
}

/**
 * A form bound to a server action. `children` may be a node or a render
 * function receiving the current field errors so inputs can highlight.
 */
export function UserActionForm({
  action,
  submitLabel,
  destructive,
  successMessage,
  onDone,
  onCancel,
  footerExtra,
  className,
  children,
}: {
  action: (formData: FormData) => Promise<ActionResultLike | void>;
  submitLabel: string;
  destructive?: boolean;
  successMessage?: string;
  onDone: () => void;
  onCancel: () => void;
  footerExtra?: React.ReactNode;
  className?: string;
  children:
    | React.ReactNode
    | ((fieldErrors: Record<string, string>) => React.ReactNode);
}) {
  const [error, setError] = React.useState<string | null>(null);
  const [fieldErrors, setFieldErrors] = React.useState<Record<string, string>>({});

  async function run(formData: FormData) {
    setError(null);
    setFieldErrors({});
    try {
      const result = await action(formData);
      if (result && result.ok === false) {
        setError(result.error ?? "Action failed");
        setFieldErrors(result.fieldErrors ?? {});
        return;
      }
      if (successMessage) toast.success(successMessage);
      onDone();
    } catch (e) {
      if (e && typeof e === "object" && "digest" in e) throw e;
      setError(e instanceof Error ? e.message : "Action failed");
    }
  }

  return (
    <form action={run} className={cn("space-y-3", className)}>
      <FormError message={error} />
      {typeof children === "function" ? children(fieldErrors) : children}
      <SubmitRow
        label={submitLabel}
        destructive={destructive}
        onCancel={onCancel}
        extra={footerExtra}
      />
    </form>
  );
}

/* ------------------------------------------------------------------ fields */

export function Field({
  label,
  htmlFor,
  hint,
  error,
  className,
  children,
}: {
  label: string;
  htmlFor?: string;
  hint?: string;
  error?: string;
  className?: string;
  children: React.ReactNode;
}) {
  return (
    <div className={cn("space-y-1.5", className)}>
      <Label htmlFor={htmlFor} className="text-xs font-medium">
        {label}
      </Label>
      {children}
      {error ? (
        <p className="text-[11px] text-rose-600 dark:text-rose-400">{error}</p>
      ) : hint ? (
        <p className="text-[11px] text-muted-foreground">{hint}</p>
      ) : null}
    </div>
  );
}

export function TextField({
  name,
  label,
  defaultValue,
  placeholder,
  hint,
  error,
  type = "text",
  required,
  step,
  className,
}: {
  name: string;
  label: string;
  defaultValue?: string;
  placeholder?: string;
  hint?: string;
  error?: string;
  type?: string;
  required?: boolean;
  step?: string;
  className?: string;
}) {
  const id = `user-field-${name}`;
  return (
    <Field label={label} htmlFor={id} hint={hint} error={error} className={className}>
      <Input
        id={id}
        name={name}
        type={type}
        step={step}
        required={required}
        placeholder={placeholder}
        defaultValue={defaultValue}
        aria-invalid={error ? true : undefined}
        className="h-8 text-sm"
      />
    </Field>
  );
}

export function TextAreaField({
  name,
  label,
  defaultValue,
  placeholder,
  hint,
  error,
  rows = 3,
  className,
}: {
  name: string;
  label: string;
  defaultValue?: string;
  placeholder?: string;
  hint?: string;
  error?: string;
  rows?: number;
  className?: string;
}) {
  const id = `user-field-${name}`;
  return (
    <Field label={label} htmlFor={id} hint={hint} error={error} className={className}>
      <Textarea
        id={id}
        name={name}
        rows={rows}
        placeholder={placeholder}
        defaultValue={defaultValue}
        className="text-sm"
      />
    </Field>
  );
}

export function SelectField({
  name,
  label,
  defaultValue,
  options,
  hint,
  error,
  disabled,
  className,
}: {
  name: string;
  label: string;
  defaultValue?: string;
  options: { value: string; label: string }[];
  hint?: string;
  error?: string;
  disabled?: boolean;
  className?: string;
}) {
  const id = `user-field-${name}`;
  return (
    <Field label={label} htmlFor={id} hint={hint} error={error} className={className}>
      <NativeSelect
        id={id}
        name={name}
        defaultValue={defaultValue}
        disabled={disabled}
        className="w-full"
      >
        {options.map((o) => (
          <NativeSelectOption key={o.value} value={o.value}>
            {o.label}
          </NativeSelectOption>
        ))}
      </NativeSelect>
    </Field>
  );
}

export function DialogLoading({ label = "Loading…" }: { label?: string }) {
  return (
    <div className="flex items-center justify-center gap-2 py-10 text-sm text-muted-foreground">
      <Loader2 className="size-4 animate-spin" />
      {label}
    </div>
  );
}
