import type { UseFormReturnType } from "@mantine/form";
import {
  Accordion,
  ActionIcon,
  Button,
  Group,
  Loader,
  MultiSelect,
  NumberInput,
  Paper,
  Select,
  Stack,
  Switch,
  Text,
  TextInput,
  Textarea,
} from "@mantine/core";
import { DatePickerInput } from "@mantine/dates";
import { IconAlertCircle, IconPlus, IconTrash } from "@tabler/icons-react";
import { useEffect, useState } from "react";
import { listEDMTemplates } from "@/lib/features/edm/query";
import { listServiceCenters } from "@/lib/features/promo-codes/query";
import { searchMemberships } from "@/lib/features/memberships/query";
import { searchMembershipChargeCenters } from "@/lib/features/charge-centers/query";
import {
  listCountriesFromDB,
  resolveCountryRecordID,
} from "@/lib/features/promo-code-campaigns/query";
import type { PromoCodeFormValues } from "@/lib/features/promo-codes/types";

const parseList = (value: string) =>
  value.split(/[\n,]+/g).map((entry) => entry.trim());

const stringifyList = (value: string[]) => value.join(", ");
interface PromoCodeFormProps {
  form: UseFormReturnType<PromoCodeFormValues>;
  isUpdate?: boolean;
  readOnly?: boolean;
}
export const PromoCodeForm: React.FC<PromoCodeFormProps> = ({
  form,
  isUpdate = false,
  readOnly = false,
}) => {
  const [edmOptions, setEdmOptions] = useState<
    { value: string; label: string }[]
  >([]);
  const [edmLoading, setEdmLoading] = useState(false);
  const [edmLoaded, setEdmLoaded] = useState(false);
  const [serviceCenters, setServiceCenters] = useState<
    { value: string; label: string }[]
  >([]);
  const [serviceCentersLoading, setServiceCentersLoading] = useState(false);
  const [accountTypes, setAccountTypes] = useState<
    { value: string; label: string }[]
  >([]);
  const [accountTypesLoading, setAccountTypesLoading] = useState(false);
  const [chargeCenters, setChargeCenters] = useState<
    { value: string; label: string }[]
  >([]);
  const [chargeCentersLoading, setChargeCentersLoading] = useState(false);

  const [countryOptions, setCountryOptions] = useState<
    { value: string; label: string }[]
  >([]);

  const loadEdmTemplates = async () => {
    if (readOnly || edmLoaded || edmLoading) return;

    setEdmLoading(true);
    try {
      const res = await listEDMTemplates();
      if (res.success && Array.isArray(res.data)) {
        setEdmOptions(
          res.data.map((t) => ({ value: t.id, label: `${t.name} (${t.id})` })),
        );
      }
    } catch {
      // ignore load failures; the field can still function as empty
    } finally {
      setEdmLoading(false);
      setEdmLoaded(true);
    }
  };

  useEffect(() => {
    // Fetch countries from DB for the Country Record IDs field.
    void (async () => {
      const res = await listCountriesFromDB();
      if (!res.success) return;
      // The API expects the country record uuid (countries.id), not the ISO
      // code — label with the name so the field stays readable.
      const baseList = res.data.map((c) => ({ value: c.id, label: c.name }));
      // The GET response returns resolved country NAMES under `countries`, not
      // the uuids we submit. mapPromoToForm already translates them when the
      // list is cached; on a cold first load it is not, so re-resolve here —
      // otherwise the selection silently disappears when editing a promo code.
      const baseSet = new Set(baseList.map((item) => item.value));
      const extras: { value: string; label: string }[] = [];
      form.values.signupPromoCodes.forEach((item, index) => {
        const current = item.countryRecordIDs;
        if (!Array.isArray(current)) return;
        const resolved = current.map((id) =>
          resolveCountryRecordID(String(id)),
        );
        if (resolved.some((id, i) => id !== current[i])) {
          form.setFieldValue(
            `signupPromoCodes.${index}.countryRecordIDs`,
            resolved,
          );
        }
        for (const id of resolved) {
          if (id && !baseSet.has(id) && !extras.some((e) => e.value === id)) {
            extras.push({ value: id, label: id });
          }
        }
      });
      setCountryOptions([...baseList, ...extras]);
    })();

    setServiceCentersLoading(true);
    listServiceCenters()
      .then((res) => {
        const list = Array.isArray(res.data)
          ? res.data
          : Array.isArray(res)
            ? res
            : [];
        setServiceCenters(
          list.map((s: any) => ({ value: String(s.id), label: s.name })),
        );
      })
      .catch(() => {})
      .finally(() => setServiceCentersLoading(false));

    setAccountTypesLoading(true);
    searchMemberships()
      .then((res) => {
        const list = Array.isArray(res.data)
          ? res.data
          : Array.isArray(res)
            ? res
            : [];
        setAccountTypes(
          list.map((a: any) => ({ value: String(a.id), label: a.name })),
        );
      })
      .catch(() => {})
      .finally(() => setAccountTypesLoading(false));

    setChargeCentersLoading(true);
    searchMembershipChargeCenters()
      .then((res: any) => {
        const list = Array.isArray(res?.data)
          ? res.data
          : Array.isArray(res)
            ? res
            : [];
        setChargeCenters(
          list.map((cc: any) => ({
            value: String(cc.viewpoint_charge_center_id || cc.id),
            label: `${cc.name}${cc.currency ? ` (${cc.currency})` : ""}`,
          })),
        );
      })
      .catch(() => {})
      .finally(() => setChargeCentersLoading(false));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const normalizeExpiresAt = (value: string | Date | null) => {
    if (!value) return "";
    if (value instanceof Date) return value.toISOString();
    const parsed = new Date(value);
    return Number.isNaN(parsed.getTime()) ? "" : parsed.toISOString();
  };
  const canRemoveSignupPromo = form.values.signupPromoCodes.length > 1;

  const canRemovePromoPoints = form.values.rewards.length > 1;

  const rewardsCount = form.values.rewards.length;
  const signupCount = form.values.signupPromoCodes.length;

  const sectionHasError = (prefixes: string[]) =>
    Object.keys(form.errors).some((key) =>
      prefixes.some((p) => key === p || key.startsWith(`${p}.`)),
    );
  const errors = {
    basic: sectionHasError([
      "name",
      "code",
      "note",
      "description",
      "expiresAt",
    ]),
    rewards: sectionHasError(["rewards"]),
    access: sectionHasError(["access_list"]),
    signup: sectionHasError(["signupPromoCodes"]),
  };
  const SectionLabel = ({
    label,
    hasError,
  }: {
    label: string;
    hasError: boolean;
  }) => (
    <Group gap={6} wrap="nowrap">
      <Text fw={600} c={hasError ? "red" : undefined}>
        {label}
      </Text>
      {hasError && (
        <IconAlertCircle size={16} color="var(--mantine-color-red-6)" />
      )}
    </Group>
  );

  return (
    <Accordion
      multiple
      variant="separated"
      defaultValue={["basic", "rewards", "access", "signup"]}
    >
      <Accordion.Item value="basic">
        <Accordion.Control>
          <SectionLabel label="Basic info" hasError={errors.basic} />
        </Accordion.Control>
        <Accordion.Panel>
          <Stack>
            <TextInput
              label="Name"
              placeholder="Enter name"
              withAsterisk={!isUpdate}
              disabled={readOnly}
              {...form.getInputProps("name")}
              onChange={(event) =>
                form.setFieldValue("name", event.currentTarget.value)
              }
            />

            <TextInput
              label="Code"
              placeholder="Enter code"
              withAsterisk={!isUpdate}
              disabled={readOnly || isUpdate}
              description={
                isUpdate
                  ? "Cannot be changed — existing signups are recorded against this code."
                  : undefined
              }
              {...form.getInputProps("code")}
              onChange={(event) =>
                form.setFieldValue(
                  "code",
                  event.currentTarget.value.toUpperCase(),
                )
              }
            />
            <Switch
              label="Active"
              checked={form.values.isActive}
              disabled={readOnly}
              onChange={(event) =>
                form.setFieldValue("isActive", event.currentTarget.checked)
              }
            />
            <TextInput
              label="Note"
              placeholder="Enter note"
              withAsterisk
              disabled={readOnly}
              {...form.getInputProps("note")}
            />
            <TextInput
              label="Description"
              placeholder="Enter description"
              withAsterisk
              disabled={readOnly}
              {...form.getInputProps("description")}
            />
            <DatePickerInput
              label="Expires At"
              placeholder="Select date"
              value={
                form.values.expiresAt ? new Date(form.values.expiresAt) : null
              }
              onChange={(date) =>
                form.setFieldValue("expiresAt", normalizeExpiresAt(date))
              }
              minDate={new Date()}
              clearable
              disabled={readOnly}
            />
          </Stack>
        </Accordion.Panel>
      </Accordion.Item>

      <Accordion.Item value="rewards">
        <Accordion.Control>
          <SectionLabel
            label={`Rewards (${rewardsCount})`}
            hasError={errors.rewards}
          />
        </Accordion.Control>
        <Accordion.Panel>
          <Stack>
            {form.values.rewards.map((reward, index) => (
              <Group
                key={`reward-${index}`}
                align="flex-end"
                style={{ width: "100%" }}
              >
                <Select
                  label="Reward Type"
                  placeholder="Select type"
                  withAsterisk
                  data={[
                    { value: "POINTS", label: "POINTS" },
                    { value: "DISCOUNT", label: "DISCOUNT" },
                  ]}
                  style={{ flex: 1 }}
                  disabled={readOnly}
                  {...form.getInputProps(`rewards.${index}.type`)}
                />
                <TextInput
                  label="Reward Name"
                  placeholder="Enter name (e.g. 10% Off)"
                  style={{ flex: 1 }}
                  disabled={readOnly}
                  {...form.getInputProps(`rewards.${index}.name`)}
                />
                <NumberInput
                  label="Reward Value"
                  placeholder="0"
                  min={0}
                  withAsterisk
                  style={{ flex: 1 }}
                  disabled={readOnly}
                  {...form.getInputProps(`rewards.${index}.value`)}
                />
                <Select
                  label="Currency"
                  placeholder="Select currency"
                  data={[
                    { value: "USD", label: "USD" },
                    { value: "EUR", label: "EUR" },
                    { value: "INR", label: "INR" },
                    { value: "GBP", label: "GBP" },
                    { value: "AUD", label: "AUD" },
                    { value: "IDR", label: "IDR" },
                    { value: "SGD", label: "SGD" },
                  ]}
                  searchable
                  clearable
                  disabled
                  style={{ flex: 1 }}
                  {...form.getInputProps(`rewards.${index}.currency`)}
                />
                <DatePickerInput
                  label="Expires At"
                  placeholder="Select date"
                  value={reward.expiresAt ? new Date(reward.expiresAt) : null}
                  onChange={(date) =>
                    form.setFieldValue(
                      `rewards.${index}.expiresAt`,
                      normalizeExpiresAt(date),
                    )
                  }
                  minDate={new Date()}
                  clearable
                  style={{ flex: 1 }}
                  disabled={readOnly}
                />
                <NumberInput
                  label="TTL (seconds)"
                  placeholder="e.g. 86400"
                  description="Optional — reward validity after redemption"
                  min={0}
                  style={{ flex: 1 }}
                  disabled={readOnly}
                  {...form.getInputProps(`rewards.${index}.ttl`)}
                />
                {/*
                  The reward's slug. Sent on create and update — it was previously
                  dropped by the payload schema, so setting it here had no effect.
                */}
                <TextInput
                  label="Slug"
                  placeholder="Optional"
                  description={
                    reward.createdAt
                      ? `Reward created ${new Date(reward.createdAt).toLocaleDateString()}`
                      : "Optional identifier for this reward"
                  }
                  style={{ flex: 1 }}
                  disabled={readOnly}
                  {...form.getInputProps(`rewards.${index}.slug`)}
                />
                {!readOnly && (
                  <ActionIcon
                    color="red"
                    variant="light"
                    onClick={() => {
                      if (canRemovePromoPoints) {
                        form.removeListItem("rewards", index);
                      }
                    }}
                    disabled={!canRemovePromoPoints}
                    size="lg"
                    mb={2}
                  >
                    <IconTrash size={16} />
                  </ActionIcon>
                )}
              </Group>
            ))}
            {!readOnly && (
              <Button
                variant="light"
                leftSection={<IconPlus size={16} />}
                onClick={() =>
                  form.insertListItem("rewards", {
                    type: "POINTS",
                    value: 1,
                    name: "",
                    currency: "",
                    expiresAt: "",
                    ttl: null,
                  })
                }
              >
                Add Reward
              </Button>
            )}
          </Stack>
        </Accordion.Panel>
      </Accordion.Item>

      <Accordion.Item value="access">
        <Accordion.Control>
          <SectionLabel label="Access list" hasError={errors.access} />
        </Accordion.Control>
        <Accordion.Panel>
          <Stack>
            <Textarea
              label="Membership Accounts"
              placeholder="Comma or newline separated IDs"
              value={stringifyList(form.values.access_list.membershipAccounts)}
              disabled={readOnly}
              onChange={(event) =>
                form.setFieldValue(
                  "access_list.membershipAccounts",
                  parseList(event.currentTarget.value),
                )
              }
            />
            <Textarea
              label="Membership Clubs"
              placeholder="Comma or newline separated IDs"
              value={stringifyList(form.values.access_list.membershipClubs)}
              disabled={readOnly}
              onChange={(event) =>
                form.setFieldValue(
                  "access_list.membershipClubs",
                  parseList(event.currentTarget.value),
                )
              }
            />
            <Textarea
              label="Membership Account Types"
              placeholder="Comma or newline separated IDs"
              value={stringifyList(
                form.values.access_list.membershipAccountTypes,
              )}
              disabled={readOnly}
              onChange={(event) =>
                form.setFieldValue(
                  "access_list.membershipAccountTypes",
                  parseList(event.currentTarget.value),
                )
              }
            />
          </Stack>
        </Accordion.Panel>
      </Accordion.Item>

      <Accordion.Item value="signup">
        <Accordion.Control>
          <SectionLabel
            label={`Signup promo codes (${signupCount})`}
            hasError={errors.signup}
          />
        </Accordion.Control>
        <Accordion.Panel>
          <Stack>
            {form.values.signupPromoCodes.map((item, index) => (
              <Paper key={`signup-${index}`} withBorder p="md">
                <Stack>
                  <Group justify="space-between">
                    <Text fw={600}>Signup Promo #{index + 1}</Text>
                    {!readOnly && (
                      <ActionIcon
                        color="red"
                        variant="light"
                        onClick={() => {
                          if (canRemoveSignupPromo) {
                            form.removeListItem("signupPromoCodes", index);
                          }
                        }}
                        disabled={!canRemoveSignupPromo}
                      >
                        <IconTrash size={16} />
                      </ActionIcon>
                    )}
                  </Group>
                  {item.id ? (
                    <TextInput
                      label="Signup Promo ID"
                      value={item.id}
                      disabled
                    />
                  ) : null}
                  {item.promoCodeID ? (
                    <TextInput
                      label="Promo Code ID"
                      value={item.promoCodeID}
                      disabled
                    />
                  ) : null}
                  {item.createdAt ? (
                    <TextInput
                      label="Created At"
                      value={item.createdAt}
                      disabled
                    />
                  ) : null}
                  {item.updatedAt ? (
                    <TextInput
                      label="Updated At"
                      value={item.updatedAt}
                      disabled
                    />
                  ) : null}
                  {item.description ? (
                    <Textarea
                      label="Signup Description"
                      value={item.description}
                      disabled
                    />
                  ) : null}
                  {item.note ? (
                    <Textarea label="Signup Note" value={item.note} disabled />
                  ) : null}
                  <Select
                    label="Service Center"
                    placeholder={
                      serviceCentersLoading
                        ? "Loading service centers…"
                        : "Select Service Center"
                    }
                    data={serviceCenters}
                    searchable
                    clearable
                    withAsterisk
                    disabled={serviceCentersLoading || readOnly}
                    rightSection={
                      serviceCentersLoading ? <Loader size={14} /> : undefined
                    }
                    error={
                      form.errors[`signupPromoCodes.${index}.serviceCenterID`]
                    }
                    {...form.getInputProps(
                      `signupPromoCodes.${index}.serviceCenterID`,
                    )}
                  />
                  <Select
                    label="Membership Account Type"
                    placeholder={
                      accountTypesLoading
                        ? "Loading account types…"
                        : "Select Account Type"
                    }
                    data={accountTypes}
                    searchable
                    clearable
                    withAsterisk
                    disabled={accountTypesLoading || readOnly}
                    rightSection={
                      accountTypesLoading ? <Loader size={14} /> : undefined
                    }
                    error={
                      form.errors[
                        `signupPromoCodes.${index}.membershipAccountTypeID`
                      ]
                    }
                    {...form.getInputProps(
                      `signupPromoCodes.${index}.membershipAccountTypeID`,
                    )}
                  />
                  <TextInput
                    label="External Membership Entity ID"
                    placeholder="Enter External Membership Entity ID"
                    withAsterisk
                    disabled={readOnly}
                    {...form.getInputProps(
                      `signupPromoCodes.${index}.externalMembershipEntityID`,
                    )}
                  />
                  <TextInput
                    label="External Membership ID"
                    placeholder="Enter External Membership ID"
                    disabled={readOnly}
                    {...form.getInputProps(
                      `signupPromoCodes.${index}.externalMembershipID`,
                    )}
                  />
                  <MultiSelect
                    label="EDM Templates"
                    description="Select one or more email templates for this signup promo"
                    placeholder={
                      edmLoading ? "Loading templates…" : "Search by name…"
                    }
                    data={edmOptions}
                    value={
                      form.values.signupPromoCodes[index]?.edmTemplateIDs ?? []
                    }
                    onChange={(vals) =>
                      form.setFieldValue(
                        `signupPromoCodes.${index}.edmTemplateIDs`,
                        vals,
                      )
                    }
                    onDropdownOpen={loadEdmTemplates}
                    searchable
                    clearable
                    withAsterisk
                    disabled={edmLoading || readOnly}
                    rightSection={edmLoading ? <Loader size={14} /> : undefined}
                    error={
                      form.errors[`signupPromoCodes.${index}.edmTemplateIDs`]
                    }
                    nothingFoundMessage={
                      edmLoading ? "Loading…" : "No templates found"
                    }
                  />
                  <MultiSelect
                    label="Verification EDM Template"
                    description="Email template used to send the verification email for this signup promo"
                    placeholder={
                      form.values.signupPromoCodes[index]
                        ?.verificationEdmTemplateID
                        ? undefined
                        : edmLoading
                          ? "Loading templates…"
                          : "Search by name…"
                    }
                    data={edmOptions}
                    value={
                      form.values.signupPromoCodes[index]
                        ?.verificationEdmTemplateID
                        ? [
                            form.values.signupPromoCodes[index]
                              .verificationEdmTemplateID as string,
                          ]
                        : []
                    }
                    onChange={(vals) =>
                      form.setFieldValue(
                        `signupPromoCodes.${index}.verificationEdmTemplateID`,
                        vals[vals.length - 1] ?? "",
                      )
                    }
                    maxValues={1}
                    onDropdownOpen={loadEdmTemplates}
                    searchable={
                      !form.values.signupPromoCodes[index]
                        ?.verificationEdmTemplateID
                    }
                    clearable
                    disabled={edmLoading || readOnly}
                    rightSection={edmLoading ? <Loader size={14} /> : undefined}
                    error={
                      form.errors[
                        `signupPromoCodes.${index}.verificationEdmTemplateID`
                      ]
                    }
                    nothingFoundMessage={
                      edmLoading ? "Loading…" : "No templates found"
                    }
                  />
                  <MultiSelect
                    label="Country Record IDs"
                    description="Select one or more country record IDs for this signup promo"
                    placeholder="Search by country name…"
                    data={countryOptions}
                    value={
                      form.values.signupPromoCodes[index]?.countryRecordIDs ??
                      []
                    }
                    onChange={(vals) =>
                      form.setFieldValue(
                        `signupPromoCodes.${index}.countryRecordIDs`,
                        vals,
                      )
                    }
                    searchable
                    clearable
                    disabled={readOnly}
                    error={
                      form.errors[`signupPromoCodes.${index}.countryRecordIDs`]
                    }
                    nothingFoundMessage="No country found"
                  />
                  <Select
                    label="Viewpoint Charge Center ID"
                    placeholder={
                      chargeCentersLoading
                        ? "Loading charge centers…"
                        : "Select Charge Center"
                    }
                    data={chargeCenters}
                    searchable
                    clearable
                    disabled={chargeCentersLoading || readOnly}
                    rightSection={
                      chargeCentersLoading ? <Loader size={14} /> : undefined
                    }
                    error={
                      form.errors[
                        `signupPromoCodes.${index}.viewpointChargeCenterID`
                      ]
                    }
                    {...form.getInputProps(
                      `signupPromoCodes.${index}.viewpointChargeCenterID`,
                    )}
                  />
                </Stack>
              </Paper>
            ))}
            {!readOnly && (
              <Button
                variant="light"
                leftSection={<IconPlus size={16} />}
                onClick={() =>
                  form.insertListItem("signupPromoCodes", {
                    serviceCenterID: "",
                    edmTemplateIDs: [],
                    externalMembershipEntityID: "",
                    membershipAccountTypeID: "",
                    externalMembershipID: "",
                    verificationEdmTemplateID: "",
                    countryRecordIDs: [],
                    viewpointChargeCenterID: "",
                  })
                }
              >
                Add Signup Promo
              </Button>
            )}
          </Stack>
        </Accordion.Panel>
      </Accordion.Item>
    </Accordion>
  );
};
