import { useEffect, useMemo, useState } from "react";
import { Loader2 } from "lucide-react";
import {
  Button,
  Group,
  Modal,
  NumberInput,
  Select,
  SimpleGrid,
  Stack,
  Text,
  Textarea,
  TextInput,
} from "@mantine/core";

import { FLEET_SELECT_NONE, type FleetFormFieldDef } from "@/pages/fleet/config/resources";
import type { FleetRecord } from "@/services/fleet/fleet.service";

export interface FleetFormDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  title: string;
  fields: FleetFormFieldDef[];
  initialRecord?: FleetRecord | null;
  emptyValues: Record<string, unknown>;
  isSubmitting: boolean;
  selectOptionsLoading?: boolean;
  onSubmit: (values: Record<string, unknown>) => void;
}

const buildInitialValues = (
  fields: FleetFormFieldDef[],
  emptyValues: Record<string, unknown>,
  record?: FleetRecord | null,
): Record<string, unknown> => {
  const values: Record<string, unknown> = { ...emptyValues };
  if (!record) return values;

  fields.forEach((field) => {
    const raw = (record as unknown as Record<string, unknown>)[field.name];
    if (raw === null || raw === undefined) {
      values[field.name] = field.noneOption ? FLEET_SELECT_NONE : "";
      return;
    }
    values[field.name] = raw;
  });
  return values;
};

const FleetFormDialog = ({
  open,
  onOpenChange,
  title,
  fields,
  initialRecord,
  emptyValues,
  isSubmitting,
  selectOptionsLoading,
  onSubmit,
}: FleetFormDialogProps) => {
  const [values, setValues] = useState<Record<string, unknown>>({});
  const [errors, setErrors] = useState<Record<string, string>>({});

  useEffect(() => {
    if (open) {
      setValues(buildInitialValues(fields, emptyValues, initialRecord));
      setErrors({});
    }
  }, [open, fields, emptyValues, initialRecord]);

  const shortFields = useMemo(
    () => fields.filter((f) => f.type !== "textarea"),
    [fields],
  );
  const longFields = useMemo(
    () => fields.filter((f) => f.type === "textarea"),
    [fields],
  );

  const validate = () => {
    const next: Record<string, string> = {};
    fields.forEach((field) => {
      const value = values[field.name];
      const stringValue =
        typeof value === "string" ? value.trim() : String(value ?? "");
      if (field.required && (stringValue === "" || stringValue === FLEET_SELECT_NONE)) {
        next[field.name] = `${field.label} is required`;
      }
    });
    setErrors(next);
    return Object.keys(next).length === 0;
  };

  const handleSubmit = () => {
    if (!validate()) return;
    const payload = Object.fromEntries(
      Object.entries(values)
        .map(([key, value]) => {
          if (value === FLEET_SELECT_NONE || value === "") return [key, undefined];
          return [key, value];
        })
        .filter(([, value]) => value !== undefined),
    );
    onSubmit(payload);
  };

  const renderField = (field: FleetFormFieldDef) => {
    const value = values[field.name];
    const error = errors[field.name];

    if (field.type === "select") {
      return (
        <Select
          key={field.name}
          label={field.label}
          data={field.options ?? []}
          value={value == null || value === "" ? (field.noneOption ? FLEET_SELECT_NONE : null) : String(value)}
          onChange={(next) =>
            setValues((current) => ({ ...current, [field.name]: next ?? "" }))
          }
          error={error}
          searchable
          disabled={selectOptionsLoading}
          rightSection={selectOptionsLoading ? <Loader2 size={14} className="animate-spin" /> : undefined}
        />
      );
    }

    if (field.type === "number") {
      return (
        <NumberInput
          key={field.name}
          label={field.label}
          value={value === "" || value == null ? "" : Number(value)}
          onChange={(next) =>
            setValues((current) => ({
              ...current,
              [field.name]: next === "" ? "" : next,
            }))
          }
          error={error}
        />
      );
    }

    if (field.type === "textarea") {
      return (
        <Textarea
          key={field.name}
          label={field.label}
          value={String(value ?? "")}
          onChange={(e) =>
            setValues((current) => ({
              ...current,
              [field.name]: e.target?.value ?? "",
            }))
          }
          error={error}
          minRows={3}
        />
      );
    }

    return (
      <TextInput
        key={field.name}
        label={field.label}
        value={String(value ?? "")}
        onChange={(e) =>
          setValues((current) => ({
            ...current,
            [field.name]: e.target?.value ?? "",
          }))
        }
        error={error}
      />
    );
  };

  return (
    <Modal
      opened={open}
      onClose={() => onOpenChange(false)}
      title={<Text fw={600}>{title}</Text>}
      size="lg"
      radius="lg"
      centered
    >
      <Stack gap="md">
        <SimpleGrid cols={{ base: 1, sm: 2 }} spacing="md">
          {shortFields.map(renderField)}
        </SimpleGrid>
        {longFields.map(renderField)}
        <Group justify="flex-end" gap="sm" mt="sm">
          <Button variant="default" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button color="green" loading={isSubmitting} onClick={handleSubmit}>
            Save
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
};

export default FleetFormDialog;
