"use client";

import { useState, useRef, useTransition, useEffect, useCallback } from "react";
import { Modal } from "@/components/ui/modal";
import Button from "@/components/ui/button/Button";
import { Typography } from "@/components/atoms/typogrpahy";
import {
  createWithdrawal,
  checkPendingWithdrawal,
  requestWithdrawalOTP,
} from "../actions/withdrawal.action";
import { formatBalanceCurrency, currencyToSymbol } from "@/lib/transactionUtil";
import { AVAILABLE_BANKS, type Bank } from "../const/bankList";
import { minWithdrawalByCurrency } from "../const/const";
import { withdrawalOtpCopy } from "../const/withdrawalOtpCopy";
import { hasPortableTextContent } from "@/lib/tenantContent";
import { User } from "@/types/auth";
import { ClientOnly } from "@/components/common/ClientOnly";
import { useRouter, useSearchParams } from "next/navigation";
import toast from "react-hot-toast";
import { ChevronDown } from "lucide-react";
import ModalTnC from "@/modules/authModule/signin/components/ModalTnC";
import Checkbox from "@/components/form/input/Checkbox";
import { XenditPayoutChannel } from "../types/withdrawal.types";
import {
  TransactionStatus,
  useTransactionStatus,
} from "@/modules/transactionModule/hooks/useTransactionStatus";
import { hasReachedTermsEnd } from "./termsReadiness";

interface WithdrawalFormProps {
  currentBalance: number;
  currency: string;
  initialProfile: User | null;
  withdrawalTnC?: {
    title?: string;
    body?: any; // Sanity portable text
    effectiveFrom?: string;
  } | null;
}

const WITHDRAW_CLIENT_LOG_PREFIX = "[withdraw][client]";
const CHANNEL_DEFAULT_ERROR_MESSAGE = "Failed to load payout channels";

const normalizeChannelKey = (value: string): string => {
  return value.trim().toUpperCase().replace(/^ID_/, "");
};

const maskAccountNumber = (accountNumber: string): string => {
  const cleaned = accountNumber.replace(/\s+/g, "");
  if (cleaned.length <= 4) {
    return cleaned;
  }
  return `${"*".repeat(cleaned.length - 4)}${cleaned.slice(-4)}`;
};

const logWithdrawalClient = (
  requestId: string,
  event: string,
  payload?: Record<string, unknown>,
) => {
  console.info(`${WITHDRAW_CLIENT_LOG_PREFIX} ${event}`, {
    requestId,
    at: new Date().toISOString(),
    ...payload,
  });
};

const warnWithdrawalClient = (
  requestId: string,
  event: string,
  payload?: Record<string, unknown>,
) => {
  console.warn(`${WITHDRAW_CLIENT_LOG_PREFIX} ${event}`, {
    requestId,
    at: new Date().toISOString(),
    ...payload,
  });
};

const errorWithdrawalClient = (
  requestId: string,
  event: string,
  payload?: Record<string, unknown>,
) => {
  console.error(`${WITHDRAW_CLIENT_LOG_PREFIX} ${event}`, {
    requestId,
    at: new Date().toISOString(),
    ...payload,
  });
};

const resolveBankPreset = (channelCode: string, channelName: string): Bank | undefined => {
  const codeKey = normalizeChannelKey(channelCode || "");
  const nameKey = normalizeChannelKey(channelName || "");

  const byCode = AVAILABLE_BANKS.find((bank) => normalizeChannelKey(bank.code) === codeKey);
  if (byCode) {
    return byCode;
  }

  return AVAILABLE_BANKS.find((bank) => normalizeChannelKey(bank.name) === nameKey);
};

const buildBankOptionsFromXenditChannels = (channels: XenditPayoutChannel[]): Bank[] => {
  const channelByCode = new Map<string, Bank>();

  for (const channel of channels) {
    if (channel.is_available === false) {
      continue;
    }
    if (!channel.channel_code) {
      continue;
    }
    const channelCode = channel.channel_code.trim().toUpperCase();
    const channelCategory = (channel.channel_category || "").trim().toUpperCase();
    const currency = (channel.currency || "").trim().toUpperCase();
    const isBankChannel = !channelCategory || channelCategory.includes("BANK");
    const isIndonesiaChannel = channelCode.startsWith("ID_") || currency === "IDR";
    if (!isBankChannel || !isIndonesiaChannel) {
      continue;
    }

    const preset = resolveBankPreset(channel.channel_code, channel.channel_name || "");
    if (!preset) {
      continue;
    }

    if (!channelByCode.has(channel.channel_code)) {
      channelByCode.set(channel.channel_code, {
        id: preset.id,
        name: preset.name,
        code: channel.channel_code,
        logo: preset.logo,
      });
    }
  }

  return Array.from(channelByCode.values()).sort((a, b) => a.name.localeCompare(b.name));
};

type WithdrawalTrackingPhase = "IDLE" | "PROCESSING" | "SUCCESS" | "FAILED";

const extractCreatedWithdrawalTransactionId = (result: {
  transactionId?: string;
  data?: any;
}): string | undefined => {
  const candidates = [
    result.transactionId,
    result.data?.id,
    result.data?.transaction_id,
    result.data?.transactionId,
    result.data?.transaction?.id,
    result.data?.withdrawal?.transaction_id,
    result.data?.withdrawal_detail?.transaction_id,
  ];

  for (const candidate of candidates) {
    if (typeof candidate === "string" && candidate.trim().length > 0) {
      return candidate.trim();
    }
  }

  return undefined;
};

const getTerminalFailureMessage = (status: TransactionStatus): string => {
  switch (status) {
    case "FAILED":
      return "Withdrawal payout failed. Please verify your account details and try again.";
    case "REVERSED":
      return "Withdrawal payout was reversed by the payment provider.";
    case "EXPIRED":
      return "Withdrawal payout request expired before completion.";
    case "CANCELED":
      return "Withdrawal payout was canceled.";
    default:
      return "Withdrawal payout did not complete.";
  }
};

