import { useEffect, useMemo, useState } from 'react'
import { Plus, Trash2 } from 'lucide-react'
import {
  AddressListEditor,
  createEmptyAddressItem,
  getLocationOptionLabel,
  matchCityByName,
  matchProvinceByName,
  useLocale,
  type AddressListItem,
} from '@meshkee/dashboard-ui'
import { Breadcrumbs } from '../components/Breadcrumbs'
import { ImageCropper } from '../components/ImageCropper'
import { MultiSelectDropdown } from '../components/MultiSelectDropdown'
import { RichTextEditor } from '../components/RichTextEditor'
import { useToast } from '../context/ToastContext'
import { useT } from '../i18n/useT'
import { ApiError } from '../lib/api'
import { dispatchBusinessProfileUpdated } from '../lib/businessContext'
import { listBusinessActivityCategories } from '../services/businessActivityCategoryService'
import type { BusinessActivityCategory } from '../services/businessActivityCategoryService'
import {
  getBusinessProfile,
  updateBusinessProfile,
  type BusinessPhoneNumber,
  type BusinessSocialMedia,
} from '../services/businessProfileService'
import {
  listCitiesByProvinceSlug,
  listIranProvinces,
  type CityOption,
} from '../services/citiesService'
import { resolveDataUrlToMediaId } from '../services/mediaService'
import { flattenBusinessActivityCategories } from '../utils/businessCategories'
import pageStyles from '../components/PageContent.module.css'
import formStyles from './AddNewProductPage.module.css'
import styles from './BusinessProfilePage.module.css'

type AddressDraft = AddressListItem

const EMPTY_SOCIAL: BusinessSocialMedia = {
  whatsapp: '',
  telegram: '',
  instagram: '',
  linkedin: '',
  youtube: '',
  aparat: '',
}

const SOCIAL_FIELDS = [
  ['whatsapp', 'WhatsApp'],
  ['telegram', 'Telegram'],
  ['instagram', 'Instagram'],
  ['linkedin', 'LinkedIn'],
  ['youtube', 'YouTube'],
  ['aparat', 'Aparat'],
] as const

function createEmptyPhone(): BusinessPhoneNumber {
  return { type: 'cell', number: '' }
}

