import { useEffect, useMemo, useState } from 'react'
import {
  ChevronLeft,
  MapPin,
  Minus,
  Plus,
  ShoppingBag,
  Store,
  Trash2,
  X,
} from 'lucide-react'
import {
  createMyAddress,
  createMyOrder,
  listBranches,
  listDistricts,
  listMyAddresses,
  listMyDiscounts,
  listShipping,
  type Branch,
  type Discount,
  type ShippingException,
  type UserAddress,
} from '../lib/api'
import {
  CART_OPEN_EVENT,
  clearCart,
  getCartCheckoutReturnUrl,
  getCartItems,
  getCartSubtotal,
  openCartDrawer,
  removeCartItem,
  setCartItemQuantity,
  showToast,
  subscribeCart,
  type CartItem,
  type CartOpenDetail,
} from '../lib/cart'
import {
  consumeAuthHashFromUrl,
  getAuthUser,
  getCustomerLoginUrl,
  isAuthenticated,
} from '../lib/auth'
import { formatPriceFa } from '../lib/types'
import defaultPhoto from '../assets/images/DefaultPhoto.png'
import './CartDrawer.css'

type Step = 1 | 2 | 3
type DeliveryType = 'pickup' | 'shipping'

function applyDiscount(subtotal: number, discount: Discount | null) {
  if (!discount) return 0
  if (subtotal < discount.minOrderAmount) return 0
  const raw = Math.round((subtotal * discount.percent) / 100)
  return Math.min(raw, discount.maxValue)
}

