// Product search item type for API results
type ProductSearchItem = {
  id: number;
  name: string;
  type: string;
  price?: number | string | null;
  regular_price?: number | string | null;
  sale_price?: number | string | null;
  sku?: string;
  stock?: number | null;
  virtual?: boolean;
  downloadable?: boolean;
  variations?: {
    id: number;
    attributes: Record<string, string>;
    price: number;
    regular_price: number;
    sale_price: number | null;
    sku: string;
    stock: number | null;
    in_stock: boolean;
  }[];
};
import * as React from 'react';
import { makeMoneyFormatter, getStoreCurrency } from '@/lib/currency';
import { useQuery } from '@tanstack/react-query';
import { api } from '@/lib/api';
import { ProductsApi } from '@/lib/api/products';
import { CustomersApi } from '@/lib/api/customers';
import { cn } from '@/lib/utils';
import { __ } from '@/lib/i18n';
import { toast } from 'sonner';
import { Input } from '@/components/ui/input';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Drawer, DrawerContent, DrawerHeader, DrawerTitle } from '@/components/ui/drawer';
import { Badge } from '@/components/ui/badge';
import { useMediaQuery } from '@/hooks/use-media-query';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { SearchableSelect } from '@/components/ui/searchable-select';
import { DynamicCheckoutField, type CheckoutField } from '@/components/DynamicCheckoutField';

// --- Types ------------------------------------------------------------
export type CountryOption = { code: string; name: string };
export type StatesMap = Record<string, Record<string, string>>; // { US: { CA: 'California' } }
export type PaymentChannel = { id: string; title: string; meta?: any };
export type PaymentMethod = {
  id: string;
  title: string;
  enabled?: boolean;
  channels?: PaymentChannel[]; // If present, show channels instead of gateway
};
export type ShippingMethod = { id: string; title: string; cost: number };

export type LineItem = {
  line_item_id?: number; // present in edit mode to update existing line
  product_id: number;
  variation_id?: number; // for variable products
  qty: number;
  name?: string;
  variation_name?: string; // e.g., "Color: Red"
  price?: number;
  virtual?: boolean;
  downloadable?: boolean;
  regular_price?: number;
  sale_price?: number | null;
};

export type ExistingOrderDTO = {
  id: number;
  status?: string;
  billing?: any;
  shipping?: any;
  items?: LineItem[];
  payment_method?: string;
  payment_method_id?: string;
  shipping_method?: string;
  shipping_method_id?: string;
  customer_note?: string;
  currency?: string;
  currency_symbol?: string;
  totals?: {
    total_items?: number;
    total_shipping?: number;
    total_tax?: number;
    total_discount?: number;
    total?: number;
    shipping?: number;
  };
};

export type OrderPayload = {
  status: string;
  billing: any;
  shipping?: any;
  items?: LineItem[];
  payment_method?: string;
  shipping_method?: string;
  customer_note?: string;
  register_as_member?: boolean;
  coupons?: string[];
  custom_fields?: Record<string, string>;
};

type Props = {
  mode: 'create' | 'edit';
  initial?: ExistingOrderDTO | null;
  countries: CountryOption[];
  states: StatesMap;
  defaultCountry?: string;
  payments?: PaymentMethod[];
  shippings?: ShippingMethod[];
  onSubmit: (payload: OrderPayload) => Promise<void> | void;
  className?: string;
  currency?: string;
  currencySymbol?: string;
  leftTop?: React.ReactNode;
  rightTop?: React.ReactNode;
  itemsEditable?: boolean;
  showCoupons?: boolean;
  formRef?: React.RefObject<HTMLFormElement>;
  hideSubmitButton?: boolean;
};

const STATUS_LIST = ['pending', 'processing', 'on-hold', 'completed', 'cancelled', 'refunded', 'failed'];

