import { useState, type ChangeEvent, type FocusEvent } from "react";
import Box from "@mui/material/Box";
import { Modal, TextField, Button } from "../ui";
import { useApiMutation } from "../lib/queries/mutations";
import { useAlert } from "../context/AlertContext";
import { PlanCategory } from "../lib/queries/plan";

interface Props {
  isOpen: boolean;
  onClose: () => void;
  categories: PlanCategory[];
}

const DEFAULT_NEW_COLOR = "#2563eb";

export default function PlanCategoriesModal({
  isOpen,
  onClose,
  categories,
}: Props) {
  const alert = useAlert();
  const [newLabel, setNewLabel] = useState("");
  const [newColor, setNewColor] = useState(DEFAULT_NEW_COLOR);
  // Id of the row showing the inline "really delete?" confirm, or null.
  const [confirmDeleteId, setConfirmDeleteId] = useState<number | null>(null);

  const createCat = useApiMutation<
    { label: string; color: string },
    PlanCategory
  >({
    url: "/api/admin/plan/categories",
    method: "POST",
    invalidate: ["plan", "dashboard", "audit-log"],
  });
  const updateCat = useApiMutation<
    { id: number; label?: string; color?: string; is_active?: boolean },
    PlanCategory
  >({
    url: (v) => `/api/admin/plan/categories/${v.id}`,
    method: "PATCH",
    invalidate: ["plan", "dashboard", "audit-log"],
  });
  const deleteCat = useApiMutation<{ id: number }, { ok: true }>({
    url: (v) => `/api/admin/plan/categories/${v.id}`,
    method: "DELETE",
    invalidate: ["plan", "dashboard", "audit-log"],
  });

  const handleAdd = () => {
    const label = newLabel.trim();
    if (!label) {
      alert.error("Zadejte název kategorie");
      return;
    }
    createCat.mutate(
      { label, color: newColor },
      {
        onSuccess: () => {
          setNewLabel("");
          setNewColor(DEFAULT_NEW_COLOR);
        },
        onError: (e) => alert.error(e.message),
      },
    );
  };

  const patch = (
    id: number,
    body: { label?: string; color?: string; is_active?: boolean },
  ) => {
    updateCat.mutate(
      { id, ...body },
      { onError: (e) => alert.error(e.message) },
    );
  };

  const handleDelete = (id: number) => {
    deleteCat.mutate(
      { id },
      {
        onSuccess: () => setConfirmDeleteId(null),
        // Server blocks deleting a category that is still in use (409) — show
        // the Czech message ("…můžete ji skrýt") and keep the row.
        onError: (e) => {
          alert.error(e.message);
          setConfirmDeleteId(null);
        },
      },
    );
  };

  const busy =
    createCat.isPending || updateCat.isPending || deleteCat.isPending;

  // Shared layout for a category row: color swatch | text input | actions.
  const rowSx = {
    display: "flex",
    alignItems: "center",
    gap: 1,
    py: 1,
  } as const;

  // Native color picker, styled to match the row (was the .plan-cat-color rule).
  const colorInputSx = {
    width: 34,
    height: 34,
    p: 0,
    border: 1,
    borderColor: "divider",
    borderRadius: "6px",
    background: "none",
    cursor: "pointer",
    flex: "0 0 auto",
  } as const;

  return (
    <Modal
      isOpen={isOpen}
      onClose={onClose}
      onSubmit={onClose}
      title="Správa kategorií"
      submitText="Zavřít"
      hideCancel
      maxWidth="md"
    >
      <Box>
        {categories.map((c) => (
          <Box key={c.id} sx={{ ...rowSx, opacity: c.is_active ? 1 : 0.55 }}>
            <Box
              component="input"
              type="color"
              sx={colorInputSx}
              // Uncontrolled + patch on blur (like the rename input): the
              // native color picker fires onChange on every drag tick, which
              // would spam PATCH requests and the audit log. onBlur commits
              // once when the picker closes.
              defaultValue={c.color}
              key={c.color}
              disabled={busy}
              onBlur={(e: FocusEvent<HTMLInputElement>) => {
                if (e.target.value !== c.color) {
                  patch(c.id, { color: e.target.value });
                }
              }}
              aria-label={`Barva – ${c.label}`}
            />
            <TextField
              // Uncontrolled defaultValue won't update if the label changes
              // externally (e.g. another tab renames it). Keying on c.label
              // remounts the input so it re-seeds, mirroring the color input.
              key={c.label}
              defaultValue={c.label}
              disabled={busy}
              onBlur={(e) => {
                const v = e.target.value.trim();
                if (v && v !== c.label) patch(c.id, { label: v });
              }}
              inputProps={{ "aria-label": `Název – ${c.label}` }}
            />
            {confirmDeleteId === c.id ? (
              <>
                <Button
                  variant="contained"
                  color="error"
                  size="small"
                  disabled={busy}
                  onClick={() => handleDelete(c.id)}
                >
                  Opravdu smazat
                </Button>
                <Button
                  variant="outlined"
                  color="inherit"
                  size="small"
                  disabled={busy}
                  onClick={() => setConfirmDeleteId(null)}
                >
                  Zrušit
                </Button>
              </>
            ) : (
              <>
                <Button
                  variant="outlined"
                  color="inherit"
                  size="small"
                  disabled={busy}
                  onClick={() => patch(c.id, { is_active: !c.is_active })}
                >
                  {c.is_active ? "Skrýt" : "Obnovit"}
                </Button>
                <Button
                  variant="contained"
                  color="error"
                  size="small"
                  disabled={busy}
                  onClick={() => setConfirmDeleteId(c.id)}
                  aria-label={`Smazat – ${c.label}`}
                  title="Smazat kategorii"
                >
                  Smazat
                </Button>
              </>
            )}
          </Box>
        ))}

        <Box
          sx={{ ...rowSx, mt: 1, pt: 2, borderTop: 1, borderColor: "divider" }}
        >
          <Box
            component="input"
            type="color"
            sx={colorInputSx}
            value={newColor}
            disabled={busy}
            onChange={(e: ChangeEvent<HTMLInputElement>) =>
              setNewColor(e.target.value)
            }
            aria-label="Barva nové kategorie"
          />
          <TextField
            placeholder="Nová kategorie…"
            value={newLabel}
            disabled={busy}
            onChange={(e) => setNewLabel(e.target.value)}
            onKeyDown={(e) => e.key === "Enter" && handleAdd()}
          />
          <Button
            variant="contained"
            color="primary"
            size="small"
            disabled={busy}
            onClick={handleAdd}
          >
            Přidat
          </Button>
        </Box>
      </Box>
    </Modal>
  );
}
