"use client";

import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
import {
  useMessages,
  useTranslation,
} from "../../../../contexts/MessagesContext";
import { useAsyncConfirm } from "../../../../hooks/useAsyncConfirm";
import { useBeforeUnloadGuard } from "../../../../hooks/useBeforeUnloadGuard";
import type { CustomMethodCardFieldBlock } from "../../../../../lib/create/customMethodCardFieldBlocks";
import {
  CUSTOM_METHOD_CARD_WIZARD_MAX_DESCRIPTION_CHARS,
  CUSTOM_METHOD_CARD_WIZARD_MAX_FIELD_CHARS,
} from "../../../../../lib/create/customMethodCardWizardConstants";
import type { AddCustomFieldType } from "../../../../components/controls/AddCustomField/AddCustomField.types";
import type { ModalHeaderMenuItem } from "../../../../components/modals/ModalHeader/ModalHeader.types";
import { CustomMethodCardWizardView } from "./CustomMethodCardWizard.view";
import type { CustomMethodCardWizardProps } from "./CustomMethodCardWizard.types";

/**
 * Shared 3-step add-custom-method-card flow (Figma Modal / Create — nodes
 * `20066:14748`, `20094:48551`, `20066:14361`).
 */
const CustomMethodCardWizardContainer = memo<CustomMethodCardWizardProps>(
  ({ isOpen, onClose, onFinalize, onPersistCustomUploadFile, initialValues }) => {
    const m = useMessages();
    const t = useTranslation("common");
    const tUpload = useTranslation("create.upload");
    const w = m.create.customRule.customMethodCardWizard;
    const menuCopy = m.create.customRule.modalKebabMenu;
    const { requestConfirm, confirmDialog } = useAsyncConfirm();

    const copy = useMemo(
      () => ({
        step1: w.steps["1"],
        step2: w.steps["2"],
        step3: w.steps["3"],
        step3BlocksList: w.step3BlocksList,
        fieldTypeLabels: {
          text: w.addCustomField.fieldTypes.text,
          badges: w.addCustomField.fieldTypes.badges,
          upload: w.addCustomField.fieldTypes.upload,
          proportion: w.addCustomField.fieldTypes.proportion,
        },
        footerFinalize: w.footer.finalize,
        fieldModals: w.fieldModals,
      }),
      [
        w.addCustomField.fieldTypes,
        w.fieldModals,
        w.footer.finalize,
        w.step3BlocksList,
        w.steps,
      ],
    );

    const fieldBodiesCopy = useMemo(
      () => ({
        requiredHint: copy.fieldModals.requiredHint,
        text: copy.fieldModals.text,
        badges: copy.fieldModals.badges,
        upload: copy.fieldModals.upload,
        proportion: copy.fieldModals.proportion,
      }),
      [copy.fieldModals],
    );

    const [wizardStep, setWizardStep] = useState<1 | 2 | 3>(1);
    const [policyTitle, setPolicyTitle] = useState("");
    const [policyDescription, setPolicyDescription] = useState("");
    const [addFieldExpanded, setAddFieldExpanded] = useState(false);
    const [fieldTypeModal, setFieldTypeModal] =
      useState<AddCustomFieldType | null>(null);
    const [draftFieldBlocks, setDraftFieldBlocks] = useState<
      CustomMethodCardFieldBlock[]
    >([]);
    const [editingBlockId, setEditingBlockId] = useState<string | null>(null);

    const [textBlockTitle, setTextBlockTitle] = useState("");
    const [textPlaceholderBody, setTextPlaceholderBody] = useState("");
    const [badgeBlockTitle, setBadgeBlockTitle] = useState("");
    const [badgeOptions, setBadgeOptions] = useState<string[]>([]);
    const [uploadBlockTitle, setUploadBlockTitle] = useState("");
    const [uploadFileName, setUploadFileName] = useState<string | undefined>(
      undefined,
    );
    const [uploadAssetUrl, setUploadAssetUrl] = useState<string | undefined>(
      undefined,
    );
    const [uploadFieldBusy, setUploadFieldBusy] = useState(false);
    const [uploadFieldError, setUploadFieldError] = useState<string | null>(
      null,
    );
    const [proportionBlockTitle, setProportionBlockTitle] = useState("");
    const [proportionDefault, setProportionDefault] = useState(50);

    const fileInputRef = useRef<HTMLInputElement>(null);
    const initialValuesRef = useRef(initialValues);
    initialValuesRef.current = initialValues;
    const openSnapshotRef = useRef<{
      title: string;
      description: string;
      fieldBlocks: string;
    } | null>(null);
    const fieldModalSnapshotRef = useRef<string | null>(null);

    const resetFieldTypeDrafts = useCallback(() => {
      setTextBlockTitle("");
      setTextPlaceholderBody("");
      setBadgeBlockTitle("");
      setBadgeOptions([]);
      setUploadBlockTitle("");
      setUploadFileName(undefined);
      setUploadAssetUrl(undefined);
      setUploadFieldBusy(false);
      setUploadFieldError(null);
      setProportionBlockTitle("");
      setProportionDefault(50);
      if (fileInputRef.current) {
        fileInputRef.current.value = "";
      }
    }, []);

    const reset = useCallback(() => {
      setWizardStep(1);
      setPolicyTitle("");
      setPolicyDescription("");
      setAddFieldExpanded(false);
      setFieldTypeModal(null);
      setEditingBlockId(null);
      setDraftFieldBlocks([]);
      openSnapshotRef.current = null;
      fieldModalSnapshotRef.current = null;
      resetFieldTypeDrafts();
    }, [resetFieldTypeDrafts]);

    useEffect(() => {
      if (!isOpen) {
        reset();
        return;
      }
      const init = initialValuesRef.current;
      setWizardStep(1);
      setPolicyTitle(init?.title ?? "");
      setPolicyDescription(init?.description ?? "");
      setAddFieldExpanded(false);
      setFieldTypeModal(null);
      setEditingBlockId(null);
      setDraftFieldBlocks(
        init?.fieldBlocks ? structuredClone(init.fieldBlocks) : [],
      );
      openSnapshotRef.current = {
        title: init?.title ?? "",
        description: init?.description ?? "",
        fieldBlocks: JSON.stringify(init?.fieldBlocks ?? []),
      };
      fieldModalSnapshotRef.current = null;
      resetFieldTypeDrafts();
    }, [isOpen, reset, resetFieldTypeDrafts]);

    const dismiss = useCallback(() => {
      reset();
      onClose();
    }, [onClose, reset]);

    const fieldModalDraftSignature = useCallback(() => {
      return JSON.stringify({
        fieldTypeModal,
        textBlockTitle,
        textPlaceholderBody,
        badgeBlockTitle,
        badgeOptions,
        uploadBlockTitle,
        uploadFileName,
        uploadAssetUrl,
        proportionBlockTitle,
        proportionDefault,
      });
    }, [
      badgeBlockTitle,
      badgeOptions,
      fieldTypeModal,
      proportionBlockTitle,
      proportionDefault,
      textBlockTitle,
      textPlaceholderBody,
      uploadAssetUrl,
      uploadBlockTitle,
      uploadFileName,
    ]);

    const isWizardSessionDirty = useCallback(() => {
      const snap = openSnapshotRef.current;
      if (!snap) return false;
      if (policyTitle !== snap.title || policyDescription !== snap.description) {
        return true;
      }
      if (JSON.stringify(draftFieldBlocks) !== snap.fieldBlocks) {
        return true;
      }
      if (
        fieldTypeModal &&
        fieldModalSnapshotRef.current != null &&
        fieldModalDraftSignature() !== fieldModalSnapshotRef.current
      ) {
        return true;
      }
      return false;
    }, [
      draftFieldBlocks,
      fieldModalDraftSignature,
      fieldTypeModal,
      policyDescription,
      policyTitle,
    ]);

    useBeforeUnloadGuard(isOpen && isWizardSessionDirty());

    const confirmAbandonWizardEdits = useCallback(async () => {
      if (!isWizardSessionDirty()) {
        return true;
      }
      return requestConfirm({
        title: menuCopy.discardUnsavedCustomizeChangesTitle,
        description: menuCopy.discardUnsavedCustomizeChangesDescription,
        proceedText: menuCopy.discardUnsavedCustomizeChangesProceed,
        cancelText: menuCopy.discardUnsavedCustomizeChangesCancel,
      });
    }, [
      isWizardSessionDirty,
      menuCopy.discardUnsavedCustomizeChangesCancel,
      menuCopy.discardUnsavedCustomizeChangesDescription,
      menuCopy.discardUnsavedCustomizeChangesProceed,
      menuCopy.discardUnsavedCustomizeChangesTitle,
      requestConfirm,
    ]);

    const titleTrim = policyTitle.trim();
    const descriptionTrim = policyDescription.trim();

    const stepValid = useMemo(() => {
      const titleOk =
        titleTrim.length > 0 &&
        titleTrim.length <= CUSTOM_METHOD_CARD_WIZARD_MAX_FIELD_CHARS;
      const descriptionOk =
        descriptionTrim.length > 0 &&
        descriptionTrim.length <= CUSTOM_METHOD_CARD_WIZARD_MAX_DESCRIPTION_CHARS;
      if (wizardStep === 1) return titleOk;
      if (wizardStep === 2) return descriptionOk;
      return titleOk && descriptionOk;
    }, [
      descriptionTrim.length,
      titleTrim.length,
      wizardStep,
    ]);

    const fieldModalStepValid = useMemo(() => {
      if (!fieldTypeModal) return false;
      if (fieldTypeModal === "text") {
        const t0 = textBlockTitle.trim();
        return (
          t0.length > 0 &&
          t0.length <= CUSTOM_METHOD_CARD_WIZARD_MAX_FIELD_CHARS
        );
      }
      if (fieldTypeModal === "badges") {
        const t0 = badgeBlockTitle.trim();
        return (
          t0.length > 0 &&
          t0.length <= CUSTOM_METHOD_CARD_WIZARD_MAX_FIELD_CHARS
        );
      }
      if (fieldTypeModal === "upload") {
        const t0 = uploadBlockTitle.trim();
        const titleOk =
          t0.length > 0 &&
          t0.length <= CUSTOM_METHOD_CARD_WIZARD_MAX_FIELD_CHARS;
        if (!titleOk) return false;
        if (onPersistCustomUploadFile) {
          return Boolean(uploadAssetUrl?.trim());
        }
        return true;
      }
      const t0 = proportionBlockTitle.trim();
      return (
        t0.length > 0 &&
        t0.length <= CUSTOM_METHOD_CARD_WIZARD_MAX_FIELD_CHARS &&
        proportionDefault >= 1 &&
        proportionDefault <= 100
      );
    }, [
      badgeBlockTitle,
      fieldTypeModal,
      proportionBlockTitle,
      proportionDefault,
      textBlockTitle,
      uploadBlockTitle,
      uploadAssetUrl,
      onPersistCustomUploadFile,
    ]);

    const headerTitle =
      wizardStep === 1
        ? copy.step1.title
        : wizardStep === 2
          ? copy.step2.title
          : copy.step3.title;

    const headerDescription =
      wizardStep === 1
        ? copy.step1.description
        : wizardStep === 2
          ? copy.step2.description
          : copy.step3.description;

    const fieldModalHeader = fieldTypeModal
      ? copy.fieldModals[fieldTypeModal]
      : null;

    const shellTitle = fieldModalHeader?.title ?? headerTitle;
    const shellDescription = fieldModalHeader?.description ?? headerDescription;

    const nextLabel = fieldTypeModal
      ? editingBlockId
        ? copy.fieldModals.saveField
        : copy.fieldModals.addField
      : wizardStep === 3
        ? copy.footerFinalize
        : t("buttons.next");

    const shellNextDisabled = fieldTypeModal
      ? !fieldModalStepValid
      : !stepValid;

    const handleShellClose = useCallback(async () => {
      if (fieldTypeModal) {
        if (
          fieldModalSnapshotRef.current != null &&
          fieldModalDraftSignature() !== fieldModalSnapshotRef.current &&
          !(await confirmAbandonWizardEdits())
        ) {
          return;
        }
        setFieldTypeModal(null);
        setEditingBlockId(null);
        fieldModalSnapshotRef.current = null;
        return;
      }
      if (!(await confirmAbandonWizardEdits())) {
        return;
      }
      dismiss();
    }, [
      confirmAbandonWizardEdits,
      dismiss,
      fieldModalDraftSignature,
      fieldTypeModal,
    ]);

    const kebabMenuItems = useMemo<ModalHeaderMenuItem[]>(() => [], []);

    const handleBack = useCallback(async () => {
      if (fieldTypeModal) {
        if (
          fieldModalSnapshotRef.current != null &&
          fieldModalDraftSignature() !== fieldModalSnapshotRef.current &&
          !(await confirmAbandonWizardEdits())
        ) {
          return;
        }
        setFieldTypeModal(null);
        setEditingBlockId(null);
        fieldModalSnapshotRef.current = null;
        return;
      }
      if (wizardStep === 1) {
        if (!(await confirmAbandonWizardEdits())) {
          return;
        }
        dismiss();
        return;
      }
      setWizardStep((s) => (s === 2 ? 1 : 2));
    }, [
      confirmAbandonWizardEdits,
      dismiss,
      fieldModalDraftSignature,
      fieldTypeModal,
      wizardStep,
    ]);

    const handleSelectFieldType = useCallback((ft: AddCustomFieldType) => {
      setEditingBlockId(null);
      setAddFieldExpanded(false);
      resetFieldTypeDrafts();
      setFieldTypeModal(ft);
      fieldModalSnapshotRef.current = JSON.stringify({
        fieldTypeModal: ft,
        textBlockTitle: "",
        textPlaceholderBody: "",
        badgeBlockTitle: "",
        badgeOptions: [],
        uploadBlockTitle: "",
        uploadFileName: undefined,
        uploadAssetUrl: undefined,
        proportionBlockTitle: "",
        proportionDefault: 50,
      });
    }, [resetFieldTypeDrafts]);

    const handleEditFieldBlock = useCallback(
      (block: CustomMethodCardFieldBlock) => {
        resetFieldTypeDrafts();
        setEditingBlockId(block.id);
        setAddFieldExpanded(false);
        switch (block.kind) {
          case "text":
            setTextBlockTitle(block.blockTitle);
            setTextPlaceholderBody(block.placeholderText);
            break;
          case "badges":
            setBadgeBlockTitle(block.blockTitle);
            setBadgeOptions([...block.options]);
            break;
          case "upload":
            setUploadBlockTitle(block.blockTitle);
            setUploadFileName(block.fileName);
            setUploadAssetUrl(block.assetUrl);
            break;
          case "proportion":
            setProportionBlockTitle(block.blockTitle);
            setProportionDefault(block.defaultPercent);
            break;
        }
        setFieldTypeModal(block.kind);
        fieldModalSnapshotRef.current = JSON.stringify({
          fieldTypeModal: block.kind,
          textBlockTitle: block.kind === "text" ? block.blockTitle : "",
          textPlaceholderBody:
            block.kind === "text" ? block.placeholderText : "",
          badgeBlockTitle: block.kind === "badges" ? block.blockTitle : "",
          badgeOptions: block.kind === "badges" ? [...block.options] : [],
          uploadBlockTitle: block.kind === "upload" ? block.blockTitle : "",
          uploadFileName: block.kind === "upload" ? block.fileName : undefined,
          uploadAssetUrl: block.kind === "upload" ? block.assetUrl : undefined,
          proportionBlockTitle:
            block.kind === "proportion" ? block.blockTitle : "",
          proportionDefault: block.kind === "proportion" ? block.defaultPercent : 50,
        });
      },
      [resetFieldTypeDrafts],
    );

    const handleFileChosen = useCallback(
      async (e: React.ChangeEvent<HTMLInputElement>) => {
        const file = e.target.files?.[0];
        setUploadFileName(file?.name);
        setUploadAssetUrl(undefined);
        setUploadFieldError(null);
        if (!file || !onPersistCustomUploadFile) return;
        setUploadFieldBusy(true);
        try {
          const { url } = await onPersistCustomUploadFile(file);
          setUploadAssetUrl(url);
        } catch {
          setUploadFieldError(tUpload("errors.generic"));
        } finally {
          setUploadFieldBusy(false);
        }
      },
      [onPersistCustomUploadFile, tUpload],
    );

    const handleClearPendingUpload = useCallback(() => {
      setUploadFileName(undefined);
      setUploadAssetUrl(undefined);
      setUploadFieldError(null);
      setUploadFieldBusy(false);
      if (fileInputRef.current) {
        fileInputRef.current.value = "";
      }
    }, []);

    const handleBadgeAddOption = useCallback((label: string) => {
      setBadgeOptions((prev) =>
        prev.includes(label) ? prev : [...prev, label],
      );
    }, []);

    const commitFieldBlock = useCallback(() => {
      if (!fieldTypeModal || !fieldModalStepValid) return;
      const id = editingBlockId ?? crypto.randomUUID();
      let block: CustomMethodCardFieldBlock;
      switch (fieldTypeModal) {
        case "text":
          block = {
            kind: "text",
            id,
            blockTitle: textBlockTitle.trim(),
            placeholderText: textPlaceholderBody,
          };
          break;
        case "badges":
          block = {
            kind: "badges",
            id,
            blockTitle: badgeBlockTitle.trim(),
            options: [...badgeOptions],
          };
          break;
        case "upload":
          block = {
            kind: "upload",
            id,
            blockTitle: uploadBlockTitle.trim(),
            fileName: uploadFileName,
            ...(uploadAssetUrl?.trim()
              ? { assetUrl: uploadAssetUrl.trim() }
              : {}),
          };
          break;
        default:
          block = {
            kind: "proportion",
            id,
            blockTitle: proportionBlockTitle.trim(),
            defaultPercent: proportionDefault,
          };
      }
      setDraftFieldBlocks((prev) => {
        if (editingBlockId) {
          return prev.map((row) => (row.id === editingBlockId ? block : row));
        }
        return [...prev, block];
      });
      setFieldTypeModal(null);
      setEditingBlockId(null);
      setAddFieldExpanded(false);
      fieldModalSnapshotRef.current = null;
    }, [
      badgeBlockTitle,
      badgeOptions,
      editingBlockId,
      fieldModalStepValid,
      fieldTypeModal,
      proportionBlockTitle,
      proportionDefault,
      textBlockTitle,
      textPlaceholderBody,
      uploadBlockTitle,
      uploadFileName,
      uploadAssetUrl,
    ]);

    const handleNext = useCallback(() => {
      if (fieldTypeModal) {
        commitFieldBlock();
        return;
      }
      if (!stepValid) return;
      if (wizardStep === 3) {
        onFinalize({
          title: titleTrim,
          description: descriptionTrim,
          fieldBlocks: draftFieldBlocks,
        });
        dismiss();
        return;
      }
      setWizardStep((s) => (s === 1 ? 2 : 3));
    }, [
      commitFieldBlock,
      descriptionTrim,
      dismiss,
      draftFieldBlocks,
      fieldTypeModal,
      onFinalize,
      stepValid,
      titleTrim,
      wizardStep,
    ]);

    return (
      <>
      <CustomMethodCardWizardView
        isOpen={isOpen}
        onDismiss={handleShellClose}
        wizardStep={wizardStep}
        title={shellTitle}
        description={shellDescription}
        policyTitle={policyTitle}
        policyDescription={policyDescription}
        addFieldExpanded={addFieldExpanded}
        copy={copy}
        maxTitleChars={CUSTOM_METHOD_CARD_WIZARD_MAX_FIELD_CHARS}
        maxDescriptionChars={CUSTOM_METHOD_CARD_WIZARD_MAX_DESCRIPTION_CHARS}
        onPolicyTitleChange={setPolicyTitle}
        onPolicyDescriptionChange={setPolicyDescription}
        onPressAddCustomField={() => setAddFieldExpanded(true)}
        onSelectFieldType={handleSelectFieldType}
        fieldTypeModal={fieldTypeModal}
        fieldBodiesCopy={fieldBodiesCopy}
        fieldBodiesProps={{
          textBlockTitle,
          textPlaceholderBody,
          onTextBlockTitleChange: setTextBlockTitle,
          onTextPlaceholderBodyChange: setTextPlaceholderBody,
          badgeBlockTitle,
          badgeOptions,
          onBadgeBlockTitleChange: setBadgeBlockTitle,
          onBadgeAddOption: handleBadgeAddOption,
          uploadBlockTitle,
          onUploadBlockTitleChange: setUploadBlockTitle,
          fileInputRef,
          onFileChosen: handleFileChosen,
          onClearPendingUpload: handleClearPendingUpload,
          uploadAssetPreviewUrl: uploadAssetUrl,
          uploadPersisting:
            Boolean(fieldTypeModal === "upload" && uploadFieldBusy),
          uploadBusyHint: tUpload("uploading"),
          uploadErrorMessage:
            fieldTypeModal === "upload" ? uploadFieldError : null,
          proportionBlockTitle,
          proportionDefault,
          onProportionBlockTitleChange: setProportionBlockTitle,
          onProportionDefaultChange: setProportionDefault,
        }}
        nextDisabled={shellNextDisabled}
        nextLabel={nextLabel}
        showBackButton
        onBack={handleBack}
        onNext={handleNext}
        stepper={!fieldTypeModal}
        draftFieldBlocks={draftFieldBlocks}
        onDraftFieldBlocksReorder={setDraftFieldBlocks}
        onEditFieldBlock={handleEditFieldBlock}
        kebabMoreOptionsAriaLabel={menuCopy.triggerAriaLabel}
        kebabMenuAriaLabel={menuCopy.menuAriaLabel}
        kebabMenuItems={kebabMenuItems}
      />
      {confirmDialog}
      </>
    );
  },
);

CustomMethodCardWizardContainer.displayName = "CustomMethodCardWizard";

export default CustomMethodCardWizardContainer;