export function BusinessProfilePage() {
  const { showToast } = useToast()
  const { locale } = useLocale()
  const t = useT()
  const [isLoading, setIsLoading] = useState(true)
  const [isSaving, setIsSaving] = useState(false)
  const [error, setError] = useState('')

  const [provinces, setProvinces] = useState<CityOption[]>([])
  const [citiesByProvince, setCitiesByProvince] = useState<Record<string, CityOption[]>>({})
  const [activityCategories, setActivityCategories] = useState<BusinessActivityCategory[]>([])
  const [categoryIds, setCategoryIds] = useState<string[]>([])
  const [nameEn, setNameEn] = useState('')
  const [nameFa, setNameFa] = useState('')
  const [email, setEmail] = useState('')
  const [about, setAbout] = useState('')
  const [vision, setVision] = useState('')
  const [logo, setLogo] = useState<string | null>(null)
  const [logoMediaId, setLogoMediaId] = useState<string | null>(null)
  const [addresses, setAddresses] = useState<AddressDraft[]>([createEmptyAddressItem()])
  const [phoneNumbers, setPhoneNumbers] = useState<BusinessPhoneNumber[]>([
    createEmptyPhone(),
  ])
  const [socialMedia, setSocialMedia] = useState<BusinessSocialMedia>(EMPTY_SOCIAL)

  const categoryOptions = useMemo(
    () => flattenBusinessActivityCategories(activityCategories),
    [activityCategories],
  )

  const addressLabels = useMemo(
    () => ({
      title: t('bizProfile.addresses'),
      addLabel: t('bizProfile.addresses.add'),
      province: t('bizProfile.province'),
      city: t('bizProfile.city'),
      address: t('bizProfile.address'),
      postalCode: t('bizProfile.postalCode'),
      landline: t('bizProfile.landline'),
      selectProvince: t('bizProfile.selectProvince'),
      selectCity: t('bizProfile.selectCity'),
      streetPlaceholder: t('bizProfile.streetPlaceholder'),
      postalPlaceholder: t('bizProfile.postalCode'),
      landlinePlaceholder: t('bizProfile.landline'),
      removeAriaLabel: t('bizProfile.removeAddress'),
    }),
    [t],
  )

  useEffect(() => {
    const controller = new AbortController()
    void loadData(controller.signal)
    return () => controller.abort()
  }, [])

  useEffect(() => {
    setAddresses((prev) =>
      prev.map((item) => {
        if (!item.provinceSlug) return item
        const province = provinces.find((p) => p.slug === item.provinceSlug)
        const cities = citiesByProvince[item.provinceSlug] ?? []
        const city = matchCityByName(item.city, cities)
        return {
          ...item,
          province: province ? getLocationOptionLabel(province, locale) : item.province,
          city: city ? getLocationOptionLabel(city, locale) : item.city,
        }
      }),
    )
  }, [locale, provinces, citiesByProvince])

  async function loadData(signal?: AbortSignal) {
    setIsLoading(true)
    setError('')

    try {
      const [categories, profileData, provinceItems] = await Promise.all([
        listBusinessActivityCategories(signal),
        getBusinessProfile(signal),
        listIranProvinces(signal),
      ])

      setProvinces(provinceItems)
      setActivityCategories(categories)
      setCategoryIds(profileData.profile.categoryIds)
      setNameEn(profileData.profile.nameEn)
      setNameFa(profileData.profile.nameFa)
      setEmail(profileData.profile.emails[0] ?? '')
      setAbout(profileData.profile.about)
      setVision(profileData.profile.vision)
      setLogo(profileData.profile.logoUrl)
      setLogoMediaId(profileData.profile.logoMediaId)

      const nextAddresses =
        profileData.addresses.length > 0
          ? profileData.addresses.map((item) => {
              const province = matchProvinceByName(item.province, provinceItems)
              return {
                id: item.id,
                provinceSlug: province?.slug ?? '',
                province: province
                  ? getLocationOptionLabel(province, locale)
                  : item.province,
                city: item.city,
                address: item.address,
                postalCode: item.postalCode,
                landline: item.landline ?? '',
              }
            })
          : [createEmptyAddressItem()]

      const slugs = [...new Set(nextAddresses.map((item) => item.provinceSlug).filter(Boolean))]
      const cityGroups = await Promise.all(
        slugs.map(async (slug) => ({
          slug,
          cities: await listCitiesByProvinceSlug(slug, signal),
        })),
      )
      const citiesMap = Object.fromEntries(cityGroups.map((group) => [group.slug, group.cities]))

      setAddresses(
        nextAddresses.map((item) => {
          if (!item.provinceSlug) return item
          const cities = citiesMap[item.provinceSlug] ?? []
          const city = matchCityByName(item.city, cities)
          return {
            ...item,
            city: city ? getLocationOptionLabel(city, locale) : item.city,
          }
        }),
      )
      setCitiesByProvince(citiesMap)

      setPhoneNumbers(
        profileData.profile.phoneNumbers.length > 0
          ? profileData.profile.phoneNumbers
          : [createEmptyPhone()],
      )
      setSocialMedia({ ...EMPTY_SOCIAL, ...profileData.profile.socialMedia })
    } catch (err) {
      if (err instanceof DOMException && err.name === 'AbortError') return
      if (err instanceof ApiError) {
        setError(err.message)
      } else {
        setError(t('bizProfile.loadError'))
      }
    } finally {
      setIsLoading(false)
    }
  }

  function updateAddress(index: number, patch: Partial<AddressDraft>) {
    setAddresses((prev) =>
      prev.map((item, i) => (i === index ? { ...item, ...patch } : item)),
    )
  }

  async function handleProvinceChange(index: number, provinceSlug: string) {
    const province = provinces.find((item) => item.slug === provinceSlug)
    updateAddress(index, {
      provinceSlug,
      province: province ? getLocationOptionLabel(province, locale) : '',
      city: '',
    })

    if (provinceSlug && !citiesByProvince[provinceSlug]) {
      const cities = await listCitiesByProvinceSlug(provinceSlug)
      setCitiesByProvince((prev) => ({ ...prev, [provinceSlug]: cities }))
    }
  }

  function addAddress() {
    setAddresses((prev) => [...prev, createEmptyAddressItem()])
  }

  function removeAddress(index: number) {
    setAddresses((prev) =>
      prev.length === 1 ? [createEmptyAddressItem()] : prev.filter((_, i) => i !== index),
    )
  }

  function updatePhone(index: number, patch: Partial<BusinessPhoneNumber>) {
    setPhoneNumbers((prev) =>
      prev.map((item, i) => (i === index ? { ...item, ...patch } : item)),
    )
  }

  function addPhone() {
    setPhoneNumbers((prev) => [...prev, createEmptyPhone()])
  }

  function removePhone(index: number) {
    setPhoneNumbers((prev) =>
      prev.length === 1 ? [createEmptyPhone()] : prev.filter((_, i) => i !== index),
    )
  }

  function updateSocial(field: keyof BusinessSocialMedia, value: string) {
    setSocialMedia((prev) => ({ ...prev, [field]: value }))
  }

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

    try {
      const nextLogoMediaId = await resolveDataUrlToMediaId(
        logo,
        'business-logo.png',
        logoMediaId,
      )

      const payloadAddresses = addresses
        .filter(
          (item) =>
            item.province.trim() ||
            item.city.trim() ||
            item.address.trim() ||
            item.postalCode.trim(),
        )
        .map((item) => ({
          id: item.id,
          province: item.province.trim(),
          city: item.city.trim(),
          address: item.address.trim(),
          postalCode: item.postalCode.trim(),
          landline: item.landline?.trim() || null,
        }))

      const payloadPhones = phoneNumbers
        .map((item) => ({
          type: item.type,
          number: item.number.trim(),
        }))
        .filter((item) => item.number)

      const trimmedEmail = email.trim()

      await updateBusinessProfile({
        nameEn: nameEn.trim(),
        nameFa: nameFa.trim(),
        about,
        vision,
        emails: trimmedEmail ? [trimmedEmail] : [],
        phoneNumbers: payloadPhones,
        socialMedia,
        logoMediaId: nextLogoMediaId,
        categoryIds,
        addresses: payloadAddresses,
      })

      showToast(t('bizProfile.toast.saved'), 'success')
      dispatchBusinessProfileUpdated()
      await loadData()
    } catch (err) {
      if (err instanceof ApiError) {
        setError(err.message)
      } else {
        setError(t('bizProfile.saveError'))
      }
    } finally {
      setIsSaving(false)
    }
  }

  if (isLoading) {
    return (
      <main className={pageStyles.content}>
        <p className={styles.status}>{t('bizProfile.loading')}</p>
      </main>
    )
  }

  return (
    <main className={pageStyles.content}>
      <Breadcrumbs items={[{ label: 'Dashboard', href: '/' }, { label: 'Business Profile' }]} />

      <div className={pageStyles.pageHeader}>
        <div>
          <h2 className={pageStyles.pageTitle}>{t('title.businessProfile')}</h2>
          <p className={pageStyles.pageSubtitle}>{t('bizProfile.subtitle')}</p>
        </div>
      </div>

      {error && (
        <div className={styles.alertError} role="alert">
          {error}
        </div>
      )}

      <form className={styles.form} onSubmit={(e) => void handleSubmit(e)}>
        <section className={styles.section}>
          <h3 className={styles.sectionTitle}>{t('bizProfile.section.basic')}</h3>
          <div className={formStyles.formGrid}>
            <div className={`${formStyles.field} ${styles.logoCol}`}>
              <label>{t('bizProfile.logo')}</label>
              <ImageCropper
                value={logo}
                onChange={setLogo}
                outputFormat="png"
                accept="image/png"
                uploadLabel={t('bizProfile.logo.upload')}
                hint={t('bizProfile.logo.hint')}
                changeLabel={t('bizProfile.logo.change')}
              />
            </div>

            <div className={styles.basicAside}>
              <div className={`${formStyles.field} ${styles.fullRow}`}>
                <label htmlFor="activity-categories">{t('bizProfile.categories')}</label>
                <MultiSelectDropdown
                  id="activity-categories"
                  options={categoryOptions}
                  value={categoryIds}
                  onChange={setCategoryIds}
                  placeholder={t('bizProfile.categories.placeholder')}
                  searchable
                  disabled={categoryOptions.length === 0}
                />
              </div>

              <div className={`${formStyles.field} ${styles.halfRow}`}>
                <label htmlFor="name-fa">{t('bizProfile.nameFa')}</label>
                <input
                  id="name-fa"
                  value={nameFa}
                  onChange={(e) => setNameFa(e.target.value)}
                  dir="rtl"
                  lang="fa"
                  className="faText"
                />
              </div>

              <div className={`${formStyles.field} ${styles.halfRow}`}>
                <label htmlFor="name-en">{t('bizProfile.nameEn')}</label>
                <input
                  id="name-en"
                  value={nameEn}
                  onChange={(e) => setNameEn(e.target.value)}
                  dir="ltr"
                  lang="en"
                />
              </div>

              <div className={`${formStyles.field} ${styles.halfRow}`}>
                <label htmlFor="email">{t('bizProfile.email')}</label>
                <input
                  id="email"
                  type="email"
                  value={email}
                  onChange={(e) => setEmail(e.target.value)}
                  placeholder="info@example.com"
                />
              </div>
            </div>

            <div className={`${formStyles.field} ${formStyles.col12}`}>
              <label>{t('bizProfile.about')}</label>
              <RichTextEditor value={about} onChange={setAbout} />
            </div>

            <div className={`${formStyles.field} ${formStyles.col12}`}>
              <label>{t('bizProfile.vision')}</label>
              <RichTextEditor value={vision} onChange={setVision} />
            </div>
          </div>
        </section>

        <section className={styles.section}>
          <h3 className={styles.sectionTitle}>{t('bizProfile.section.contact')}</h3>

          <div className={styles.duplicatorBlock}>
            <AddressListEditor
              addresses={addresses}
              provinces={provinces}
              citiesByProvince={citiesByProvince}
              onAddressChange={updateAddress}
              onProvinceChange={handleProvinceChange}
              onAdd={addAddress}
              onRemove={removeAddress}
              locale={locale}
              labels={addressLabels}
            />
          </div>

          <div className={styles.duplicatorBlock}>
            <div className={styles.sectionHeader}>
              <h4 className={styles.subTitle}>{t('bizProfile.phones')}</h4>
              <button type="button" className={styles.addBtn} onClick={addPhone}>
                <Plus size={16} />
                {t('bizProfile.phones.add')}
              </button>
            </div>

            <div className={styles.phoneGrid}>
              <div className={styles.gridHeader}>
                <span>{t('bizProfile.phones.type')}</span>
                <span>{t('bizProfile.phones.number')}</span>
                <span />
              </div>

              {phoneNumbers.map((item, index) => (
                <div key={`phone-${index}`} className={styles.gridRow}>
                  <select
                    className={styles.selectField}
                    value={item.type}
                    onChange={(e) =>
                      updatePhone(index, {
                        type: e.target.value as BusinessPhoneNumber['type'],
                      })
                    }
                  >
                    <option value="cell">{t('bizProfile.phones.cell')}</option>
                    <option value="landline">{t('bizProfile.phones.landline')}</option>
                  </select>

                  <input
                    className={styles.textField}
                    value={item.number}
                    onChange={(e) => updatePhone(index, { number: e.target.value })}
                    placeholder={t('bizProfile.phones.number')}
                  />

                  <button
                    type="button"
                    className={styles.removeBtn}
                    onClick={() => removePhone(index)}
                    aria-label={t('bizProfile.phones.remove')}
                  >
                    <Trash2 size={15} />
                  </button>
                </div>
              ))}
            </div>
          </div>
        </section>

        <section className={styles.section}>
          <h3 className={styles.sectionTitle}>{t('bizProfile.section.social')}</h3>
          <div className={formStyles.formGrid}>
            {SOCIAL_FIELDS.map(([key, label]) => (
              <div key={key} className={`${formStyles.field} ${formStyles.col4}`}>
                <label htmlFor={`social-${key}`}>{label}</label>
                <input
                  id={`social-${key}`}
                  value={socialMedia[key]}
                  onChange={(e) => updateSocial(key, e.target.value)}
                  placeholder={t('bizProfile.social.placeholder', { name: label })}
                />
              </div>
            ))}
          </div>
        </section>

        <div className={styles.actions}>
          <button type="submit" className={styles.saveBtn} disabled={isSaving}>
            {isSaving ? t('bizProfile.saving') : t('bizProfile.save')}
          </button>
        </div>
      </form>
    </main>
  )
}
