import { useEffect, useState } from 'react'
import { createPortal } from 'react-dom'
import { X } from 'lucide-react'
import {
  getLocationOptionLabel,
  matchCityByName,
  matchProvinceByName,
  useLocale,
  useToast,
} from '@meshkee/dashboard-ui'
import { useT } from '../i18n/useT'
import { ApiError } from '../lib/api'
import {
  createAddress,
  updateAddress,
  type UserAddress,
} from '../services/addressService'
import {
  listCitiesByProvinceSlug,
  listIranProvinces,
  type CityOption,
} from '../services/citiesService'
import modalStyles from './VariationsModal.module.css'
import panelStyles from './checkout/CheckoutAddAddressPanel.module.css'
import styles from './AddressFormModal.module.css'

interface AddressFormModalProps {
  open: boolean
  address: UserAddress | null
  onClose: () => void
  onSaved: (address: UserAddress) => void
}

const ANIMATION_MS = 220

export function AddressFormModal({ open, address, onClose, onSaved }: AddressFormModalProps) {
  const t = useT()
  const { locale, dir } = useLocale()
  const { showToast } = useToast()
  const [mounted, setMounted] = useState(open)
  const [closing, setClosing] = useState(false)
  const [formKey, setFormKey] = useState(0)

  useEffect(() => {
    if (open) {
      setMounted(true)
      setClosing(false)
      setFormKey((key) => key + 1)
    } else if (mounted) {
      setClosing(true)
      const timer = setTimeout(() => {
        setMounted(false)
        setClosing(false)
      }, ANIMATION_MS)
      return () => clearTimeout(timer)
    }
  }, [open, mounted])

  useEffect(() => {
    if (!mounted || closing) return

    const prevOverflow = document.body.style.overflow
    document.body.style.overflow = 'hidden'

    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose()
    }

    document.addEventListener('keydown', onKey)
    return () => {
      document.body.style.overflow = prevOverflow
      document.removeEventListener('keydown', onKey)
    }
  }, [mounted, closing, onClose])

  if (!mounted) return null

  const isEdit = Boolean(address?.id)

  return createPortal(
    <div
      className={`${modalStyles.overlay} ${styles.overlay} ${closing ? modalStyles.overlayOut : modalStyles.overlayIn}`}
      onClick={onClose}
    >
      <div
        className={`${modalStyles.modal} ${styles.modal} ${closing ? modalStyles.modalOut : modalStyles.modalIn}`}
        onClick={(e) => e.stopPropagation()}
        role="dialog"
        aria-modal="true"
        aria-labelledby="address-form-title"
        lang={locale}
        dir={dir}
      >
        <div className={modalStyles.header}>
          <div>
            <h2 id="address-form-title" className={modalStyles.title}>
              {isEdit ? t('addresses.modal.editTitle') : t('addresses.modal.addTitle')}
            </h2>
            <p className={modalStyles.subtitle}>{t('addresses.modal.subtitle')}</p>
          </div>
          <button
            type="button"
            className={modalStyles.closeBtn}
            onClick={onClose}
            aria-label={t('common.close')}
          >
            <X size={20} />
          </button>
        </div>

        <div className={modalStyles.body}>
          <AddressFormFields
            key={formKey}
            address={address}
            onCancel={onClose}
            onSaved={(saved) => {
              showToast(
                isEdit ? t('addresses.toast.updated') : t('addresses.toast.created'),
                'success',
              )
              onSaved(saved)
              onClose()
            }}
          />
        </div>
      </div>
    </div>,
    document.body,
  )
}