export default function CartDrawer() {
  const [open, setOpen] = useState(false)
  const [step, setStep] = useState<Step>(1)
  const [items, setItems] = useState<CartItem[]>(() => getCartItems())
  const [deliveryType, setDeliveryType] = useState<DeliveryType>('pickup')
  const [branches, setBranches] = useState<Branch[]>([])
  const [addresses, setAddresses] = useState<UserAddress[]>([])
  const [districts, setDistricts] = useState<string[]>([])
  const [shipping, setShipping] = useState<ShippingException[]>([])
  const [discounts, setDiscounts] = useState<Discount[]>([])
  const [branchId, setBranchId] = useState('')
  const [addressId, setAddressId] = useState('')
  const [discountCode, setDiscountCode] = useState('')
  const [appliedDiscount, setAppliedDiscount] = useState<Discount | null>(null)
  const [note, setNote] = useState('')
  const [loadingMeta, setLoadingMeta] = useState(false)
  const [submitting, setSubmitting] = useState(false)
  const [error, setError] = useState('')
  const [showNewAddress, setShowNewAddress] = useState(false)
  const [newAddress, setNewAddress] = useState({
    name: '',
    district: '',
    address: '',
    landline: '',
  })

  const subtotal = useMemo(() => getCartSubtotal(), [items])
  const selectedAddress = addresses.find((row) => row.id === addressId)
  const shippingFee =
    deliveryType === 'shipping' && selectedAddress
      ? shipping.find((row) => row.district === selectedAddress.district)?.price ?? 0
      : 0
  const discountValue = applyDiscount(subtotal, appliedDiscount)
  const payable = Math.max(0, subtotal + shippingFee - discountValue)

  useEffect(() => {
    return subscribeCart(() => setItems(getCartItems()))
  }, [])

  useEffect(() => {
    consumeAuthHashFromUrl()

    function onOpen(event: Event) {
      const detail = (event as CustomEvent<CartOpenDetail>).detail
      const nextStep = detail?.step ?? 1
      setItems(getCartItems())
      setError('')
      // Guests may only stay on the items step.
      if (nextStep > 1 && !isAuthenticated()) {
        setStep(1)
        setOpen(true)
        return
      }
      setStep(nextStep)
      setOpen(true)
    }

    window.addEventListener(CART_OPEN_EVENT, onOpen)

    const params = new URLSearchParams(window.location.search)
    const cartParam = params.get('cart')
    if (cartParam === 'checkout' || cartParam === '1' || cartParam === 'open') {
      if (cartParam === 'checkout' && isAuthenticated()) {
        openCartDrawer(2)
      } else {
        openCartDrawer(1)
      }
      params.delete('cart')
      const clean = `${window.location.pathname}${params.toString() ? `?${params}` : ''}${window.location.hash}`
      window.history.replaceState(null, '', clean)
    }

    return () => window.removeEventListener(CART_OPEN_EVENT, onOpen)
  }, [])

  useEffect(() => {
    if (!open || step === 1) return
    if (!isAuthenticated()) {
      setStep(1)
      return
    }
    let cancelled = false
    setLoadingMeta(true)
    setError('')
    Promise.all([
      listBranches(),
      listMyAddresses(),
      listDistricts(),
      listShipping(),
      listMyDiscounts(),
    ])
      .then(([branchRows, addressRows, districtRows, shippingRows, discountRows]) => {
        if (cancelled) return
        setBranches(branchRows)
        setAddresses(addressRows)
        setDistricts(districtRows)
        setShipping(shippingRows)
        setDiscounts(discountRows.items.filter((d) => d.active && !d.expired))
        if (!branchId && branchRows[0]) setBranchId(branchRows[0].id)
        if (!addressId && addressRows[0]) setAddressId(addressRows[0].id)
        if (!newAddress.district && districtRows[0]) {
          setNewAddress((current) => ({ ...current, district: districtRows[0] }))
        }
      })
      .catch((err: Error) => {
        if (!cancelled) setError(err.message || 'خطا در دریافت اطلاعات')
      })
      .finally(() => {
        if (!cancelled) setLoadingMeta(false)
      })
    return () => {
      cancelled = true
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open, step])

  function close() {
    setOpen(false)
    setError('')
  }

  function goNext() {
    setError('')
    if (step === 1) {
      if (items.length === 0) {
        setError('سبد خرید خالی است')
        return
      }
      // Auth is required only after reviewing cart items.
      if (!isAuthenticated()) {
        window.location.assign(getCustomerLoginUrl(getCartCheckoutReturnUrl()))
        return
      }
      setStep(2)
      return
    }
    if (step === 2) {
      if (deliveryType === 'pickup' && !branchId) {
        setError('شعبه را انتخاب کنید')
        return
      }
      if (deliveryType === 'shipping' && !addressId) {
        setError('آدرس را انتخاب کنید')
        return
      }
      setStep(3)
    }
  }

  function applyCode() {
    const code = discountCode.trim()
    if (!code) {
      setAppliedDiscount(null)
      return
    }
    const found = discounts.find(
      (row) => row.code.toLowerCase() === code.toLowerCase(),
    )
    if (!found) {
      setError('کد تخفیف معتبر نیست')
      setAppliedDiscount(null)
      return
    }
    if (subtotal < found.minOrderAmount) {
      setError(
        `حداقل مبلغ سفارش برای این کد ${formatPriceFa(found.minOrderAmount)} تومان است`,
      )
      setAppliedDiscount(null)
      return
    }
    setError('')
    setAppliedDiscount(found)
    showToast({ message: 'کد تخفیف اعمال شد' })
  }

  async function saveAddress() {
    try {
      setSubmitting(true)
      setError('')
      const created = await createMyAddress(newAddress)
      setAddresses((current) => [created, ...current])
      setAddressId(created.id)
      setShowNewAddress(false)
      setNewAddress({ name: '', district: districts[0] || '', address: '', landline: '' })
      showToast({ message: 'آدرس جدید ذخیره شد' })
    } catch (err) {
      setError(err instanceof Error ? err.message : 'ثبت آدرس ناموفق بود')
    } finally {
      setSubmitting(false)
    }
  }

  async function submitOrder() {
    try {
      setSubmitting(true)
      setError('')
      const order = await createMyOrder({
        deliveryType,
        branchId: deliveryType === 'pickup' ? branchId : undefined,
        shippingAddressId: deliveryType === 'shipping' ? addressId : undefined,
        discountCode: appliedDiscount?.code,
        note: note.trim() || undefined,
        items: items.map((item) => ({
          productId: item.productId,
          quantity: item.quantity,
          optionIds: item.options.map((option) => option.id),
        })),
      })
      clearCart()
      setItems([])
      setStep(1)
      setOpen(false)
      showToast({
        message: 'سفارش با موفقیت ثبت شد',
        detail: `کد سفارش ${order.code} — مبلغ ${formatPriceFa(order.totalPrice)} تومان`,
      })
    } catch (err) {
      setError(err instanceof Error ? err.message : 'ثبت سفارش ناموفق بود')
    } finally {
      setSubmitting(false)
    }
  }

  if (!open) return null

  const user = getAuthUser()

  return (
    <div className="cart-drawer-overlay" onClick={close} role="presentation">
      <aside
        className="cart-drawer"
        role="dialog"
        aria-modal="true"
        aria-label="سبد خرید"
        onClick={(event) => event.stopPropagation()}
      >
        <div className="cart-drawer__header">
          <div>
            <p className="cart-drawer__eyebrow">Shopping Cart</p>
            <h2 className="cart-drawer__title">سبد خرید</h2>
          </div>
          <button type="button" className="cart-drawer__close" onClick={close} aria-label="بستن">
            <X size={18} />
          </button>
        </div>

        <div className="cart-drawer__steps">
          {[
            { n: 1 as Step, label: 'اقلام' },
            { n: 2 as Step, label: 'ارسال' },
            { n: 3 as Step, label: 'پرداخت' },
          ].map((row) => (
            <div
              key={row.n}
              className={`cart-drawer__step${step === row.n ? ' is-active' : ''}${step > row.n ? ' is-done' : ''}`}
            >
              <span>{row.n.toLocaleString('fa-IR')}</span>
              <em>{row.label}</em>
            </div>
          ))}
        </div>

        <div className="cart-drawer__body">
          {error && <div className="cart-drawer__error">{error}</div>}

          {step === 1 && (
            <div className="cart-drawer__section">
              {items.length === 0 ? (
                <div className="cart-drawer__empty">
                  <ShoppingBag size={36} strokeWidth={1.4} />
                  <p>سبد خرید شما خالی است</p>
                </div>
              ) : (
                <ul className="cart-lines">
                  {items.map((item) => {
                    const unitLabel = item.sellUnit === 'kilo' ? 'کیلو' : 'واحد'
                    const productTotal = Math.round(item.quantity * item.basePrice)
                    const optionRows = item.options.map((option) => ({
                      ...option,
                      total: Math.round(item.quantity * option.price),
                    }))
                    const lineTotal =
                      productTotal +
                      optionRows.reduce((sum, option) => sum + option.total, 0)
                    const step = item.sellUnit === 'kilo' ? 0.1 : 1

                    return (
                      <li key={item.key} className="cart-line">
                        <img
                          src={item.imageUrl || defaultPhoto}
                          alt=""
                          className="cart-line__image"
                        />
                        <div className="cart-line__info">
                          <div className="cart-line__top">
                            <div className="cart-line__name">{item.nameFa}</div>
                            <button
                              type="button"
                              className="cart-line__remove"
                              onClick={() => removeCartItem(item.key)}
                              aria-label="حذف"
                            >
                              <Trash2 size={15} />
                            </button>
                          </div>

                          <div className="cart-line__calc-row">
                            <span className="cart-line__calc" dir="rtl">
                              {formatPriceFa(item.quantity)}{' '}
                              <bdi>{unitLabel}</bdi>
                              {' × '}
                              {formatPriceFa(item.basePrice)}
                            </span>
                            <span className="cart-line__result" dir="rtl">
                              = {formatPriceFa(productTotal)} تومان
                            </span>
                          </div>

                          {optionRows.map((option) => (
                            <div key={option.id} className="cart-line__calc-row cart-line__calc-row--option">
                              <span className="cart-line__option-name">{option.name}</span>
                              <span className="cart-line__calc" dir="rtl">
                                {formatPriceFa(item.quantity)}{' '}
                                <bdi>{unitLabel}</bdi>
                                {' × '}
                                {formatPriceFa(option.price)}
                              </span>
                              <span className="cart-line__result" dir="rtl">
                                = {formatPriceFa(option.total)} تومان
                              </span>
                            </div>
                          ))}

                          <div className="cart-line__footer">
                            <div className="qty-stepper qty-stepper--sm" dir="ltr">
                              <button
                                type="button"
                                className="qty-stepper__btn"
                                onClick={() =>
                                  setCartItemQuantity(item.key, item.quantity - step)
                                }
                              >
                                <Minus size={14} />
                              </button>
                              <span className="qty-stepper__value">
                                {formatPriceFa(item.quantity)}
                              </span>
                              <button
                                type="button"
                                className="qty-stepper__btn"
                                onClick={() =>
                                  setCartItemQuantity(item.key, item.quantity + step)
                                }
                              >
                                <Plus size={14} />
                              </button>
                            </div>
                            <div className="cart-line__line-total">
                              <span>جمع این قلم</span>
                              <strong>{formatPriceFa(lineTotal)} تومان</strong>
                            </div>
                          </div>
                        </div>
                      </li>
                    )
                  })}
                </ul>
              )}
            </div>
          )}

          {step === 2 && (
            <div className="cart-drawer__section">
              {loadingMeta ? (
                <p className="cart-drawer__muted">در حال بارگذاری...</p>
              ) : (
                <>
                  <div className="cart-delivery-toggle">
                    <button
                      type="button"
                      className={deliveryType === 'pickup' ? 'is-active' : undefined}
                      onClick={() => setDeliveryType('pickup')}
                    >
                      <Store size={16} />
                      تحویل حضوری
                    </button>
                    <button
                      type="button"
                      className={deliveryType === 'shipping' ? 'is-active' : undefined}
                      onClick={() => setDeliveryType('shipping')}
                    >
                      <MapPin size={16} />
                      ارسال به آدرس
                    </button>
                  </div>

                  {deliveryType === 'pickup' ? (
                    <div className="cart-choice-list">
                      {branches.map((branch) => (
                        <label key={branch.id} className={`cart-choice${branchId === branch.id ? ' is-active' : ''}`}>
                          <input
                            type="radio"
                            name="branch"
                            checked={branchId === branch.id}
                            onChange={() => setBranchId(branch.id)}
                          />
                          <span>
                            <strong>{branch.name}</strong>
                            <em>
                              {branch.district} — {branch.address}
                            </em>
                          </span>
                        </label>
                      ))}
                      {branches.length === 0 && (
                        <p className="cart-drawer__muted">شعبه‌ای ثبت نشده است</p>
                      )}
                    </div>
                  ) : (
                    <>
                      <div className="cart-choice-list">
                        {addresses.map((address) => (
                          <label
                            key={address.id}
                            className={`cart-choice${addressId === address.id ? ' is-active' : ''}`}
                          >
                            <input
                              type="radio"
                              name="address"
                              checked={addressId === address.id}
                              onChange={() => setAddressId(address.id)}
                            />
                            <span>
                              <strong>{address.name}</strong>
                              <em>
                                {address.district} — {address.address}
                              </em>
                            </span>
                          </label>
                        ))}
                      </div>
                      <button
                        type="button"
                        className="cart-drawer__link-btn"
                        onClick={() => setShowNewAddress((v) => !v)}
                      >
                        {showNewAddress ? 'بستن فرم آدرس' : 'افزودن آدرس جدید'}
                      </button>
                      {showNewAddress && (
                        <div className="cart-address-form">
                          <input
                            placeholder="عنوان (منزل / محل کار)"
                            value={newAddress.name}
                            onChange={(e) =>
                              setNewAddress((c) => ({ ...c, name: e.target.value }))
                            }
                          />
                          <select
                            value={newAddress.district}
                            onChange={(e) =>
                              setNewAddress((c) => ({ ...c, district: e.target.value }))
                            }
                          >
                            {districts.map((district) => (
                              <option key={district} value={district}>
                                {district}
                              </option>
                            ))}
                          </select>
                          <textarea
                            placeholder="آدرس کامل"
                            rows={3}
                            value={newAddress.address}
                            onChange={(e) =>
                              setNewAddress((c) => ({ ...c, address: e.target.value }))
                            }
                          />
                          <input
                            placeholder="تلفن ثابت"
                            value={newAddress.landline}
                            onChange={(e) =>
                              setNewAddress((c) => ({ ...c, landline: e.target.value }))
                            }
                          />
                          <button
                            type="button"
                            className="btn-primary"
                            disabled={submitting}
                            onClick={saveAddress}
                          >
                            ذخیره آدرس
                          </button>
                        </div>
                      )}
                    </>
                  )}
                </>
              )}
            </div>
          )}

          {step === 3 && (
            <div className="cart-drawer__section">
              <div className="cart-pay-summary">
                <div>
                  <span>جمع اقلام</span>
                  <strong>{formatPriceFa(subtotal)} تومان</strong>
                </div>
                <div>
                  <span>هزینه ارسال</span>
                  <strong>
                    {shippingFee > 0 ? `${formatPriceFa(shippingFee)} تومان` : '۰ تومان'}
                  </strong>
                </div>
                <div>
                  <span>تخفیف</span>
                  <strong>
                    {discountValue > 0
                      ? `${formatPriceFa(discountValue)}- تومان`
                      : '۰ تومان'}
                  </strong>
                </div>
                <div className="cart-pay-summary__total">
                  <span>مبلغ قابل پرداخت</span>
                  <strong>{formatPriceFa(payable)} تومان</strong>
                </div>
              </div>

              <label className="cart-field">
                <span>کد تخفیف</span>
                <div className="cart-discount-row">
                  <input
                    value={discountCode}
                    onChange={(e) =>
                      setDiscountCode(e.target.value.toUpperCase())
                    }
                    placeholder="مثلاً WELCOME10"
                    dir="ltr"
                    autoCapitalize="characters"
                    spellCheck={false}
                    className="cart-discount-input"
                    disabled={Boolean(appliedDiscount)}
                  />
                  <button type="button" onClick={applyCode} disabled={Boolean(appliedDiscount)}>
                    اعمال
                  </button>
                </div>
                {appliedDiscount && (
                  <div className="cart-discount-active" role="status">
                    <span>
                      {appliedDiscount.code} —{' '}
                      {appliedDiscount.percent.toLocaleString('fa-IR')}٪
                      {discountValue > 0
                        ? ` (${formatPriceFa(discountValue)} تومان تخفیف)`
                        : ''}
                    </span>
                    <button
                      type="button"
                      className="cart-discount-active__cancel"
                      aria-label="لغو تخفیف"
                      onClick={() => {
                        setAppliedDiscount(null)
                        setDiscountCode('')
                        setError('')
                      }}
                    >
                      <X size={16} strokeWidth={2} />
                    </button>
                  </div>
                )}
              </label>

              <label className="cart-field">
                <span>یادداشت سفارش</span>
                <textarea
                  rows={2}
                  value={note}
                  onChange={(e) => setNote(e.target.value)}
                  placeholder="توضیح اختیاری"
                />
              </label>

              <div className="cart-pay-method">
                <strong>روش پرداخت</strong>
                <p>پرداخت در محل / هنگام تحویل</p>
                {user && <em>{user.name} — {user.cellNumber}</em>}
              </div>
            </div>
          )}
        </div>

        <div className="cart-drawer__footer">
          {step > 1 && (
            <button type="button" className="cart-drawer__ghost" onClick={() => setStep((s) => (s - 1) as Step)}>
              قبلی
            </button>
          )}
          {step < 3 ? (
            <button type="button" className="btn-primary cart-drawer__primary" onClick={goNext}>
              ادامه
              <ChevronLeft size={14} />
            </button>
          ) : (
            <button
              type="button"
              className="btn-primary cart-drawer__primary"
              disabled={submitting || items.length === 0}
              onClick={submitOrder}
            >
              {submitting ? 'در حال ثبت...' : 'پرداخت و ثبت سفارش'}
              <ChevronLeft size={14} />
            </button>
          )}
        </div>
      </aside>
    </div>
  )
}