// --- Component --------------------------------------------------------
export default function OrderForm({
  mode,
  initial,
  countries,
  states,
  defaultCountry,
  payments = [],
  shippings = [],
  onSubmit,
  className,
  leftTop: _leftTop,
  rightTop,
  itemsEditable = true,
  showCoupons = true,
  currency,
  currencySymbol,
  formRef,
  hideSubmitButton = false,
}: Props) {
  const oneCountryOnly = countries.length === 1;
  const firstCountry = countries[0]?.code || 'US';
  const baseCountry = (defaultCountry && countries.find(c => c.code === defaultCountry)?.code) || firstCountry;

  // Billing
  const [bFirst, setBFirst] = React.useState(initial?.billing?.first_name || '');
  const [bLast, setBLast] = React.useState(initial?.billing?.last_name || '');
  const [bEmail, setBEmail] = React.useState(initial?.billing?.email || '');
  const [bPhone, setBPhone] = React.useState(initial?.billing?.phone || '');
  const [bAddr1, setBAddr1] = React.useState(initial?.billing?.address_1 || '');
  const [bCity, setBCity] = React.useState(initial?.billing?.city || '');
  const [bPost, setBPost] = React.useState(initial?.billing?.postcode || '');
  const [bCountry, setBCountry] = React.useState(initial?.billing?.country || baseCountry);
  const [bState, setBState] = React.useState(initial?.billing?.state || '');

  // Shipping toggle + dynamic fields
  const [shipDiff, setShipDiff] = React.useState(Boolean(initial?.shipping && !isEmptyAddress(initial?.shipping)));
  const [shippingData, setShippingData] = React.useState<Record<string, any>>(initial?.shipping || {});

  // If store sells to a single country, force-select it for billing & shipping
  React.useEffect(() => {
    if (oneCountryOnly) {
      const only = countries[0]?.code || '';
      if (only && bCountry !== only) setBCountry(only);
    }
  }, [oneCountryOnly, countries, bCountry]);

  React.useEffect(() => {
    if (oneCountryOnly) {
      const only = countries[0]?.code || '';
      if (shipDiff) {
        if (only && shippingData.country !== only) {
          setShippingData({ ...shippingData, country: only });
        }
      } else {
        // keep shipping synced to billing when not different
        setShippingData({ ...shippingData, country: bCountry });
      }
    }
  }, [oneCountryOnly, countries, shipDiff, bCountry, shippingData.country]);

  // Order meta
  const [status, setStatus] = React.useState(initial?.status || 'pending');
  const [paymentMethod, setPaymentMethod] = React.useState(initial?.payment_method_id || initial?.payment_method || '');
  const [shippingMethod, setShippingMethod] = React.useState(initial?.shipping_method_id || initial?.shipping_method || '');
  const [note, setNote] = React.useState(initial?.customer_note || '');
  const [selectedCustomerId, setSelectedCustomerId] = React.useState<number | null>(null);
  const [submitting, setSubmitting] = React.useState(false);

  const [items, setItems] = React.useState<LineItem[]>(initial?.items || []);
  const [couponInput, setCouponInput] = React.useState('');
  const [validatedCoupons, setValidatedCoupons] = React.useState<any[]>([]);
  const [couponValidating, setCouponValidating] = React.useState(false);

  // Custom field values (for plugin fields like destination_id)
  const [customFieldData, setCustomFieldData] = React.useState<Record<string, string>>({});

  // Fetch dynamic checkout fields based on cart items
  const { data: checkoutFields } = useQuery({
    queryKey: ['checkout-fields', items.map(i => ({ product_id: i.product_id, qty: i.qty }))],
    queryFn: async () => {
      if (items.length === 0) return null;
      return api.post('/checkout/fields', {
        items: items.map(i => ({ product_id: i.product_id, qty: i.qty })),
      });
    },
    enabled: items.length > 0,
  });

  // Apply default values from API for hidden fields (like customer checkout does)
  React.useEffect(() => {
    if (!checkoutFields?.fields) return;

    // Initialize custom field defaults
    const customDefaults: Record<string, string> = {};
    checkoutFields.fields.forEach((field: any) => {
      if (field.default && field.custom) {
        customDefaults[field.key] = field.default;
      }
    });
    if (Object.keys(customDefaults).length > 0) {
      setCustomFieldData(prev => ({ ...customDefaults, ...prev }));
    }

    // Set billing country default for hidden fields (e.g., Indonesia-only stores)
    const billingCountryField = checkoutFields.fields.find((f: any) => f.key === 'billing_country');
    if ((billingCountryField?.type === 'hidden' || billingCountryField?.hidden) && billingCountryField.default && !bCountry) {
      setBCountry(billingCountryField.default);
    }

    // Set shipping country default for hidden fields
    const shippingCountryField = checkoutFields.fields.find((f: any) => f.key === 'shipping_country');
    if ((shippingCountryField?.type === 'hidden' || shippingCountryField?.hidden) && shippingCountryField.default && !shippingData.country) {
      setShippingData(prev => ({ ...prev, country: shippingCountryField.default }));
    }
  }, [checkoutFields?.fields]);

  // Get effective shipping address (use billing if not shipping to different address)
  const effectiveShippingAddress = React.useMemo(() => {
    // Get destination_id from custom fields (Rajaongkir)
    const destinationId = shipDiff
      ? customFieldData['shipping_destination_id']
      : customFieldData['billing_destination_id'];

    if (shipDiff) {
      return {
        ...shippingData,
        destination_id: destinationId || undefined,
      };
    }
    // Use billing address
    return {
      country: bCountry,
      state: bState,
      city: bCity,
      postcode: bPost,
      address_1: bAddr1,
      address_2: '',
      destination_id: destinationId || undefined,
    };
  }, [shipDiff, shippingData, bCountry, bState, bCity, bPost, bAddr1, customFieldData]);

  // Check if shipping address is complete enough to calculate rates
  // Should match customer checkout: just needs country to fetch (destination_id can provide more specific rates)
  const isShippingAddressComplete = React.useMemo(() => {
    const addr = effectiveShippingAddress;
    // Need at minimum: country OR destination_id
    // destination_id from Rajaongkir is sufficient to calculate shipping
    if (addr.destination_id) return true;
    return !!addr.country;
  }, [effectiveShippingAddress]);

  // Debounce city input to avoid hitting backend on every keypress
  const [debouncedCity, setDebouncedCity] = React.useState(effectiveShippingAddress.city);

  React.useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedCity(effectiveShippingAddress.city);
    }, 500); // Wait 500ms after user stops typing

    return () => clearTimeout(timer);
  }, [effectiveShippingAddress.city]);

  // Calculate shipping rates dynamically
  const { data: shippingRates, isLoading: shippingLoading } = useQuery({
    queryKey: ['shipping-rates', items.map(i => ({ product_id: i.product_id, qty: i.qty })), effectiveShippingAddress.country, effectiveShippingAddress.state, debouncedCity, effectiveShippingAddress.postcode, effectiveShippingAddress.destination_id],
    queryFn: async () => {
      return api.post('/shipping/calculate', {
        items: items.map(i => ({ product_id: i.product_id, qty: i.qty })),
        shipping: effectiveShippingAddress,
      });
    },
    enabled: isShippingAddressComplete && items.length > 0,
    gcTime: 0, // Don't cache - always fresh data
    staleTime: 0, // Always refetch when query key changes
  });

  // Calculate order preview with taxes
  const { data: orderPreview, isLoading: previewLoading } = useQuery({
    queryKey: ['order-preview', items.map(i => ({ product_id: i.product_id, qty: i.qty })), bCountry, bState, bPost, bCity, effectiveShippingAddress.country, effectiveShippingAddress.state, debouncedCity, effectiveShippingAddress.postcode, shippingMethod, validatedCoupons.map(c => c.code)],
    queryFn: async () => {
      return api.post('/orders/preview', {
        items: items.map(i => ({ product_id: i.product_id, qty: i.qty })),
        billing: { country: bCountry, state: bState, postcode: bPost, city: bCity },
        shipping: shipDiff ? shippingData : undefined,
        shipping_method: shippingMethod,
        coupons: validatedCoupons.map(c => c.code),
      });
    },
    enabled: items.length > 0 && !!bCountry && !!shippingMethod,
    gcTime: 0, // Don't cache - always fresh data
    staleTime: 0, // Always refetch when query key changes
  });

  // --- Product search for Add Item ---
  const [searchQ, setSearchQ] = React.useState('');
  const [customerSearchQ, setCustomerSearchQ] = React.useState('');
  const [selectedProduct, setSelectedProduct] = React.useState<ProductSearchItem | null>(null);
  const [selectedVariationId, setSelectedVariationId] = React.useState<number | null>(null);
  const [showVariationDrawer, setShowVariationDrawer] = React.useState(false);
  const isDesktop = useMediaQuery("(min-width: 768px)");
  const productsQ = useQuery({
    queryKey: ['products', searchQ],
    queryFn: () => ProductsApi.search(searchQ),
    enabled: !!searchQ,
  });

  const customersQ = useQuery({
    queryKey: ['customers', customerSearchQ],
    queryFn: () => CustomersApi.search(customerSearchQ),
    enabled: !!customerSearchQ && customerSearchQ.length >= 2,
  });
  const raw = productsQ.data as any;
  const products: ProductSearchItem[] = Array.isArray(raw)
    ? raw
    : Array.isArray(raw?.data)
      ? raw.data
      : Array.isArray(raw?.rows)
        ? raw.rows
        : [];

  const customersRaw = customersQ.data as any;
  const customers: any[] = Array.isArray(customersRaw) ? customersRaw : [];

  const itemsCount = React.useMemo(
    () => items.reduce((n, it) => n + (Number(it.qty) || 0), 0),
    [items]
  );
  const itemsTotal = React.useMemo(
    () => items.reduce((sum, it) => sum + (Number(it.qty) || 0) * (Number(it.price) || 0), 0),
    [items]
  );

  // Calculate shipping cost
  // In edit mode: use existing order shipping total (fixed unless address changes)
  // In create mode: calculate from selected shipping method
  const shippingCost = React.useMemo(() => {
    if (mode === 'edit' && initial?.totals?.shipping !== undefined) {
      // Use existing shipping total from order
      return Number(initial.totals.shipping) || 0;
    }
    // Create mode: calculate from shipping method
    if (!shippingMethod) return 0;
    const method = shippings.find(s => s.id === shippingMethod);
    return method ? Number(method.cost) || 0 : 0;
  }, [mode, initial?.totals?.shipping, shippingMethod, shippings]);

  // Calculate discount from validated coupons
  const couponDiscount = React.useMemo(() => {
    return validatedCoupons.reduce((sum, c) => sum + (c.discount_amount || 0), 0);
  }, [validatedCoupons]);

  // Calculate order total (items + shipping - coupons)
  const orderTotal = React.useMemo(() => {
    return Math.max(0, itemsTotal + shippingCost - couponDiscount);
  }, [itemsTotal, shippingCost, couponDiscount]);

  // Validate coupon
  const validateCoupon = async (code: string) => {
    if (!code.trim()) return;

    // Check if already added
    if (validatedCoupons.some(c => c.code.toLowerCase() === code.toLowerCase())) {
      toast.error(__('Coupon already added'));
      return;
    }

    setCouponValidating(true);
    try {
      const response = await api.post('/coupons/validate', {
        code: code.trim(),
        subtotal: itemsTotal,
      });

      if (response.valid) {
        setValidatedCoupons([...validatedCoupons, response]);
        setCouponInput('');
        toast.success(`${__('Coupon applied')}: ${response.code}`);
      } else {
        toast.error(response.error || __('Invalid coupon'));
      }
    } catch (error: any) {
      toast.error(error?.message || __('Failed to validate coupon'));
    } finally {
      setCouponValidating(false);
    }
  };

  const removeCoupon = (code: string) => {
    setValidatedCoupons(validatedCoupons.filter(c => c.code !== code));
  };

  // Auto-select first shipping rate when rates change
  React.useEffect(() => {
    if (shippingRates?.methods && shippingRates.methods.length > 0) {
      const firstRateId = shippingRates.methods[0].id;
      // Only auto-select if no method selected or current method not in new rates
      const currentMethodExists = shippingRates.methods.some((m: any) => m.id === shippingMethod);
      if (!shippingMethod || !currentMethodExists) {
        setShippingMethod(firstRateId);
      }
    } else if (shippingRates?.methods && shippingRates.methods.length === 0) {
      // Clear selection if no rates available
      setShippingMethod('');
    }
  }, [shippingRates?.methods]);

  // Check if cart has physical products
  const hasPhysicalProduct = React.useMemo(
    () => items.some(item => {
      // Check item's stored metadata first
      if (typeof item.virtual !== 'undefined' || typeof item.downloadable !== 'undefined') {
        return !item.virtual && !item.downloadable;
      }
      // Fallback: check products array (for search results)
      const product = products.find(p => p.id === item.product_id);
      return product ? !product.virtual && !product.downloadable : true; // Default to physical if unknown
    }),
    [items, products]
  );

  // --- Currency-aware formatting for unit prices and totals ---
  const storeCur = getStoreCurrency();
  const currencyCode = currency || initial?.currency || storeCur.currency;
  const symbol = initial?.currency_symbol ?? currencySymbol ?? storeCur.symbol;
  const money = React.useMemo(() => makeMoneyFormatter({ currency: currencyCode, symbol }), [currencyCode, symbol]);

  // Keep shipping country synced to billing when unchecked
  React.useEffect(() => {
    if (!shipDiff) setShippingData({ ...shippingData, country: bCountry });
  }, [shipDiff, bCountry]);

  // Clamp states when country changes
  React.useEffect(() => {
    if (bState && !states[bCountry]?.[bState]) setBState('');
  }, [bCountry]);
  React.useEffect(() => {
    if (shippingData.state && !states[shippingData.country]?.[shippingData.state]) {
      setShippingData({ ...shippingData, state: '' });
    }
  }, [shippingData.country]);

  const countryOptions = countries.map(c => ({ value: c.code, label: `${c.name} (${c.code})` }));
  const bStateOptions = Object.entries(states[bCountry] || {}).map(([code, name]) => ({ value: code, label: name }));

  // Helper to get billing field config from API - returns null if hidden
  const getBillingField = (key: string) => {
    if (!checkoutFields?.fields) return { label: '', required: false }; // fallback when API not loaded
    const field = checkoutFields.fields.find((f: any) => f.key === key);
    // Check both hidden flag and type === 'hidden'
    if (!field || field.hidden || field.type === 'hidden') return null;
    return field;
  };

  // Helper to check if billing field should have full width
  const isBillingFieldWide = (key: string) => {
    const field = getBillingField(key);
    if (!field) return false;
    const hasFormRowWide = Array.isArray(field.class) && field.class.includes('form-row-wide');
    return hasFormRowWide || ['billing_address_1', 'billing_address_2'].includes(key);
  };

  // Derive custom fields from API (for plugin fields like destination_id)
  const billingCustomFields = React.useMemo(() => {
    if (!checkoutFields?.fields) return [];
    return checkoutFields.fields
      .filter((f: any) => f.fieldset === 'billing' && f.custom && !f.hidden && f.type !== 'hidden')
      .sort((a: any, b: any) => (a.priority || 10) - (b.priority || 10));
  }, [checkoutFields?.fields]);

  const shippingCustomFields = React.useMemo(() => {
    if (!checkoutFields?.fields) return [];
    return checkoutFields.fields
      .filter((f: any) => f.fieldset === 'shipping' && f.custom && !f.hidden && f.type !== 'hidden')
      .sort((a: any, b: any) => (a.priority || 10) - (b.priority || 10));
  }, [checkoutFields?.fields]);

  // Helper to handle custom field changes
  const handleCustomFieldChange = (key: string, value: string) => {
    setCustomFieldData(prev => ({ ...prev, [key]: value }));
  };

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();

    // For virtual-only products, don't send address fields
    const billingData: any = {
      first_name: bFirst,
      last_name: bLast,
      email: bEmail,
      phone: bPhone,
    };

    // Only add address fields for physical products
    if (hasPhysicalProduct) {
      billingData.address_1 = bAddr1;
      billingData.city = bCity;
      billingData.state = bState;
      billingData.postcode = bPost;
      billingData.country = bCountry;
    }

    const payload: OrderPayload = {
      status,
      billing: billingData,
      shipping: shipDiff && hasPhysicalProduct ? shippingData : undefined,
      payment_method: paymentMethod || undefined,
      shipping_method: shippingMethod || undefined,
      customer_note: note || undefined,
      items: itemsEditable ? items : undefined,
      coupons: showCoupons ? validatedCoupons.map(c => c.code) : undefined,
      custom_fields: Object.keys(customFieldData).length > 0 ? customFieldData : undefined,
    };

    try {
      setSubmitting(true);
      await onSubmit(payload);
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <form ref={formRef} onSubmit={handleSubmit} className={cn('grid grid-cols-1 lg:grid-cols-3 gap-6', className)}>
      {/* Left: Order details */}
      <div className="lg:col-span-2 space-y-6">
        {/* Items and Coupons */}
        {(mode === 'create' || showCoupons || itemsEditable) && (
          <div className="space-y-4">
            {/* Items */}
            <div className="rounded border p-4 space-y-3">
              <div className="font-medium flex items-center justify-between">
                <span>{__('Items')}</span>
                {itemsEditable ? (
                  <div className="flex items-center gap-2">
                    <SearchableSelect
                      options={
                        products.map((p: ProductSearchItem) => ({
                          value: String(p.id),
                          label: (
                            <div className="leading-tight">
                              <div className="font-medium">{p.name}</div>
                              {(typeof p.price !== 'undefined' && p.price !== null && !Number.isNaN(Number(p.price))) && (
                                <div className="text-xs text-muted-foreground">
                                  {p.sale_price ? (
                                    <>
                                      {money(Number(p.sale_price))} <span className="line-through">{money(Number(p.regular_price))}</span>
                                    </>
                                  ) : money(Number(p.price))}
                                </div>
                              )}
                            </div>
                          ),
                          searchText: p.name,
                          product: p,
                        }))
                      }
                      value={undefined}
                      onChange={(val: string) => {
                        const p = products.find((prod: ProductSearchItem) => String(prod.id) === val);
                        if (!p) return;

                        // If variable product, show variation selector
                        if (p.type === 'variable' && p.variations && p.variations.length > 0) {
                          setSelectedProduct(p);
                          setSelectedVariationId(null);
                          setShowVariationDrawer(true);
                          return;
                        }

                        // Simple product - add directly (but allow duplicates for different quantities)
                        setItems(prev => [
                          ...prev,
                          {
                            product_id: p.id,
                            name: p.name,
                            price: Number(p.price) || 0,
                            qty: 1,
                            virtual: p.virtual,
                            downloadable: p.downloadable,
                          }
                        ]);
                        setSearchQ('');
                      }}
                      placeholder={__('Search products…')}
                      search={searchQ}
                      onSearch={setSearchQ}
                      disabled={!itemsEditable}
                      showCheckIndicator={false}
                    />
                  </div>
                ) : (
                  <span className="text-xs opacity-70">({__('locked')})</span>
                )}
              </div>

              {/* Desktop/table view */}
              <div className="hidden md:block">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="text-left border-b">
                      <th className="px-2 py-1">{__('Product')}</th>
                      <th className="px-2 py-1 w-24">{__('Qty')}</th>
                      <th className="px-2 py-1 w-16"></th>
                    </tr>
                  </thead>
                  <tbody>
                    {items.map((it, idx) => (
                      <tr key={`${it.product_id}-${it.variation_id || 'simple'}-${idx}`} className="border-b last:border-0">
                        <td className="px-2 py-1">
                          <div>
                            <div>{it.name || `Product #${it.product_id}`}</div>
                            {it.variation_name && (
                              <div className="text-xs text-muted-foreground">{it.variation_name}</div>
                            )}
                            {typeof it.price === 'number' && (
                              <div className="text-xs opacity-60">
                                {/* Show strike-through regular price if on sale */}
                                {(() => {
                                  // Check item's own data first (for edit mode)
                                  if (it.sale_price && it.regular_price && it.sale_price < it.regular_price) {
                                    return (
                                      <>
                                        <span className="line-through text-gray-400 mr-1">{money(Number(it.regular_price))}</span>
                                        <span className="text-red-600 font-semibold">{money(Number(it.sale_price))}</span>
                                      </>
                                    );
                                  }
                                  // Fallback: check products array (for create mode)
                                  const product = products.find(p => p.id === it.product_id);
                                  if (product && product.sale_price && product.regular_price && product.sale_price < product.regular_price) {
                                    return (
                                      <>
                                        <span className="text-red-600 font-semibold">{money(Number(product.sale_price))}</span>
                                        <span className="line-through text-gray-400 ml-1">{money(Number(product.regular_price))}</span>
                                      </>
                                    );
                                  }
                                  return money(Number(it.price));
                                })()}
                              </div>
                            )}
                          </div>
                        </td>
                        <td className="px-2 py-1">
                          <Input
                            inputMode="numeric"
                            pattern="[0-9]*"
                            min={1}
                            className="ui-ctrl w-24 text-center"
                            value={String(it.qty)}
                            onChange={(e) => {
                              if (!itemsEditable) return;
                              const raw = e.target.value.replace(/[^0-9]/g, '');
                              const v = Math.max(1, parseInt(raw || '1', 10));
                              setItems(prev => prev.map((x, i) => i === idx ? { ...x, qty: v } : x));
                            }}
                            disabled={!itemsEditable}
                          />
                        </td>
                        <td className="px-2 py-1 text-right">
                          {itemsEditable && (
                            <button
                              className="text-red-600"
                              type="button"
                              onClick={() => setItems(prev => prev.filter((_, i) => i !== idx))}
                            >
                              {__('Remove')}
                            </button>
                          )}
                        </td>
                      </tr>
                    ))}
                    {items.length === 0 && (
                      <tr>
                        <td className="px-2 py-4 text-center opacity-70" colSpan={3}>{__('No items yet')}</td>
                      </tr>
                    )}
                  </tbody>
                </table>
              </div>

              {/* Mobile/card view */}
              <div className="md:hidden divide-y">
                {items.length ? (
                  items.map((it, idx) => (
                    <div key={`${it.product_id}-${it.variation_id || 'simple'}-${idx}`} className="py-3">
                      <div className="px-1 flex items-start justify-between gap-3">
                        <div className="min-w-0">
                          <div className="font-medium truncate">{it.name || `Product #${it.product_id}`}</div>
                          {it.variation_name && (
                            <div className="text-xs text-muted-foreground">{it.variation_name}</div>
                          )}
                          {typeof it.price === 'number' && (
                            <div className="text-xs opacity-60">{money(Number(it.price))}</div>
                          )}
                        </div>
                        <div className="text-right">
                          {itemsEditable && (
                            <button
                              className="text-red-600 text-xs"
                              type="button"
                              onClick={() => setItems(prev => prev.filter((_, i) => i !== idx))}
                            >
                              {__('Remove')}
                            </button>
                          )}
                        </div>
                      </div>
                      <div className="mt-2 px-1 grid grid-cols-3 gap-2 items-center">
                        <div className="col-span-2 text-sm opacity-70">{__('Quantity')}</div>
                        <div>
                          <Input
                            inputMode="numeric"
                            pattern="[0-9]*"
                            min={1}
                            className="ui-ctrl w-full text-center"
                            value={String(it.qty)}
                            onChange={(e) => {
                              if (!itemsEditable) return;
                              const raw = e.target.value.replace(/[^0-9]/g, '');
                              const v = Math.max(1, parseInt(raw || '1', 10));
                              setItems(prev => prev.map((x, i) => i === idx ? { ...x, qty: v } : x));
                            }}
                            disabled={!itemsEditable}
                          />
                        </div>
                      </div>
                    </div>
                  ))
                ) : (
                  <div className="px-2 py-4 text-center opacity-70">{__('No items yet')}</div>
                )}
              </div>
              <div className="rounded-md border px-3 py-2 text-sm bg-white/60 space-y-1.5">
                <div className="flex justify-between">
                  <span className="opacity-70">{__('Items')}</span>
                  <span>{itemsCount}</span>
                </div>
                <div className="flex justify-between">
                  <span className="opacity-70">{__('Subtotal')}</span>
                  <span>
                    {orderPreview ? money(orderPreview.subtotal) : itemsTotal ? money(itemsTotal) : '—'}
                  </span>
                </div>
                {(orderPreview?.shipping_total > 0 || shippingCost > 0) && (
                  <div className="flex justify-between">
                    <span className="opacity-70">{__('Shipping')}</span>
                    <span>{orderPreview ? money(orderPreview.shipping_total) : money(shippingCost)}</span>
                  </div>
                )}
                {(orderPreview?.discount_total > 0 || couponDiscount > 0) && (
                  <div className="flex justify-between text-green-700">
                    <span>{__('Discount')}</span>
                    <span>-{orderPreview ? money(orderPreview.discount_total) : money(couponDiscount)}</span>
                  </div>
                )}
                {orderPreview?.total_tax > 0 && (
                  <div className="flex justify-between">
                    <span className="opacity-70">{__('Tax')}</span>
                    <span>{money(orderPreview.total_tax)}</span>
                  </div>
                )}
                <div className="flex justify-between pt-1.5 border-t font-medium">
                  <span>{__('Total')}</span>
                  <span>
                    {previewLoading ? (
                      <span className="opacity-50">{__('Calculating...')}</span>
                    ) : orderPreview ? (
                      money(orderPreview.total)
                    ) : (
                      money(orderTotal)
                    )}
                  </span>
                </div>
              </div>
            </div>

            {/* Variation Selector - Dialog (Desktop) */}
            {selectedProduct && selectedProduct.type === 'variable' && isDesktop && (
              <Dialog open={showVariationDrawer} onOpenChange={setShowVariationDrawer}>
                <DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
                  <DialogHeader>
                    <DialogTitle>{selectedProduct.name}</DialogTitle>
                    <p className="text-sm text-muted-foreground">{__('Select a variation')}</p>
                  </DialogHeader>
                  <div className="space-y-3 p-4">
                    {selectedProduct.variations?.map((variation) => {
                      // Build formatted label with styled key:value pairs
                      const variationParts = Object.entries(variation.attributes)
                        .filter(([_, value]) => value) // Remove empty values
                        .map(([key, value]) => ({ key, value: value || '' }));

                      return (
                        <button
                          key={variation.id}
                          type="button"
                          onClick={() => {
                            // Check if this product+variation already exists
                            const existingIndex = items.findIndex(
                              item => item.product_id === selectedProduct.id && item.variation_id === variation.id
                            );

                            if (existingIndex !== -1) {
                              // Increment quantity of existing item
                              setItems(prev => prev.map((item, idx) =>
                                idx === existingIndex
                                  ? { ...item, qty: item.qty + 1 }
                                  : item
                              ));
                            } else {
                              // Add new cart item
                              setItems(prev => [
                                ...prev,
                                {
                                  product_id: selectedProduct.id,
                                  variation_id: variation.id,
                                  name: selectedProduct.name,
                                  variation_name: variationParts.map(p => `${p.key}: ${p.value}`).join(', '),
                                  price: variation.price,
                                  regular_price: variation.regular_price,
                                  sale_price: variation.sale_price,
                                  qty: 1,
                                  virtual: selectedProduct.virtual,
                                  downloadable: selectedProduct.downloadable,
                                }
                              ]);
                            }
                            setShowVariationDrawer(false);
                            setSelectedProduct(null);
                            setSearchQ('');
                          }}
                          className="w-full text-left p-3 border rounded-lg hover:bg-accent transition-colors"
                        >
                          <div className="flex items-start justify-between gap-3">
                            <div className="flex-1 min-w-0">
                              <div className="text-sm">
                                {variationParts.map((part, idx) => (
                                  <span key={part.key}>
                                    <span className="font-semibold">{part.key}:</span>{' '}
                                    <span>{part.value}</span>
                                    {idx < variationParts.length - 1 && ', '}
                                  </span>
                                ))}
                              </div>
                              {variation.sku && (
                                <div className="text-xs text-muted-foreground mt-0.5">
                                  SKU: {variation.sku}
                                </div>
                              )}
                              {variation.stock !== null && (
                                <div className="text-xs text-muted-foreground mt-0.5">
                                  {__('Stock')}: {variation.stock}
                                </div>
                              )}
                            </div>
                            <div className="text-right flex-shrink-0">
                              <div className="font-semibold">
                                {variation.sale_price ? (
                                  <>
                                    {money(variation.sale_price)}
                                    <div className="text-xs line-through text-muted-foreground">
                                      {money(variation.regular_price)}
                                    </div>
                                  </>
                                ) : (
                                  money(variation.price)
                                )}
                              </div>
                              {!variation.in_stock && (
                                <Badge variant="destructive" className="mt-1 text-xs">
                                  {__('Out of stock')}
                                </Badge>
                              )}
                            </div>
                          </div>
                        </button>
                      );
                    })}
                  </div>
                </DialogContent>
              </Dialog>
            )}

            {/* Variation Selector - Drawer (Mobile) */}
            {selectedProduct && selectedProduct.type === 'variable' && !isDesktop && (
              <Drawer open={showVariationDrawer} onOpenChange={setShowVariationDrawer}>
                <DrawerContent>
                  <DrawerHeader>
                    <DrawerTitle>{selectedProduct.name}</DrawerTitle>
                    <p className="text-sm text-muted-foreground">{__('Select a variation')}</p>
                  </DrawerHeader>
                  <div className="p-4 space-y-3 max-h-[60vh] overflow-y-auto">
                    {selectedProduct.variations?.map((variation) => {
                      // Build formatted label with styled key:value pairs
                      const variationParts = Object.entries(variation.attributes)
                        .filter(([_, value]) => value) // Remove empty values
                        .map(([key, value]) => ({ key, value: value || '' }));

                      return (
                        <button
                          key={variation.id}
                          type="button"
                          onClick={() => {
                            // Check if this product+variation already exists
                            const existingIndex = items.findIndex(
                              item => item.product_id === selectedProduct.id && item.variation_id === variation.id
                            );

                            if (existingIndex !== -1) {
                              // Increment quantity of existing item
                              setItems(prev => prev.map((item, idx) =>
                                idx === existingIndex
                                  ? { ...item, qty: item.qty + 1 }
                                  : item
                              ));
                            } else {
                              // Add new cart item
                              setItems(prev => [
                                ...prev,
                                {
                                  product_id: selectedProduct.id,
                                  variation_id: variation.id,
                                  name: selectedProduct.name,
                                  variation_name: variationParts.map(p => `${p.key}: ${p.value}`).join(', '),
                                  price: variation.price,
                                  regular_price: variation.regular_price,
                                  sale_price: variation.sale_price,
                                  qty: 1,
                                  virtual: selectedProduct.virtual,
                                  downloadable: selectedProduct.downloadable,
                                }
                              ]);
                            }
                            setShowVariationDrawer(false);
                            setSelectedProduct(null);
                            setSearchQ('');
                          }}
                          className="w-full text-left p-3 border rounded-lg hover:bg-accent transition-colors"
                        >
                          <div className="flex items-start justify-between gap-3">
                            <div className="flex-1 min-w-0">
                              <div className="text-sm">
                                {variationParts.map((part, idx) => (
                                  <span key={part.key}>
                                    <span className="font-semibold">{part.key}:</span>{' '}
                                    <span>{part.value}</span>
                                    {idx < variationParts.length - 1 && ', '}
                                  </span>
                                ))}
                              </div>
                              {variation.sku && (
                                <div className="text-xs text-muted-foreground mt-0.5">
                                  SKU: {variation.sku}
                                </div>
                              )}
                              {variation.stock !== null && (
                                <div className="text-xs text-muted-foreground mt-0.5">
                                  {__('Stock')}: {variation.stock}
                                </div>
                              )}
                            </div>
                            <div className="text-right flex-shrink-0">
                              <div className="font-semibold">
                                {variation.sale_price ? (
                                  <>
                                    {money(variation.sale_price)}
                                    <div className="text-xs line-through text-muted-foreground">
                                      {money(variation.regular_price)}
                                    </div>
                                  </>
                                ) : (
                                  money(variation.price)
                                )}
                              </div>
                              {!variation.in_stock && (
                                <Badge variant="destructive" className="mt-1 text-xs">
                                  {__('Out of stock')}
                                </Badge>
                              )}
                            </div>
                          </div>
                        </button>
                      );
                    })}
                  </div>
                </DrawerContent>
              </Drawer>
            )}

            {/* Coupons */}
            {showCoupons && (
              <div className="rounded border p-4 space-y-3">
                <div className="font-medium flex items-center justify-between">
                  <span>{__('Coupons')}</span>
                  {!itemsEditable && (
                    <span className="text-xs opacity-70">({__('locked')})</span>
                  )}
                </div>

                {/* Coupon Input */}
                <div className="flex gap-2">
                  <Input
                    value={couponInput}
                    onChange={(e) => setCouponInput(e.target.value)}
                    onKeyDown={(e) => {
                      if (e.key === 'Enter') {
                        e.preventDefault();
                        validateCoupon(couponInput);
                      }
                    }}
                    placeholder={__('Enter coupon code')}
                    disabled={!itemsEditable || couponValidating}
                    className="flex-1"
                  />
                  <Button
                    type="button"
                    onClick={() => validateCoupon(couponInput)}
                    disabled={!itemsEditable || !couponInput.trim() || couponValidating}
                    size="sm"
                  >
                    {couponValidating ? __('Validating...') : __('Apply')}
                  </Button>
                </div>

                {/* Applied Coupons */}
                {validatedCoupons.length > 0 && (
                  <div className="space-y-2">
                    {validatedCoupons.map((coupon) => (
                      <div key={coupon.code} className="flex items-center justify-between p-2 bg-green-50 border border-green-200 rounded text-sm">
                        <div className="flex-1">
                          <div className="font-medium text-green-800">{coupon.code}</div>
                          {coupon.description && (
                            <div className="text-xs text-green-700 opacity-80">{coupon.description}</div>
                          )}
                          <div className="text-xs text-green-700 mt-1">
                            {coupon.discount_type === 'percent' && `${coupon.amount}% off`}
                            {coupon.discount_type === 'fixed_cart' && `${money(coupon.amount)} off`}
                            {coupon.discount_type === 'fixed_product' && `${money(coupon.amount)} off per item`}
                            {' · '}
                            <span className="font-medium">{__('Discount')}: {money(coupon.discount_amount)}</span>
                          </div>
                        </div>
                        <Button
                          type="button"
                          variant="ghost"
                          size="sm"
                          onClick={() => removeCoupon(coupon.code)}
                          disabled={!itemsEditable}
                          className="text-red-600 hover:text-red-700 hover:bg-red-50"
                        >
                          {__('Remove')}
                        </Button>
                      </div>
                    ))}
                  </div>
                )}

                <div className="text-[11px] opacity-70">
                  {__('Enter coupon code and click Apply to validate and calculate discount')}
                </div>
              </div>
            )}
          </div>
        )}
        {/* Billing address - only show when items are added (so checkout fields API is loaded) */}
        {items.length > 0 && (
          <div className="rounded border p-4 space-y-3">
            <div className="flex items-center justify-between mb-3">
              <h3 className="text-sm font-medium">{__('Billing address')}</h3>
              {mode === 'create' && (
                <SearchableSelect
                  options={customers.map((c: any) => ({
                    value: String(c.id),
                    label: (
                      <div className="leading-tight">
                        <div className="font-medium">{c.name || c.email}</div>
                        <div className="text-xs text-muted-foreground">{c.email}</div>
                      </div>
                    ),
                    searchText: `${c.name} ${c.email}`,
                    customer: c,
                  }))}
                  value={undefined}
                  onChange={async (val: string) => {
                    const customer = customers.find((c: any) => String(c.id) === val);
                    if (!customer) return;

                    // Fetch full customer data
                    try {
                      const data = await CustomersApi.searchByEmail(customer.email);
                      if (data.found && data.billing) {
                        // Always fill name, email, phone
                        setBFirst(data.billing.first_name || data.first_name || '');
                        setBLast(data.billing.last_name || data.last_name || '');
                        setBEmail(data.email || '');
                        setBPhone(data.billing.phone || '');

                        // Only fill address fields if cart has physical products
                        if (hasPhysicalProduct) {
                          setBAddr1(data.billing.address_1 || '');
                          setBCity(data.billing.city || '');
                          setBPost(data.billing.postcode || '');
                          setBCountry(data.billing.country || bCountry);
                          setBState(data.billing.state || '');

                          // Autofill shipping if available
                          if (data.shipping && data.shipping.address_1) {
                            setShipDiff(true);
                            setShippingData({
                              first_name: data.shipping.first_name || '',
                              last_name: data.shipping.last_name || '',
                              address_1: data.shipping.address_1 || '',
                              city: data.shipping.city || '',
                              postcode: data.shipping.postcode || '',
                              country: data.shipping.country || bCountry,
                              state: data.shipping.state || '',
                            });
                          }
                        }

                        // Mark customer as selected
                        setSelectedCustomerId(data.user_id);
                      }
                    } catch (e) {
                      console.error('Customer autofill error:', e);
                    }

                    setCustomerSearchQ('');
                  }}
                  onSearch={setCustomerSearchQ}
                  placeholder={__('Search customer...')}
                  className="w-64"
                />
              )}
            </div>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
              {/* Dynamic billing fields - respects API visibility, labels, required status */}
              {getBillingField('billing_first_name') && (
                <div className={isBillingFieldWide('billing_first_name') ? 'md:col-span-2' : ''}>
                  <Label>
                    {getBillingField('billing_first_name')?.label || __('First name')}
                    {getBillingField('billing_first_name')?.required && <span className="text-destructive ml-1">*</span>}
                  </Label>
                  <Input
                    className="rounded-md border px-3 py-2"
                    value={bFirst}
                    onChange={e => setBFirst(e.target.value)}
                    required={getBillingField('billing_first_name')?.required}
                  />
                </div>
              )}
              {getBillingField('billing_last_name') && (
                <div className={isBillingFieldWide('billing_last_name') ? 'md:col-span-2' : ''}>
                  <Label>
                    {getBillingField('billing_last_name')?.label || __('Last name')}
                    {getBillingField('billing_last_name')?.required && <span className="text-destructive ml-1">*</span>}
                  </Label>
                  <Input
                    className="rounded-md border px-3 py-2"
                    value={bLast}
                    onChange={e => setBLast(e.target.value)}
                    required={getBillingField('billing_last_name')?.required}
                  />
                </div>
              )}
              {getBillingField('billing_email') && (
                <div className={isBillingFieldWide('billing_email') ? 'md:col-span-2' : ''}>
                  <Label>
                    {getBillingField('billing_email')?.label || __('Email')}
                    {getBillingField('billing_email')?.required && <span className="text-destructive ml-1">*</span>}
                  </Label>
                  <Input
                    inputMode="email"
                    autoComplete="email"
                    className="rounded-md border px-3 py-2 appearance-none"
                    value={bEmail}
                    onChange={e => setBEmail(e.target.value)}
                    required={getBillingField('billing_email')?.required}
                  />
                </div>
              )}
              {getBillingField('billing_phone') && (
                <div className={isBillingFieldWide('billing_phone') ? 'md:col-span-2' : ''}>
                  <Label>
                    {getBillingField('billing_phone')?.label || __('Phone')}
                    {getBillingField('billing_phone')?.required && <span className="text-destructive ml-1">*</span>}
                  </Label>
                  <Input
                    className="rounded-md border px-3 py-2"
                    value={bPhone}
                    onChange={e => setBPhone(e.target.value)}
                    required={getBillingField('billing_phone')?.required}
                  />
                </div>
              )}
              {/* Address fields - only shown for physical products AND when not hidden by API */}
              {hasPhysicalProduct && (
                <>
                  {getBillingField('billing_address_1') && (
                    <div className="md:col-span-2">
                      <Label>
                        {getBillingField('billing_address_1')?.label || __('Address')}
                        {getBillingField('billing_address_1')?.required && <span className="text-destructive ml-1">*</span>}
                      </Label>
                      <Input
                        className="rounded-md border px-3 py-2"
                        value={bAddr1}
                        onChange={e => setBAddr1(e.target.value)}
                        required={getBillingField('billing_address_1')?.required}
                      />
                    </div>
                  )}
                  {getBillingField('billing_city') && (
                    <div className={isBillingFieldWide('billing_city') ? 'md:col-span-2' : ''}>
                      <Label>
                        {getBillingField('billing_city')?.label || __('City')}
                        {getBillingField('billing_city')?.required && <span className="text-destructive ml-1">*</span>}
                      </Label>
                      <Input
                        className="rounded-md border px-3 py-2"
                        value={bCity}
                        onChange={e => setBCity(e.target.value)}
                        required={getBillingField('billing_city')?.required}
                      />
                    </div>
                  )}
                  {getBillingField('billing_postcode') && (
                    <div className={isBillingFieldWide('billing_postcode') ? 'md:col-span-2' : ''}>
                      <Label>
                        {getBillingField('billing_postcode')?.label || __('Postcode')}
                        {getBillingField('billing_postcode')?.required && <span className="text-destructive ml-1">*</span>}
                      </Label>
                      <Input
                        className="rounded-md border px-3 py-2"
                        value={bPost}
                        onChange={e => setBPost(e.target.value)}
                        required={getBillingField('billing_postcode')?.required}
                      />
                    </div>
                  )}
                  {getBillingField('billing_country') && (
                    <div className={isBillingFieldWide('billing_country') ? 'md:col-span-2' : ''}>
                      <Label>
                        {getBillingField('billing_country')?.label || __('Country')}
                        {getBillingField('billing_country')?.required && <span className="text-destructive ml-1">*</span>}
                      </Label>
                      <SearchableSelect
                        options={countryOptions}
                        value={bCountry}
                        onChange={setBCountry}
                        placeholder={countries.length ? __('Select country') : __('No countries')}
                        disabled={oneCountryOnly}
                      />
                    </div>
                  )}
                  {getBillingField('billing_state') && (
                    <div className={isBillingFieldWide('billing_state') ? 'md:col-span-2' : ''}>
                      <Label>
                        {getBillingField('billing_state')?.label || __('State/Province')}
                        {getBillingField('billing_state')?.required && <span className="text-destructive ml-1">*</span>}
                      </Label>
                      <SearchableSelect
                        options={bStateOptions}
                        value={bState}
                        onChange={setBState}
                        placeholder={bStateOptions.length ? __('Select state') : __('N/A')}
                        disabled={!bStateOptions.length}
                      />
                    </div>
                  )}
                </>
              )}

              {/* Billing custom fields from plugins (e.g., destination_id from Rajaongkir) */}
              {hasPhysicalProduct && billingCustomFields.map((field: CheckoutField) => (
                <DynamicCheckoutField
                  key={field.key}
                  field={field}
                  value={customFieldData[field.key] || ''}
                  onChange={(v) => handleCustomFieldChange(field.key, v)}
                  countryOptions={countryOptions}
                  stateOptions={bStateOptions}
                />
              ))}
            </div>
          </div>
        )}

        {/* Conditional: Only show address fields and shipping for physical products */}
        {!hasPhysicalProduct && (
          <div className="rounded border border-blue-200 bg-blue-50 p-3 text-sm text-blue-800">
            {__('Digital products only - shipping not required')}
          </div>
        )}

        {/* Shipping toggle */}
        {hasPhysicalProduct && (
          <div className="pt-2 mt-4">
            <div className="flex items-center gap-2 text-sm">
              <Checkbox id="shipDiff" checked={shipDiff} onCheckedChange={(v) => setShipDiff(Boolean(v))} />
              <Label htmlFor="shipDiff" className="leading-none">{__('Ship to a different address')}</Label>
            </div>
          </div>
        )}

        {/* Shipping address - Dynamic Fields */}
        {hasPhysicalProduct && shipDiff && checkoutFields?.fields && (
          <div className="rounded border p-4 space-y-3 mt-4">
            <h3 className="text-sm font-medium">{__('Shipping address')}</h3>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
              {checkoutFields.fields
                .filter((f: any) => f.fieldset === 'shipping' && !f.hidden && f.type !== 'hidden')
                .sort((a: any, b: any) => (a.priority || 0) - (b.priority || 0))
                .map((field: any) => {
                  // Check for full width: address fields or form-row-wide class from PHP
                  const hasFormRowWide = Array.isArray(field.class) && field.class.includes('form-row-wide');
                  const isWide = hasFormRowWide || ['address_1', 'address_2'].includes(field.key.replace('shipping_', ''));
                  const fieldKey = field.key.replace('shipping_', '');

                  // For searchable_select, DynamicCheckoutField renders its own label wrapper
                  if (field.type === 'searchable_select') {
                    return (
                      <DynamicCheckoutField
                        key={field.key}
                        field={field}
                        value={customFieldData[field.key] || ''}
                        onChange={(v) => handleCustomFieldChange(field.key, v)}
                        countryOptions={countryOptions}
                        stateOptions={Object.entries(states[shippingData.country] || {}).map(([code, name]) => ({ value: code, label: name }))}
                      />
                    );
                  }

                  return (
                    <div key={field.key} className={isWide ? 'md:col-span-2' : ''}>
                      <Label>
                        {field.label}
                        {field.required && <span className="text-destructive ml-1">*</span>}
                      </Label>
                      {field.type === 'select' && field.options && field.key !== 'shipping_state' ? (
                        <Select
                          value={shippingData[fieldKey] || ''}
                          onValueChange={(v) => setShippingData({ ...shippingData, [fieldKey]: v })}
                        >
                          <SelectTrigger className="w-full">
                            <SelectValue placeholder={field.placeholder || field.label} />
                          </SelectTrigger>
                          <SelectContent className="max-h-64">
                            {Object.entries(field.options).map(([value, label]: [string, any]) => (
                              <SelectItem key={value} value={value}>{label}</SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                      ) : field.key === 'shipping_country' ? (
                        <SearchableSelect
                          options={countryOptions}
                          value={shippingData.country || ''}
                          onChange={(v) => setShippingData({ ...shippingData, country: v })}
                          placeholder={field.placeholder || __('Select country')}
                          disabled={oneCountryOnly}
                        />
                      ) : field.key === 'shipping_state' && field.options ? (
                        <SearchableSelect
                          options={Object.entries(field.options).map(([value, label]: [string, any]) => ({ value, label }))}
                          value={shippingData.state || ''}
                          onChange={(v) => setShippingData({ ...shippingData, state: v })}
                          placeholder={field.placeholder || __('Select state')}
                          disabled={!Object.keys(field.options).length}
                        />
                      ) : field.type === 'textarea' ? (
                        <Textarea
                          value={field.custom ? customFieldData[field.key] || '' : shippingData[fieldKey] || ''}
                          onChange={(e) => field.custom
                            ? handleCustomFieldChange(field.key, e.target.value)
                            : setShippingData({ ...shippingData, [fieldKey]: e.target.value })
                          }
                          placeholder={field.placeholder}
                          required={field.required}
                        />
                      ) : field.custom ? (
                        // For other custom field types, store in customFieldData
                        <Input
                          type={field.type === 'email' ? 'email' : field.type === 'tel' ? 'tel' : 'text'}
                          value={customFieldData[field.key] || ''}
                          onChange={(e) => handleCustomFieldChange(field.key, e.target.value)}
                          placeholder={field.placeholder}
                          required={field.required}
                        />
                      ) : (
                        <Input
                          type={field.type === 'email' ? 'email' : field.type === 'tel' ? 'tel' : 'text'}
                          value={shippingData[fieldKey] || ''}
                          onChange={(e) => setShippingData({ ...shippingData, [fieldKey]: e.target.value })}
                          placeholder={field.placeholder}
                          required={field.required}
                        />
                      )}
                    </div>
                  );
                })}
            </div>
          </div>
        )}
      </div>

      {/* Right: Settings + Actions */}
      <aside className="lg:col-span-1">
        <div className="sticky top-4 space-y-4">
          {rightTop}
          <div className="rounded border p-4 space-y-3">
            <div className="font-medium">{__('Order Settings')}</div>
            <div>
              <Label>{__('Status')}</Label>
              <Select value={status} onValueChange={setStatus}>
                <SelectTrigger className="w-full"><SelectValue /></SelectTrigger>
                <SelectContent>
                  {STATUS_LIST.map((s) => (
                    <SelectItem key={s} value={s}>{s.charAt(0).toUpperCase() + s.slice(1)}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div>
              <Label>{__('Payment method')}</Label>
              <Select value={paymentMethod} onValueChange={setPaymentMethod}>
                <SelectTrigger className="w-full"><SelectValue placeholder={payments.length ? __('Select payment') : __('No methods')} /></SelectTrigger>
                <SelectContent>
                  {payments.map(p => {
                    // If gateway has channels, show channels instead of gateway
                    if (p.channels && p.channels.length > 0) {
                      return p.channels.map((channel: any) => (
                        <SelectItem key={channel.id} value={channel.id}>
                          {channel.title}
                        </SelectItem>
                      ));
                    }
                    // Otherwise show gateway
                    return (
                      <SelectItem key={p.id} value={p.id}>{p.title}</SelectItem>
                    );
                  })}
                </SelectContent>
              </Select>
            </div>
            {/* Only show shipping method for physical products */}
            {hasPhysicalProduct && (
              <div>
                <Label>{__('Shipping method')}</Label>
                {!isShippingAddressComplete ? (
                  /* Prompt user to enter address first */
                  <div className="text-sm text-muted-foreground py-2 italic">
                    {__('Enter shipping address to see available rates')}
                  </div>
                ) : shippingLoading ? (
                  <div className="text-sm text-muted-foreground py-2">{__('Calculating rates...')}</div>
                ) : shippingRates?.methods && shippingRates.methods.length > 0 ? (
                  <Select value={shippingMethod} onValueChange={setShippingMethod}>
                    <SelectTrigger className="w-full"><SelectValue placeholder={__('Select shipping')} /></SelectTrigger>
                    <SelectContent>
                      {shippingRates.methods.map((rate: any) => (
                        <SelectItem key={rate.id} value={rate.id}>
                          {rate.label} - {money(rate.cost)}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                ) : (
                  /* Address is complete but no methods returned */
                  <div className="text-sm text-muted-foreground py-2">{__('No shipping methods available for this address')}</div>
                )}
              </div>
            )}
          </div>

          <div className="rounded border p-4 space-y-2">
            <Label>{__('Customer note (optional)')}</Label>
            <Textarea value={note} onChange={e => setNote(e.target.value)} placeholder={__('Write a note for this order…')} />
          </div>

          {!hideSubmitButton && (
            <Button type="submit" disabled={submitting} className="w-full">
              {submitting ? (mode === 'edit' ? __('Saving…') : __('Creating…')) : (mode === 'edit' ? __('Save changes') : __('Create order'))}
            </Button>
          )}
        </div>
      </aside>
    </form>
  );
}

function isEmptyAddress(a: any) {
  if (!a) return true;
  const keys = ['first_name', 'last_name', 'address_1', 'city', 'state', 'postcode', 'country'];
  return keys.every(k => !a[k]);
}