import { useState, useCallback, useRef } from "react";
import { useNavigate } from "react-router-dom";
import { toast } from "@medusajs/ui";

import { useCreateSellerAccount, useLogout } from "@hooks/api";
import { queryClient } from "@lib/query-client";
import { TOTAL_STEPS } from "../constants";

type StoreData = {
  name: string;
  email: string;
  phone?: string;
  currency_code: string;
  description?: string;
  handle?: string;
};

type AddressData = {
  name?: string;
  address_1?: string;
  address_2?: string;
  postal_code?: string;
  city?: string;
  country_code: string;
  province?: string;
};

type CompanyData = {
  corporate_name?: string;
  registration_number?: string;
  tax_id?: string;
  [key: string]: unknown;
};

const KNOWN_COMPANY_KEYS = new Set([
  "corporate_name",
  "registration_number",
  "tax_id",
]);

type PaymentData = {
  country_code: string;
  holder_name: string;
  iban?: string;
  bic?: string;
  routing_number?: string;
  account_number?: string;
};

export const useOnboarding = (memberEmail: string) => {
  const navigate = useNavigate();
  const [currentStep, setCurrentStep] = useState(0);
  const [isSubmitting, setIsSubmitting] = useState(false);

  const sellerIdRef = useRef<string | null>(null);
  const [sellerIdState, setSellerIdState] = useState<string | null>(null);

  const setSellerId = (id: string) => {
    sellerIdRef.current = id;
    setSellerIdState(id);
  };

  const storeDataRef = useRef<StoreData | null>(null);
  const addressDataRef = useRef<AddressData | null>(null);
  const companyDataRef = useRef<CompanyData | null>(null);

  const { mutateAsync: createSeller, isPending: isCreating } =
    useCreateSellerAccount();
  const { mutateAsync: logout } = useLogout();

  const isPending = isCreating || isSubmitting;

  // Step 1: Store — save locally
  const submitStoreStep = useCallback(async (data: StoreData) => {
    storeDataRef.current = data;
    setCurrentStep(1);
  }, []);

  // Step 2: Address — save locally
  const submitAddressStep = useCallback(async (data: AddressData) => {
    addressDataRef.current = data;
    setCurrentStep(2);
  }, []);

  const skipAddressStep = useCallback(() => {
    addressDataRef.current = null;
    setCurrentStep(2);
  }, []);

  // Step 3: Company — save locally
  const submitCompanyStep = useCallback(async (data: CompanyData) => {
    companyDataRef.current = data;
    setCurrentStep(3);
  }, []);

  const skipCompanyStep = useCallback(() => {
    companyDataRef.current = null;
    setCurrentStep(3);
  }, []);

  /**
   * Creates seller with ALL collected data (Steps 1-4) in one API call.
   * This goes through POST /vendor/sellers which is unauthenticated —
   * no seller_context needed, no session issues.
   */
  const createSellerWithAllData = useCallback(
    async (paymentData?: PaymentData) => {
      const storeData = storeDataRef.current;
      if (!storeData) return;

      // Already created (user went back and forward)
      if (sellerIdRef.current) {
        navigate("/store-select", { replace: true });
        return;
      }

      const addressData = addressDataRef.current;
      const companyData = companyDataRef.current;
      const hasCompanyData =
        companyData?.corporate_name ||
        companyData?.registration_number ||
        companyData?.tax_id;

      const companyExtras = companyData
        ? Object.fromEntries(
            Object.entries(companyData).filter(
              ([key, value]) =>
                !KNOWN_COMPANY_KEYS.has(key) &&
                value !== undefined &&
                value !== "",
            ),
          )
        : {};
      const hasCompanyExtras = Object.keys(companyExtras).length > 0;

      const isUS = paymentData?.country_code === "us";

      let registerDraft: { first_name?: string; last_name?: string } = {};
      try {
        const raw = sessionStorage.getItem("mercur_register_draft");
        if (raw) {
          const parsed = JSON.parse(raw);
          registerDraft = {
            first_name: parsed.first_name || undefined,
            last_name: parsed.last_name || undefined,
          };
        }
      } catch {
        // Ignore malformed draft
      }

      try {
        setIsSubmitting(true);

        const result = await createSeller({
          name: storeData.name,
          handle: storeData.handle || undefined,
          email: storeData.email,
          phone: storeData.phone || undefined,
          member_email: memberEmail,
          first_name: registerDraft.first_name,
          last_name: registerDraft.last_name,
          currency_code: storeData.currency_code.toLowerCase(),
          description: storeData.description || undefined,
          address: addressData
            ? {
                name: addressData.name || undefined,
                address_1: addressData.address_1 || undefined,
                address_2: addressData.address_2 || undefined,
                postal_code: addressData.postal_code || undefined,
                city: addressData.city || undefined,
                country_code: addressData.country_code,
                province: addressData.province || undefined,
              }
            : undefined,
          professional_details: hasCompanyData
            ? {
                corporate_name: companyData!.corporate_name || undefined,
                registration_number:
                  companyData!.registration_number || undefined,
                tax_id: companyData!.tax_id || undefined,
              }
            : undefined,
          payment_details: paymentData
            ? {
                country_code: paymentData.country_code,
                holder_name: paymentData.holder_name,
                iban: isUS ? null : paymentData.iban || null,
                bic: isUS ? null : paymentData.bic || null,
                routing_number: isUS
                  ? paymentData.routing_number || null
                  : null,
                account_number: paymentData.account_number || null,
              }
            : undefined,
          additional_data: hasCompanyExtras ? companyExtras : undefined,
        });

        const newSellerId = result.seller.id;
        setSellerId(newSellerId);

        // Force a fresh login so the new member_id lands in the JWT.
        try {
          await logout();
        } catch {
          // If logout fails we still redirect to /login — user will re-auth there.
        }
        queryClient.clear();
        sessionStorage.removeItem("mercur_onboarding_email");
        sessionStorage.removeItem("mercur_register_draft");

        navigate("/login", { replace: true });
      } catch (error: any) {
        toast.error(error.message);
      } finally {
        setIsSubmitting(false);
      }
    },
    [createSeller, logout, memberEmail, navigate],
  );

  // Step 4: Payment — create seller with everything and finish
  const submitPaymentStep = useCallback(
    async (data: PaymentData) => {
      await createSellerWithAllData(data);
    },
    [createSellerWithAllData],
  );

  // Skip payment — create seller without payment details
  const skipPaymentStep = useCallback(async () => {
    await createSellerWithAllData();
  }, [createSellerWithAllData]);

  const goBack = useCallback(() => {
    if (currentStep > 0) {
      setCurrentStep((prev) => prev - 1);
    }
  }, [currentStep]);

  return {
    currentStep,
    totalSteps: TOTAL_STEPS,
    sellerId: sellerIdState,
    isPending,
    canGoBack: currentStep > 0,
    goBack,
    submitStoreStep,
    submitAddressStep,
    skipAddressStep,
    submitCompanyStep,
    skipCompanyStep,
    submitPaymentStep,
    skipPaymentStep,
  };
};