const releaseModalScrollLock = () => {
  if (typeof document === "undefined") {
    return;
  }

  document.body.style.overflow = "";
  document.body.style.overscrollBehavior = "";
  document.documentElement.style.overscrollBehavior = "";
};

export const WithdrawalForm: React.FC<WithdrawalFormProps> = ({
  currentBalance,
  currency,
  initialProfile,
  withdrawalTnC,
}) => {
  const generateRequestId = (): string => {
    if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
      return crypto.randomUUID();
    }
    return `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
  };

  const searchParams = useSearchParams();
  const adminFeeFromUrl = searchParams.get("admin_fee");
  const ADMIN_FEE = adminFeeFromUrl ? parseInt(adminFeeFromUrl) : 10000; // Use admin fee from URL or default to 10000
  // Quick Pick amounts
  const predefinedAmounts = [50000, 100000, 200000, 500000];
  const minWithdrawalAmount = minWithdrawalByCurrency[currency] || predefinedAmounts[0];
  // Always enforce minimum withdrawal validation
  const enforceMinWithdrawal = true;

  const [amount, setAmount] = useState<number>(predefinedAmounts[0]);
  const [displayAmount, setDisplayAmount] = useState<string>(
    predefinedAmounts[0].toLocaleString("id-ID"),
  );
  const [withdrawAll, setWithdrawAll] = useState<boolean>(false);
  const isBelowMin = enforceMinWithdrawal && amount <= minWithdrawalAmount;
  const [amountError, setAmountError] = useState<string | null>(null);
  const amountInputRef = useRef<HTMLInputElement>(null);

  // Form fields
  const [fullName, setFullName] = useState<string>("");
  const [phoneNumber, setPhoneNumber] = useState<string>("");
  const [email, setEmail] = useState<string>("");
  const [bankName, setBankName] = useState<string>("");
  const [availableBanks, setAvailableBanks] = useState<Bank[]>([]);
  const [isLoadingChannels, setIsLoadingChannels] = useState<boolean>(true);
  const [channelLoadError, setChannelLoadError] = useState<string | null>(null);
  const [accountNumber, setAccountNumber] = useState<string>("");
  const [accountHolderName, setAccountHolderName] = useState<string>("");
  const [otpCode, setOtpCode] = useState<string>("");
  const [otpError, setOtpError] = useState<string | null>(null);
  const [isRequestingOtp, setIsRequestingOtp] = useState<boolean>(false);
  const [confirmationAgreed, setConfirmationAgreed] = useState<boolean>(false);
  const [hasPendingWithdrawal, setHasPendingWithdrawal] = useState<boolean>(false);
  const [isCheckingPending, setIsCheckingPending] = useState<boolean>(true);

  const [isConfirmModalOpen, setIsConfirmModalOpen] = useState<boolean>(false);

  // TNC modal states
  const [showTerms, setShowTerms] = useState<boolean>(false);
  const [canAcceptTerms, setCanAcceptTerms] = useState<boolean>(false);
  const [hasReadTerms, setHasReadTerms] = useState<boolean>(false);
  const hasTermsContent = hasPortableTextContent(withdrawalTnC?.body);

  const formRef = useRef<HTMLFormElement>(null);
  const requestIdRef = useRef<string>(generateRequestId());
  const [isPending, startTransition] = useTransition();
  const router = useRouter();
  const [isPayoutStatusModalOpen, setIsPayoutStatusModalOpen] = useState<boolean>(false);
  const [payoutTrackingPhase, setPayoutTrackingPhase] = useState<WithdrawalTrackingPhase>("IDLE");
  const [withdrawalTransactionId, setWithdrawalTransactionId] = useState<string>("");
  const [terminalTransactionStatus, setTerminalTransactionStatus] =
    useState<TransactionStatus | null>(null);
  const [payoutTrackingError, setPayoutTrackingError] = useState<string | null>(null);

  // Check for pending withdrawal requests
  useEffect(() => {
    const checkPending = async () => {
      const requestId = requestIdRef.current;
      try {
        setIsCheckingPending(true);
        logWithdrawalClient(requestId, "pending-check-start");
        const result = await checkPendingWithdrawal();
        setHasPendingWithdrawal(result.hasPending);
        logWithdrawalClient(requestId, "pending-check-finished", {
          hasPending: result.hasPending,
          error: result.error || null,
        });
      } catch (error) {
        errorWithdrawalClient(requestId, "pending-check-exception", {
          error: error instanceof Error ? error.message : String(error),
        });
        // Don't block user if check fails, but log the error
      } finally {
        setIsCheckingPending(false);
      }
    };

    checkPending();
  }, []);

  const resetWithdrawalForm = useCallback(() => {
    const defaultAmount = predefinedAmounts[0];
    const defaultFullName = initialProfile
      ? `${initialProfile.firstname || ""} ${initialProfile.lastname || ""}`.trim()
      : "";

    setAmount(defaultAmount);
    setDisplayAmount(defaultAmount.toLocaleString("id-ID"));
    setAmountError(null);
    setFullName(defaultFullName);
    setPhoneNumber(initialProfile?.phone || "");
    setEmail(initialProfile?.email || "");
    setBankName("");
    setAccountNumber("");
    setAccountHolderName(defaultFullName);
    setOtpCode("");
    setOtpError(null);
    setConfirmationAgreed(false);
    setWithdrawAll(false);
  }, [initialProfile, predefinedAmounts]);

  const handlePayoutTerminalStatus = useCallback(
    (status: TransactionStatus) => {
      setTerminalTransactionStatus(status);
      setHasPendingWithdrawal(false);

      if (status === "SUCCESS") {
        setPayoutTrackingPhase("SUCCESS");
        setPayoutTrackingError(null);
        resetWithdrawalForm();
      } else {
        const failureMessage = getTerminalFailureMessage(status);
        setPayoutTrackingPhase("FAILED");
        setPayoutTrackingError(failureMessage);
      }
    },
    [resetWithdrawalForm],
  );

  const handlePayoutStatusError = useCallback((error: string) => {
    setPayoutTrackingError(
      "Connection to payout status is unstable. We will keep retrying automatically.",
    );
    warnWithdrawalClient(requestIdRef.current, "payout-status-watch-error", {
      error,
    });
  }, []);

  useTransactionStatus(withdrawalTransactionId, {
    enabled:
      isPayoutStatusModalOpen &&
      payoutTrackingPhase === "PROCESSING" &&
      Boolean(withdrawalTransactionId),
    onTerminalStatus: handlePayoutTerminalStatus,
    onError: handlePayoutStatusError,
  });

  useEffect(() => {
    let mounted = true;

    const fetchDynamicChannels = async () => {
      const requestId = requestIdRef.current;
      try {
        setIsLoadingChannels(true);
        setChannelLoadError(null);
        logWithdrawalClient(requestId, "channel-fetch-start");

        const response = await fetch("/api/withdrawals", {
          method: "GET",
          cache: "no-store",
        });
        const responseBody = await response.json().catch(() => null);

        if (!response.ok || !responseBody?.ok || !Array.isArray(responseBody?.result)) {
          throw new Error(responseBody?.message || "Invalid channel response");
        }

        const rawChannels = responseBody.result as XenditPayoutChannel[];
        const channels = buildBankOptionsFromXenditChannels(rawChannels);

        if (!mounted) {
          return;
        }

        if (channels.length > 0) {
          setAvailableBanks(channels);
          logWithdrawalClient(requestId, "channel-fetch-success", {
            totalChannels: channels.length,
            channelCodes: channels.map((channel) => channel.code),
          });
          logWithdrawalClient(requestId, "channel-filtered-by-country-success", {
            country: "ID",
            totalFetchedChannels: rawChannels.length,
            totalFilteredChannels: channels.length,
            filteredChannelCodes: channels.map((channel) => channel.code),
          });
        } else {
          setAvailableBanks([]);
          setChannelLoadError("No payout channels available");
          warnWithdrawalClient(requestId, "channel-fetch-empty-no-fallback");
        }
      } catch (error) {
        if (!mounted) {
          return;
        }
        setAvailableBanks([]);
        setChannelLoadError(
          error instanceof Error && error.message ? error.message : CHANNEL_DEFAULT_ERROR_MESSAGE,
        );
        warnWithdrawalClient(requestIdRef.current, "channel-fetch-failed-no-fallback", {
          error: error instanceof Error ? error.message : String(error),
        });
      } finally {
        if (mounted) {
          setIsLoadingChannels(false);
        }
      }
    };

    fetchDynamicChannels();

    return () => {
      mounted = false;
    };
  }, []);

  // Handle TNC scroll - enable checkbox when scrolled to bottom (user must manually check)
  const handleTermsScroll = (e: React.UIEvent<HTMLDivElement>) => {
    if (!hasTermsContent) return;

    if (hasReachedTermsEnd(e.currentTarget)) {
      setHasReadTerms(true);
      // Only enable checkbox, don't auto-check - user must manually check
      setCanAcceptTerms(true);
    }
  };

  const handleTermsContentReady = (container: HTMLDivElement) => {
    if (!hasTermsContent) return;

    if (hasReachedTermsEnd(container)) {
      setHasReadTerms(true);
      setCanAcceptTerms(true);
    }
  };

  const handleTermsClose = () => {
    setConfirmationAgreed(false);
    setCanAcceptTerms(false);
    setShowTerms(false);
  };

  const handleTermsAgree = () => {
    setHasReadTerms(true);
    setCanAcceptTerms(true);
    setConfirmationAgreed(true);
    setShowTerms(false);
  };

  const validateMinWithdrawal = (value: number) => {
    // Always validate minimum withdrawal
    if (value <= minWithdrawalAmount) {
      setAmountError(
        `Minimum withdrawal allowed is above ${currencyToSymbol(currency)} ${minWithdrawalAmount.toLocaleString("id-ID")}`,
      );
      return;
    }
    // Clear error if amount is valid
    setAmountError(null);
  };

  useEffect(() => {
    if (withdrawAll) {
      // When withdrawing all, amount should be balance minus admin fee
      // to ensure total (amount + admin fee) doesn't exceed balance
      const maxWithdrawableAmount = Math.max(0, currentBalance);
      setAmount(maxWithdrawableAmount);
      setDisplayAmount(maxWithdrawableAmount.toLocaleString("id-ID"));
      validateMinWithdrawal(maxWithdrawableAmount);
    }
  }, [withdrawAll, currentBalance]);

  useEffect(() => {
    // Set default user data if available
    if (initialProfile) {
      const fullNameValue =
        `${initialProfile.firstname || ""} ${initialProfile.lastname || ""}`.trim();
      if (fullNameValue) {
        setFullName(fullNameValue);
        setAccountHolderName(fullNameValue);
      }
      if (initialProfile.email) {
        setEmail(initialProfile.email);
      }
      if (initialProfile.phone) {
        setPhoneNumber(initialProfile.phone);
      }
    }
  }, [initialProfile]);

  const handleAmountClick = (predefinedAmount: number) => {
    setAmount(predefinedAmount);
    setDisplayAmount(predefinedAmount.toLocaleString("id-ID"));
    setWithdrawAll(false);
    validateMinWithdrawal(predefinedAmount);
  };

  const handleCustomAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    const rawValue = value.replace(/\D/g, "");
    const numericValue = Number(rawValue);

    const formattedValue = rawValue ? numericValue.toLocaleString("id-ID") : "";
    setDisplayAmount(formattedValue);
    setWithdrawAll(false);

    if (rawValue) {
      setAmount(numericValue);
      validateMinWithdrawal(numericValue);
    } else {
      setAmount(predefinedAmounts[0]);
      validateMinWithdrawal(predefinedAmounts[0]);
    }
  };

  const handleCustomAmountBlur = () => {
    if (amount !== undefined && !isNaN(amount)) {
      if (amount === 0) {
        setDisplayAmount("");
      } else {
        setDisplayAmount(amount.toLocaleString("id-ID"));
      }
      validateMinWithdrawal(amount);
    } else {
      setDisplayAmount("");
    }
  };

  const handleWithdrawAllToggle = (checked: boolean) => {
    setWithdrawAll(checked);
    if (checked) {
      // When withdrawing all, amount should be balance minus admin fee
      // to ensure total (amount + admin fee) doesn't exceed balance
      const maxWithdrawableAmount = Math.max(0, currentBalance);
      setAmount(maxWithdrawableAmount);
      setDisplayAmount(maxWithdrawableAmount.toLocaleString("id-ID"));
      validateMinWithdrawal(maxWithdrawableAmount);
    } else {
      // Reset to first predefined amount when unchecking
      setAmount(predefinedAmounts[0]);
      setDisplayAmount(predefinedAmounts[0].toLocaleString("id-ID"));
      validateMinWithdrawal(predefinedAmounts[0]);
    }
  };

  const buildWithdrawalFormData = (code?: string) => {
    const formData = new FormData();
    formData.append("amount", amount.toString());
    formData.append("fullName", fullName.trim());
    formData.append("phoneNumber", phoneNumber.trim());
    formData.append("email", email.trim());
    formData.append("bankName", bankName);
    formData.append("accountNumber", accountNumber.trim());
    formData.append("accountHolderName", accountHolderName.trim());
    formData.append("confirmationAgreed", confirmationAgreed.toString());
    formData.append("requestId", requestIdRef.current);
    if (code) {
      formData.append("otpCode", code);
    }
    return formData;
  };

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const requestId = requestIdRef.current;

    logWithdrawalClient(requestId, "submit-clicked", {
      amount,
      currentBalance,
      bankName,
      accountNumberMasked: maskAccountNumber(accountNumber),
      confirmationAgreed,
      hasPendingWithdrawal,
    });

    // Check if user has pending withdrawal request
    if (hasPendingWithdrawal) {
      warnWithdrawalClient(requestId, "validation-failed", { reason: "has-pending-withdrawal" });
      toast.error(
        "You already have a pending withdrawal request. Please wait until it is finalized before submitting a new request.",
      );
      return;
    }

    // Validation
    if (amount === undefined || isNaN(amount) || amount <= 0) {
      warnWithdrawalClient(requestId, "validation-failed", { reason: "invalid-amount", amount });
      toast.error("Please enter a valid withdrawal amount.");
      return;
    }

    if (enforceMinWithdrawal && amount <= minWithdrawalAmount) {
      warnWithdrawalClient(requestId, "validation-failed", {
        reason: "amount-below-minimum",
        amount,
        minWithdrawalAmount,
      });
      setAmountError(
        `Minimum withdrawal allowed is above ${currencyToSymbol(currency)} ${minWithdrawalAmount.toLocaleString("id-ID")}`,
      );
      requestAnimationFrame(() => {
        amountInputRef.current?.focus();
        amountInputRef.current?.scrollIntoView({ behavior: "smooth", block: "center" });
      });
      return;
    }

    // Check if total amount (withdrawal + admin fee) exceeds balance
    const totalNeeded = amount;
    if (totalNeeded > currentBalance) {
      warnWithdrawalClient(requestId, "validation-failed", {
        reason: "amount-exceeds-balance",
        totalNeeded,
        currentBalance,
      });
      toast.error(
        `Insufficient balance. You need ${formatBalanceCurrency(totalNeeded, currency)} (withdrawal amount), but your balance is only ${formatBalanceCurrency(currentBalance, currency)}.`,
      );
      return;
    }

    // Validate user profile data (fullName, email, phoneNumber are from profile)
    if (!fullName || fullName.trim() === "") {
      warnWithdrawalClient(requestId, "validation-failed", { reason: "missing-full-name" });
      toast.error("Full name is required. Please update your profile.");
      return;
    }

    if (!phoneNumber || phoneNumber.trim() === "") {
      warnWithdrawalClient(requestId, "validation-failed", { reason: "missing-phone-number" });
      toast.error("Phone number is required. Please update your profile.");
      return;
    }

    if (!email || email.trim() === "") {
      warnWithdrawalClient(requestId, "validation-failed", { reason: "missing-email" });
      toast.error("Email is required. Please update your profile.");
      return;
    }

    if (!bankName || bankName.trim() === "") {
      warnWithdrawalClient(requestId, "validation-failed", { reason: "missing-bank-name" });
      toast.error("Please select a withdrawal channel.");
      return;
    }

    if (!accountNumber || accountNumber.trim() === "") {
      warnWithdrawalClient(requestId, "validation-failed", { reason: "missing-account-number" });
      toast.error("Please enter account number.");
      return;
    }

    if (!accountHolderName || accountHolderName.trim() === "") {
      warnWithdrawalClient(requestId, "validation-failed", {
        reason: "missing-account-holder-name",
      });
      toast.error("Please enter account holder name.");
      return;
    }

    if (!hasTermsContent) {
      warnWithdrawalClient(requestId, "validation-failed", { reason: "terms-unavailable" });
      toast.error("Withdrawal Terms and Conditions are currently unavailable. Please try again later.");
      return;
    }

    if (!confirmationAgreed) {
      warnWithdrawalClient(requestId, "validation-failed", { reason: "confirmation-not-agreed" });
      toast.error("Please confirm the terms to continue.");
      return;
    }

    logWithdrawalClient(requestId, "validation-passed-request-otp");
    setIsRequestingOtp(true);
    setOtpCode("");
    setOtpError(null);
    try {
      const result = await requestWithdrawalOTP(buildWithdrawalFormData());
      logWithdrawalClient(requestId, "request-otp-response", {
        success: result.success,
        message: result.message || null,
        error: result.error || null,
      });

      if (!result.success) {
        toast.error(result.error || "Failed to send withdrawal OTP. Please try again.");
        return;
      }

      toast.success(result.message || withdrawalOtpCopy.sentToast);
      setIsConfirmModalOpen(true);
    } catch (error) {
      errorWithdrawalClient(requestId, "request-otp-exception", {
        error: error instanceof Error ? error.message : String(error),
      });
      toast.error("Failed to send withdrawal OTP. Please try again.");
    } finally {
      setIsRequestingOtp(false);
    }
  };

  const handleConfirmWithdrawal = () => {
    const requestId = requestIdRef.current;
    const normalizedOtp = otpCode.trim();
    if (!/^\d{6}$/.test(normalizedOtp)) {
      setOtpError(withdrawalOtpCopy.invalidCode);
      return;
    }
    const formData = buildWithdrawalFormData(normalizedOtp);

    logWithdrawalClient(requestId, "confirm-submit-start", {
      amount,
      bankName,
      accountNumberMasked: maskAccountNumber(accountNumber),
      accountHolderName,
      hasOtpCode: true,
    });

    startTransition(async () => {
      try {
        setIsConfirmModalOpen(false);
        setTerminalTransactionStatus(null);
        setPayoutTrackingError(null);
        setPayoutTrackingPhase("IDLE");
        setWithdrawalTransactionId("");
        const result = await createWithdrawal(formData);
        logWithdrawalClient(requestId, "confirm-submit-response", {
          success: result.success,
          message: result.message || null,
          error: result.error || null,
          transactionId: result.transactionId || null,
          transactionStatus: result.transactionStatus || null,
        });

        if (result.success) {
          const transactionId = extractCreatedWithdrawalTransactionId(result);
          if (!transactionId) {
            warnWithdrawalClient(requestId, "tracking-unavailable-no-transaction-id");
            setPayoutTrackingPhase("FAILED");
            setPayoutTrackingError(
              "Withdrawal request sudah dibuat, tapi transaction ID tidak ditemukan untuk tracking otomatis. Silakan cek halaman wallet/transactions.",
            );
            setIsPayoutStatusModalOpen(true);
            return;
          }

          setWithdrawalTransactionId(transactionId);
          setPayoutTrackingPhase("PROCESSING");
          setPayoutTrackingError(null);
          setTerminalTransactionStatus(null);
          setIsPayoutStatusModalOpen(true);
          setHasPendingWithdrawal(true);
          setOtpCode("");
          setOtpError(null);
          requestIdRef.current = generateRequestId();
        } else {
          warnWithdrawalClient(requestId, "confirm-submit-failed", {
            error: result.error || "unknown",
          });
          setPayoutTrackingPhase("FAILED");
          setPayoutTrackingError(
            result.error || "Failed to submit withdrawal request. Please try again.",
          );
          setIsPayoutStatusModalOpen(true);
        }
      } catch (error) {
        errorWithdrawalClient(requestId, "confirm-submit-exception", {
          error: error instanceof Error ? error.message : String(error),
        });
        setPayoutTrackingPhase("FAILED");
        setPayoutTrackingError(
          "Failed to submit withdrawal request. An unexpected error occurred.",
        );
        setIsPayoutStatusModalOpen(true);
      }
    });
  };

  const resetPayoutTrackingState = () => {
    setPayoutTrackingPhase("IDLE");
    setWithdrawalTransactionId("");
    setTerminalTransactionStatus(null);
    setPayoutTrackingError(null);
  };

  const handlePayoutStatusModalClose = () => {
    if (payoutTrackingPhase === "PROCESSING") {
      return;
    }

    const shouldHardRefreshAfterClose = payoutTrackingPhase === "FAILED";
    setIsPayoutStatusModalOpen(false);
    releaseModalScrollLock();

    if (withdrawalTransactionId && payoutTrackingPhase === "SUCCESS") {
      resetPayoutTrackingState();
      router.push(`/transactions/${withdrawalTransactionId}`);
      return;
    }

    resetPayoutTrackingState();

    if (shouldHardRefreshAfterClose && typeof window !== "undefined") {
      window.location.reload();
    }
  };

  const goToWithdrawalTransactionDetail = () => {
    if (!withdrawalTransactionId) {
      return;
    }

    const targetTransactionId = withdrawalTransactionId;
    setIsPayoutStatusModalOpen(false);
    resetPayoutTrackingState();
    releaseModalScrollLock();

    if (typeof window !== "undefined") {
      window.location.assign(`/transactions/${targetTransactionId}`);
      return;
    }

    router.push(`/transactions/${targetTransactionId}`);
  };

  const goToWalletPage = () => {
    setIsPayoutStatusModalOpen(false);
    resetPayoutTrackingState();
    releaseModalScrollLock();

    if (typeof window !== "undefined") {
      window.location.assign("/wallet");
      return;
    }

    router.push("/wallet");
  };

  const totalAmount = amount - ADMIN_FEE;
  const selectedBank = availableBanks.find((bank) => bank.code === bankName);

  return (
    <div>
      <ClientOnly>
        <form ref={formRef} onSubmit={handleSubmit}>
          {/* Balance Display */}
          <div className="mb-8">
            <Typography variant="s2" className="mb-2 font-medium text-black/70 dark:text-white/70">
              Available Balance
            </Typography>
            <Typography
              variant="h1"
              className="text-3xl lg:text-4xl font-bold text-black dark:text-white"
            >
              {formatBalanceCurrency(currentBalance, currency)}
            </Typography>
          </div>

          {/* Amount Input */}
          <div className="mb-6">
            <Typography variant="s1" className="mb-2 font-bold text-black dark:text-white">
              Enter amount
            </Typography>
            <div className="relative">
              <Typography
                variant="h3"
                className={`absolute left-4 top-1/2 -translate-y-1/2 font-normal ${
                  isBelowMin || amount > currentBalance
                    ? "text-red-600 dark:text-red-400"
                    : "text-gray-800 dark:text-white/90"
                }`}
              >
                {currencyToSymbol(currency)}
              </Typography>
              <input
                id="customAmount"
                type="text"
                ref={amountInputRef}
                value={displayAmount}
                onChange={handleCustomAmountChange}
                onBlur={handleCustomAmountBlur}
                disabled={withdrawAll}
                placeholder="e.g., 65.000"
                className={`
                  w-full py-2.5 pl-18 max-md:pr-14 focus:outline-hidden focus:ring-0
                  border-b-2
                  ${
                    isBelowMin || amount > currentBalance
                      ? "border-red-500 focus:border-red-500 text-red-600 placeholder:text-red-300 dark:text-red-400 dark:placeholder:text-red-300"
                      : "border-gray-300 dark:border-gray-700 text-gray-800 placeholder:text-gray-400 focus:border-brand-500 dark:focus:border-brand-500 dark:text-white/90 dark:placeholder:text-white/30"
                  }
                  dark:bg-white/[0.03]
                  transition-all duration-200 ease-in-out
                  text-2xl lg:text-5xl overflow-auto text-center
                  placeholder:font-normal
                  ${withdrawAll ? "opacity-50 cursor-not-allowed" : ""}
                `}
              />
            </div>
            {amountError && (
              <Typography variant="b2" className="mt-2 text-sm text-red-600 dark:text-red-400">
                {amountError}
              </Typography>
            )}
            {amount > currentBalance && !amountError && (
              <Typography variant="b2" className="mt-2 text-sm text-red-600 dark:text-red-400">
                Amount exceeds available balance.
              </Typography>
            )}
          </div>

          {/* Quick Select Amounts */}
          <div className="mb-4 flex flex-wrap gap-2">
            {predefinedAmounts.map((predefinedAmount) => (
              <button
                key={predefinedAmount}
                type="button"
                onClick={() => handleAmountClick(predefinedAmount)}
                className={`
                  px-4 py-2 rounded-lg border transition-all duration-200
                  ${
                    amount === predefinedAmount && !withdrawAll
                      ? "border-brand-500 bg-brand-50 dark:bg-brand-900/20 text-brand-600 dark:text-brand-400"
                      : "border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700"
                  }
                `}
              >
                {formatBalanceCurrency(predefinedAmount, currency)}
              </button>
            ))}
          </div>

          {/* Withdraw All Toggle */}
          <div className="mb-8 flex justify-end">
            <label
              className={`flex items-center space-x-3 ${currentBalance < ADMIN_FEE ? "cursor-not-allowed opacity-50" : "cursor-pointer"}`}
            >
              <Typography
                variant="b2"
                className="font-medium text-gray-900 dark:text-white"
                style={{ fontSize: "14px" }}
              >
                Withdraw all balance
                {currentBalance < ADMIN_FEE && (
                  <span className="ml-2 text-xs text-red-600 dark:text-red-400">
                    (Balance insufficient for admin fee)
                  </span>
                )}
              </Typography>
              <input
                type="checkbox"
                checked={withdrawAll}
                onChange={(e) => handleWithdrawAllToggle(e.target.checked)}
                disabled={currentBalance < ADMIN_FEE}
                className="w-5 h-5 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 disabled:opacity-50 disabled:cursor-not-allowed"
              />
            </label>
          </div>

          {/* Bank Account Section */}
          <div className="mt-8 space-y-6">
            <Typography variant="s1" className="mb-4 font-bold text-black dark:text-white">
              Destination Account
            </Typography>

            <div className="space-y-4">
              {/* Bank Selection */}
              <div>
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
                  Withdrawal Channel <span className="text-red-500">*</span>
                </label>
                <div className="relative">
                  <select
                    value={bankName}
                    onChange={(e) => setBankName(e.target.value)}
                    className="w-full appearance-none px-4 py-2.5 pr-10 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-brand-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
                    required
                    disabled={isLoadingChannels || availableBanks.length === 0}
                  >
                    <option value="">
                      {isLoadingChannels ? "Loading channels..." : "Select withdrawal channel"}
                    </option>
                    {availableBanks.map((bank) => (
                      <option key={bank.id} value={bank.code}>
                        {bank.name}
                      </option>
                    ))}
                  </select>
                  <ChevronDown className="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-500 dark:text-gray-300" />
                </div>
                {channelLoadError && (
                  <Typography
                    variant="b2"
                    className="mt-2 text-xs text-orange-700 dark:text-orange-300"
                  >
                    {channelLoadError}
                  </Typography>
                )}
              </div>

              {/* Account Number */}
              <div>
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
                  Account Number <span className="text-red-500">*</span>
                </label>
                <input
                  type="text"
                  value={accountNumber}
                  onChange={(e) => setAccountNumber(e.target.value.replace(/\D/g, ""))}
                  placeholder="Enter account number"
                  className="w-full px-4 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-brand-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
                  required
                />
              </div>

              {/* Account Holder Name */}
              <div>
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
                  Account Holder Name <span className="text-red-500">*</span>
                </label>
                <input
                  type="text"
                  value={accountHolderName}
                  onChange={(e) => setAccountHolderName(e.target.value)}
                  placeholder="Enter account holder name"
                  className="w-full px-4 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-brand-500 focus:border-transparent dark:bg-gray-700 dark:text-white"
                  required
                />
              </div>
            </div>
          </div>

          {/* Confirmation Checkbox */}
          <div className="mt-4 p-4 bg-orange-50 dark:bg-orange-900/10 border border-orange-200 dark:border-orange-800/50 rounded-lg">
            <div className="flex items-start gap-3">
              <Checkbox
                checked={confirmationAgreed}
                onChange={setConfirmationAgreed}
                disabled={hasPendingWithdrawal || !hasTermsContent || !canAcceptTerms}
              />
              <p className="text-sm text-gray-800 dark:text-gray-200">
                I have read and agree to the{" "}
                <button
                  type="button"
                  className="text-brand-600 dark:text-brand-400 underline hover:text-brand-700 dark:hover:text-brand-300 focus:outline-none"
                  onClick={() => {
                    if (!hasReadTerms) {
                      setConfirmationAgreed(false);
                      setCanAcceptTerms(false);
                    }
                    setShowTerms(true);
                  }}
                >
                  Terms and Conditions
                </button>
                <span className="text-red-500">*</span>
              </p>
            </div>
          </div>

          {/* Pending Withdrawal Warning */}
          {hasPendingWithdrawal && (
            <div className="mt-4 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg">
              <Typography variant="b2" className="text-red-800 dark:text-red-200 font-medium">
                You already have a pending withdrawal request. Please wait until it is finalized
                before submitting a new request.
              </Typography>
            </div>
          )}

          {/* Amount Summary */}
          <div className="mt-6 p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
            <div className="space-y-2">
              <div className="flex justify-between items-center">
                <Typography variant="b2" className="text-gray-600 dark:text-gray-400">
                  Withdrawal Amount:
                </Typography>
                <Typography variant="b1" className="font-semibold text-black dark:text-white">
                  {formatBalanceCurrency(amount, currency)}
                </Typography>
              </div>
              <div className="flex justify-between items-center">
                <Typography variant="b2" className="text-gray-600 dark:text-gray-400">
                  Admin Fee:
                </Typography>
                <Typography variant="b1" className="font-semibold text-black dark:text-white">
                  {formatBalanceCurrency(ADMIN_FEE, currency)}
                </Typography>
              </div>
              <div className="flex justify-between items-center pt-2 border-t border-gray-200 dark:border-gray-700">
                <Typography variant="s1" className="font-bold text-black dark:text-white">
                  Amount Received:
                </Typography>
                <Typography variant="s1" className="font-bold text-brand-600 dark:text-brand-400">
                  {formatBalanceCurrency(totalAmount, currency)}
                </Typography>
              </div>
            </div>
          </div>

          {/* Submit Button */}
          <div className="mt-8">
            <Button
              type="submit"
              variant="primary"
              size="md"
              disabled={
                amount <= 0 ||
                amount > currentBalance ||
                !fullName ||
                !phoneNumber ||
                !email ||
                !bankName ||
                !accountNumber ||
                !accountHolderName ||
                !hasTermsContent ||
                !confirmationAgreed ||
                hasPendingWithdrawal ||
                isLoadingChannels ||
                isRequestingOtp ||
                isPending ||
                payoutTrackingPhase === "PROCESSING" ||
                isCheckingPending
              }
              className="w-full justify-center text-lg font-bold bg-brand-500 text-white hover:bg-brand-600 disabled:bg-gray-400 dark:bg-brand-500 dark:hover:bg-brand-600 dark:disabled:bg-gray-600"
            >
              {isCheckingPending
                ? "Checking..."
                : hasPendingWithdrawal
                  ? "Pending Request Exists"
                  : payoutTrackingPhase === "PROCESSING"
                    ? "Processing Payout..."
                    : isRequestingOtp
                      ? "Sending OTP..."
                      : isPending
                        ? "Submitting..."
                        : "Submit Withdrawal Request"}
            </Button>
          </div>
        </form>
      </ClientOnly>

      {/* Confirmation Modal */}
      <Modal
        isOpen={isConfirmModalOpen}
        onClose={() => {
          setIsConfirmModalOpen(false);
          setOtpError(null);
        }}
        className="max-w-md mx-auto p-6 rounded-xl shadow-lg dark:bg-gray-900"
      >
        <div className="text-center text-black dark:text-white">
          <h2 className="mb-2 text-2xl font-bold text-brand-500">Withdrawal Confirmation</h2>
          <p className="text-sm text-gray-500 dark:text-gray-400 mb-6">
            {new Date().toLocaleDateString("id-ID", {
              day: "2-digit",
              month: "long",
              year: "numeric",
            })}{" "}
            at{" "}
            {new Date().toLocaleTimeString("id-ID", {
              hour: "2-digit",
              minute: "2-digit",
              hour12: false,
            })}
          </p>

          <div className="pt-4 space-y-4 mb-8 text-left">
            <div className="flex justify-between items-center">
              <Typography variant="b2" className="text-gray-600 dark:text-gray-300">
                Bank:
              </Typography>
              <Typography variant="s1" className="font-semibold text-black dark:text-white">
                {selectedBank?.name || bankName}
              </Typography>
            </div>
            <div className="flex justify-between items-center">
              <Typography variant="b2" className="text-gray-600 dark:text-gray-300">
                Account Number:
              </Typography>
              <Typography variant="s1" className="font-semibold text-black dark:text-white">
                {accountNumber}
              </Typography>
            </div>
            <div className="flex justify-between items-center">
              <Typography variant="b2" className="text-gray-600 dark:text-gray-300">
                Account Holder:
              </Typography>
              <Typography variant="s1" className="font-semibold text-black dark:text-white">
                {accountHolderName}
              </Typography>
            </div>
            <div className="flex justify-between items-center pt-2 border-t border-gray-200 dark:border-gray-700">
              <Typography variant="b2" className="text-gray-600 dark:text-gray-300">
                Amount:
              </Typography>
              <Typography variant="s1" className="font-semibold text-lg text-black dark:text-white">
                {formatBalanceCurrency(amount, currency)}
              </Typography>
            </div>
            <div className="flex justify-between items-center">
              <Typography variant="b2" className="text-gray-600 dark:text-gray-300">
                Admin Fee:
              </Typography>
              <Typography variant="s1" className="font-semibold text-black dark:text-white">
                {formatBalanceCurrency(ADMIN_FEE, currency)}
              </Typography>
            </div>
            <div className="flex justify-between items-center pt-2 border-t border-gray-200 dark:border-gray-700">
              <Typography variant="b1" className="font-bold text-black dark:text-white">
                Total:
              </Typography>
              <Typography
                variant="s1"
                className="font-bold text-lg text-brand-600 dark:text-brand-400"
              >
                {formatBalanceCurrency(totalAmount, currency)}
              </Typography>
            </div>
          </div>

          <p className="pt-4 text-sm text-gray-600 dark:text-gray-400 mb-4">
            {withdrawalOtpCopy.instructions}
          </p>

          <div className="mb-5 text-left">
            <label
              htmlFor="withdrawal-otp-code"
              className="mb-2 block text-sm font-semibold text-gray-700 dark:text-gray-200"
            >
              {withdrawalOtpCopy.label}
            </label>
            <input
              id="withdrawal-otp-code"
              type="text"
              inputMode="numeric"
              autoComplete="one-time-code"
              value={otpCode}
              onChange={(event) => {
                const nextValue = event.target.value.replace(/\D/g, "").slice(0, 6);
                setOtpCode(nextValue);
                if (otpError) {
                  setOtpError(null);
                }
              }}
              placeholder="123456"
              className="w-full rounded-lg border border-gray-300 px-4 py-3 text-center text-lg font-semibold tracking-[0.4em] text-black outline-none focus:border-brand-500 focus:ring-2 focus:ring-brand-100 dark:border-gray-700 dark:bg-gray-800 dark:text-white dark:focus:ring-brand-900/30"
            />
            {otpError && (
              <p className="mt-2 text-sm font-medium text-red-600 dark:text-red-400">{otpError}</p>
            )}
          </div>

          <div className="flex flex-col gap-3">
            <Button
              type="button"
              onClick={handleConfirmWithdrawal}
              variant="primary"
              className="w-full justify-center rounded-md px-6 py-3 bg-brand-500 text-white hover:bg-brand-600 text-lg font-semibold"
              disabled={otpCode.length !== 6 || isPending || payoutTrackingPhase === "PROCESSING"}
            >
              {isPending || payoutTrackingPhase === "PROCESSING"
                ? "Submitting..."
                : "Confirm & Submit"}
            </Button>
            <Button
              type="button"
              onClick={() => setIsConfirmModalOpen(false)}
              variant="outline"
              className="w-full justify-center rounded-md px-6 py-3 border border-slate-300 text-red-600 dark:border-strokedark dark:text-red-400 hover:bg-slate-100 dark:hover:bg-gray-800 text-lg font-semibold"
            >
              Cancel
            </Button>
          </div>
        </div>
      </Modal>

      {/* Payout Tracking Modal */}
      <Modal
        isOpen={isPayoutStatusModalOpen}
        onClose={handlePayoutStatusModalClose}
        showCloseButton={payoutTrackingPhase !== "PROCESSING"}
        className="max-w-md mx-auto p-6 rounded-xl shadow-lg dark:bg-gray-900"
      >
        <div className="text-center text-black dark:text-white">
          {payoutTrackingPhase === "PROCESSING" && (
            <>
              <div className="mx-auto mb-5 h-16 w-16 rounded-full border-4 border-brand-100 border-t-brand-500 animate-spin dark:border-brand-900/30" />
              <h2 className="mb-2 text-2xl font-bold text-brand-500">Processing Payout</h2>
              <p className="mb-3 text-sm text-gray-600 dark:text-gray-300">
                Mohon tunggu, kami sedang menunggu konfirmasi pembayaran withdrawal Anda.
              </p>
              <p className="mb-1 text-xs text-gray-500 dark:text-gray-400">Transaction ID</p>
              <p className="mb-4 break-all font-mono text-xs text-gray-700 dark:text-gray-300">
                {withdrawalTransactionId || "-"}
              </p>
              {payoutTrackingError && (
                <p className="rounded-lg bg-yellow-50 px-3 py-2 text-xs text-yellow-700 dark:bg-yellow-900/20 dark:text-yellow-300">
                  {payoutTrackingError}
                </p>
              )}
            </>
          )}

          {payoutTrackingPhase === "SUCCESS" && (
            <>
              <div className="mx-auto mb-5 flex h-16 w-16 items-center justify-center rounded-full bg-green-100 text-green-600 dark:bg-green-900/30 dark:text-green-300">
                <svg className="h-9 w-9" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth={2}
                    d="M5 13l4 4L19 7"
                  />
                </svg>
              </div>
              <h2 className="mb-2 text-2xl font-bold text-green-600 dark:text-green-300">
                Withdrawal Paid
              </h2>
              <p className="mb-5 text-sm text-gray-600 dark:text-gray-300">
                Withdrawal Anda sudah berhasil dibayar.
              </p>
              <div className="flex flex-col gap-3">
                <Button
                  type="button"
                  variant="primary"
                  className="w-full justify-center rounded-md px-6 py-3 text-lg font-semibold"
                  onClick={goToWithdrawalTransactionDetail}
                >
                  View Transaction Detail
                </Button>
                <Button
                  type="button"
                  variant="outline"
                  className="w-full justify-center rounded-md px-6 py-3 border border-slate-300 text-black dark:border-strokedark dark:text-white hover:bg-slate-100 dark:hover:bg-gray-800 text-lg font-semibold"
                  onClick={goToWalletPage}
                >
                  Back to Wallet
                </Button>
              </div>
            </>
          )}

          {payoutTrackingPhase === "FAILED" && (
            <>
              <div className="mx-auto mb-5 flex h-16 w-16 items-center justify-center rounded-full bg-red-100 text-red-600 dark:bg-red-900/30 dark:text-red-300">
                <svg className="h-9 w-9" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth={2}
                    d="M6 18L18 6M6 6l12 12"
                  />
                </svg>
              </div>
              <h2 className="mb-2 text-2xl font-bold text-red-600 dark:text-red-300">
                Withdrawal Failed
              </h2>
              <p className="mb-2 text-sm text-gray-600 dark:text-gray-300">
                {payoutTrackingError || "Withdrawal payout gagal diproses."}
              </p>
              {terminalTransactionStatus && (
                <p className="mb-5 text-xs text-gray-500 dark:text-gray-400">
                  Final status: {terminalTransactionStatus}
                </p>
              )}
              <div className="flex flex-col gap-3">
                {withdrawalTransactionId && (
                  <Button
                    type="button"
                    variant="primary"
                    className="w-full justify-center rounded-md px-6 py-3 text-lg font-semibold"
                    onClick={goToWithdrawalTransactionDetail}
                  >
                    View Transaction Detail
                  </Button>
                )}
                <Button
                  type="button"
                  variant="outline"
                  className="w-full justify-center rounded-md px-6 py-3 border border-slate-300 text-black dark:border-strokedark dark:text-white hover:bg-slate-100 dark:hover:bg-gray-800 text-lg font-semibold"
                  onClick={handlePayoutStatusModalClose}
                >
                  Close
                </Button>
              </div>
            </>
          )}
        </div>
      </Modal>

      {/* Terms and Conditions Modal */}
      <ModalTnC
        isOpen={showTerms}
        onClose={handleTermsClose}
        onAgree={handleTermsAgree}
        onScroll={handleTermsScroll}
        onContentReady={handleTermsContentReady}
        title={withdrawalTnC?.title || "Terms and Conditions"}
        body={withdrawalTnC?.body}
      />
    </div>
  );
};
