"use client";

import * as React from "react";
import { Search } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  loadUserRatesAction,
  saveUserCustomRatesAction,
} from "@/lib/actions/admin-users";
import { adminUsersTexts } from "@/lib/i18n/admin-users";
import { cn } from "@/lib/utils";
import { DialogLoading, FormError, UserActionForm, UserDialog } from "./dialog-shell";
import type { UserRatesData } from "./types";

const t = adminUsersTexts.rates;
const MAX_VISIBLE = 200;

export function CustomRatesDialog({
  userId,
  username,
  open,
  onOpenChange,
}: {
  userId: string;
  username: string;
  open: boolean;
  onOpenChange: (open: boolean) => void;
}) {
  const [data, setData] = React.useState<UserRatesData | null>(null);
  const [loadError, setLoadError] = React.useState<string | null>(null);
  const [values, setValues] = React.useState<Record<string, string>>({});
  const [term, setTerm] = React.useState("");
  const [onlyOverrides, setOnlyOverrides] = React.useState(false);

  React.useEffect(() => {
    if (!open) return;
    let cancelled = false;
    setData(null);
    setLoadError(null);
    setValues({});
    setTerm("");
    setOnlyOverrides(false);
    loadUserRatesAction(userId)
      .then((result) => {
        if (cancelled) return;
        if (result.ok && result.data) {
          setData(result.data);
          setValues(
            Object.fromEntries(
              result.data.rows.map((r) => [String(r.serviceId), r.custom]),
            ),
          );
        } else {
          setLoadError(result.ok ? adminUsersTexts.errors.loadFailed : result.error);
        }
      })
      .catch(() => {
        if (!cancelled) setLoadError(adminUsersTexts.errors.loadFailed);
      });
    return () => {
      cancelled = true;
    };
  }, [open, userId]);

  const initial = React.useMemo(
    () =>
      Object.fromEntries(
        (data?.rows ?? []).map((r) => [String(r.serviceId), r.custom]),
      ) as Record<string, string>,
    [data],
  );

  const changes = React.useMemo(() => {
    const out: Record<string, string> = {};
    for (const [key, value] of Object.entries(values)) {
      if ((initial[key] ?? "") !== value.trim()) out[key] = value.trim();
    }
    return out;
  }, [values, initial]);

  const overrideCount = React.useMemo(
    () => Object.values(values).filter((v) => v.trim() !== "").length,
    [values],
  );

  const filtered = React.useMemo(() => {
    const rows = data?.rows ?? [];
    const q = term.trim().toLowerCase();
    return rows.filter((row) => {
      if (onlyOverrides && (values[String(row.serviceId)] ?? "").trim() === "") {
        return false;
      }
      if (!q) return true;
      return (
        row.name.toLowerCase().includes(q) ||
        row.category.toLowerCase().includes(q) ||
        String(row.serviceId).includes(q)
      );
    });
  }, [data, term, onlyOverrides, values]);

  const visible = filtered.slice(0, MAX_VISIBLE);

  function clearAll() {
    setValues((prev) =>
      Object.fromEntries(Object.keys(prev).map((key) => [key, ""])),
    );
  }

  return (
    <UserDialog
      open={open}
      onOpenChange={onOpenChange}
      title={`${t.title} · ${username}`}
      description={t.description}
      size="xl"
    >
      {loadError ? <FormError message={loadError} /> : null}
      {!data && !loadError ? <DialogLoading /> : null}

      {data ? (
        <UserActionForm
          action={saveUserCustomRatesAction}
          submitLabel={t.submit}
          successMessage={adminUsersTexts.toast.ratesSaved}
          onDone={() => onOpenChange(false)}
          onCancel={() => onOpenChange(false)}
          footerExtra={
            <span className="font-mono text-[11px] text-muted-foreground tabular-nums">
              {t.count.replace("{n}", String(overrideCount))}
            </span>
          }
        >
          <input type="hidden" name="id" value={data.userId} />
          <input type="hidden" name="payload" value={JSON.stringify(changes)} />

          <div className="flex flex-wrap items-center gap-2">
            <div className="relative min-w-0 flex-1">
              <Search className="pointer-events-none absolute top-1/2 left-2 size-3.5 -translate-y-1/2 text-muted-foreground" />
              <Input
                value={term}
                onChange={(e) => setTerm(e.target.value)}
                placeholder={t.search}
                className="h-7 pl-7 text-sm"
              />
            </div>
            <Button
              type="button"
              size="sm"
              variant={onlyOverrides ? "secondary" : "outline"}
              onClick={() => setOnlyOverrides((v) => !v)}
            >
              {t.onlyOverrides}
            </Button>
            <Button type="button" size="sm" variant="outline" onClick={clearAll}>
              {t.clearAll}
            </Button>
          </div>

          <div className="max-h-[52vh] overflow-auto rounded-lg border">
            <table className="w-full border-separate border-spacing-0 text-sm">
              <thead>
                <tr>
                  <th className="sticky top-0 z-10 border-b bg-card px-2.5 py-1.5 text-left text-[11px] font-semibold tracking-wider text-muted-foreground uppercase">
                    {t.service}
                  </th>
                  <th className="sticky top-0 z-10 border-b bg-card px-2.5 py-1.5 text-right text-[11px] font-semibold tracking-wider text-muted-foreground uppercase">
                    {t.base}
                  </th>
                  <th className="sticky top-0 z-10 hidden border-b bg-card px-2.5 py-1.5 text-right text-[11px] font-semibold tracking-wider text-muted-foreground uppercase sm:table-cell">
                    {t.effective}
                  </th>
                  <th className="sticky top-0 z-10 border-b bg-card px-2.5 py-1.5 text-right text-[11px] font-semibold tracking-wider text-muted-foreground uppercase">
                    {t.custom}
                  </th>
                </tr>
              </thead>
              <tbody>
                {visible.length === 0 ? (
                  <tr>
                    <td
                      colSpan={4}
                      className="px-2.5 py-8 text-center text-xs text-muted-foreground"
                    >
                      {t.empty}
                    </td>
                  </tr>
                ) : (
                  visible.map((row) => {
                    const key = String(row.serviceId);
                    const value = values[key] ?? "";
                    const dirty = (initial[key] ?? "") !== value.trim();
                    return (
                      <tr
                        key={key}
                        className={cn(
                          "[&:last-child>td]:border-0",
                          dirty && "bg-blue-600/5 dark:bg-blue-500/10",
                        )}
                      >
                        <td className="border-b px-2.5 py-1.5">
                          <div className="leading-tight">
                            <span className="flex items-center gap-1.5">
                              <span className="shrink-0 rounded bg-muted px-1.5 py-px font-mono text-[11px] text-muted-foreground tabular-nums">
                                {row.serviceId}
                              </span>
                              <span
                                className={cn(
                                  "truncate text-sm",
                                  !row.active && "text-muted-foreground line-through",
                                )}
                              >
                                {row.name}
                              </span>
                            </span>
                            <span className="block truncate text-[11px] text-muted-foreground">
                              {row.category}
                            </span>
                          </div>
                        </td>
                        <td className="border-b px-2.5 py-1.5 text-right font-mono text-xs text-muted-foreground tabular-nums">
                          {row.base}
                        </td>
                        <td className="hidden border-b px-2.5 py-1.5 text-right font-mono text-xs tabular-nums sm:table-cell">
                          {row.effective}
                        </td>
                        <td className="border-b px-2.5 py-1.5 text-right">
                          <Input
                            value={value}
                            onChange={(e) =>
                              setValues((prev) => ({
                                ...prev,
                                [key]: e.target.value,
                              }))
                            }
                            inputMode="decimal"
                            placeholder={row.effective}
                            aria-label={`${t.custom} ${row.serviceId}`}
                            className="ml-auto h-7 w-28 text-right font-mono text-sm tabular-nums"
                          />
                        </td>
                      </tr>
                    );
                  })
                )}
              </tbody>
            </table>
            {filtered.length > visible.length ? (
              <p className="border-t px-2.5 py-1.5 text-[11px] text-muted-foreground">
                +{filtered.length - visible.length} more — narrow the filter to see them.
              </p>
            ) : null}
          </div>
        </UserActionForm>
      ) : null}
    </UserDialog>
  );
}

export default CustomRatesDialog;