function AddressFormFields({
  address,
  onCancel,
  onSaved,
}: {
  address: UserAddress | null
  onCancel: () => void
  onSaved: (address: UserAddress) => void
}) {
  const t = useT()
  const { locale } = useLocale()
  const [provinces, setProvinces] = useState<CityOption[]>([])
  const [cities, setCities] = useState<CityOption[]>([])
  const [loadingLocations, setLoadingLocations] = useState(true)
  const [saving, setSaving] = useState(false)
  const [error, setError] = useState('')
  const [label, setLabel] = useState(address?.label ?? '')
  const [provinceSlug, setProvinceSlug] = useState('')
  const [city, setCity] = useState('')
  const [street, setStreet] = useState(address?.address ?? '')
  const [postalCode, setPostalCode] = useState(address?.postalCode ?? '')
  const [landline, setLandline] = useState(address?.landline ?? '')

  useEffect(() => {
    const controller = new AbortController()

    async function load() {
      setLoadingLocations(true)
      try {
        const items = await listIranProvinces(controller.signal)
        if (controller.signal.aborted) return
        setProvinces(items)

        if (!address) return

        const province = matchProvinceByName(address.province, items)
        if (!province) return

        setProvinceSlug(province.slug)
        const cityItems = await listCitiesByProvinceSlug(province.slug, controller.signal)
        if (controller.signal.aborted) return
        setCities(cityItems)
        const matchedCity = matchCityByName(address.city, cityItems)
        setCity(
          matchedCity ? getLocationOptionLabel(matchedCity, locale) : address.city,
        )
      } catch {
        if (!controller.signal.aborted) setError(t('addresses.error.loadLocations'))
      } finally {
        if (!controller.signal.aborted) setLoadingLocations(false)
      }
    }

    void load()
    return () => controller.abort()
  }, [address, locale, t])

  async function handleProvinceChange(slug: string) {
    setProvinceSlug(slug)
    setCity('')
    setCities([])

    if (!slug) return

    try {
      const items = await listCitiesByProvinceSlug(slug)
      setCities(items)
    } catch {
      setError(t('addresses.error.loadCities'))
    }
  }

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

    const province = provinces.find((item) => item.slug === provinceSlug)
    if (!label.trim() || !province || !city.trim() || !street.trim()) {
      setError(t('addresses.error.incompleteForm'))
      return
    }

    const payload = {
      label: label.trim(),
      province: getLocationOptionLabel(province, locale),
      city: city.trim(),
      address: street.trim(),
      postalCode: postalCode.trim() || undefined,
      landline: landline.trim() || undefined,
    }

    setSaving(true)
    try {
      const result = address?.id
        ? await updateAddress(address.id, payload)
        : await createAddress(payload)
      onSaved(result.address)
    } catch (err) {
      setError(err instanceof ApiError ? err.message : t('addresses.error.save'))
    } finally {
      setSaving(false)
    }
  }

  return (
    <form
      className={[panelStyles.form, panelStyles.formInModal].join(' ')}
      onSubmit={(e) => void handleSubmit(e)}
    >
      {error && (
        <div className={panelStyles.error} role="alert">
          {error}
        </div>
      )}

      <div className={panelStyles.fieldRowTriple}>
        <div className={panelStyles.field}>
          <label htmlFor="address-label">{t('addresses.label')}</label>
          <input
            id="address-label"
            type="text"
            value={label}
            disabled={saving}
            onChange={(e) => setLabel(e.target.value)}
            placeholder={t('addresses.labelPlaceholder')}
          />
        </div>

        <div className={panelStyles.field}>
          <label htmlFor="address-province">{t('addresses.province')}</label>
          <select
            id="address-province"
            value={provinceSlug}
            disabled={loadingLocations || saving}
            onChange={(e) => void handleProvinceChange(e.target.value)}
          >
            <option value="">{t('addresses.selectProvince')}</option>
            {provinces.map((province) => (
              <option key={province.id} value={province.slug}>
                {getLocationOptionLabel(province, locale)}
              </option>
            ))}
          </select>
        </div>

        <div className={panelStyles.field}>
          <label htmlFor="address-city">{t('addresses.city')}</label>
          <select
            id="address-city"
            value={city}
            disabled={!provinceSlug || saving}
            onChange={(e) => setCity(e.target.value)}
          >
            <option value="">{t('addresses.selectCity')}</option>
            {cities.map((item) => (
              <option key={item.id} value={getLocationOptionLabel(item, locale)}>
                {getLocationOptionLabel(item, locale)}
              </option>
            ))}
          </select>
        </div>
      </div>

      <div className={panelStyles.field}>
        <label htmlFor="address-street">{t('addresses.address')}</label>
        <input
          id="address-street"
          type="text"
          value={street}
          disabled={saving}
          onChange={(e) => setStreet(e.target.value)}
          placeholder={t('addresses.streetPlaceholder')}
        />
      </div>

      <div className={panelStyles.fieldRow}>
        <div className={panelStyles.field}>
          <label htmlFor="address-postal">
            {t('addresses.postalCode')}
            <span className={panelStyles.optionalMark}> {t('addresses.optional')}</span>
          </label>
          <input
            id="address-postal"
            type="text"
            inputMode="numeric"
            value={postalCode}
            disabled={saving}
            onChange={(e) => setPostalCode(e.target.value)}
            placeholder={t('addresses.postalPlaceholder')}
            dir="ltr"
          />
        </div>

        <div className={panelStyles.field}>
          <label htmlFor="address-landline">
            {t('addresses.landline')}
            <span className={panelStyles.optionalMark}> {t('addresses.optional')}</span>
          </label>
          <input
            id="address-landline"
            type="tel"
            value={landline}
            disabled={saving}
            onChange={(e) => setLandline(e.target.value)}
            placeholder={t('addresses.landlinePlaceholder')}
            dir="ltr"
          />
        </div>
      </div>

      <div className={panelStyles.formActions}>
        <button
          type="button"
          className={panelStyles.cancelBtn}
          onClick={onCancel}
          disabled={saving}
        >
          {t('addresses.cancel')}
        </button>
        <button type="submit" className={panelStyles.saveBtn} disabled={saving}>
          {saving ? t('addresses.saving') : t('addresses.saveOne')}
        </button>
      </div>
    </form>
  )
}
