import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import {
  AlertTriangle,
  Database,
  FileText,
  Globe,
  Lock,
  Pencil,
  Plus,
  RotateCcw,
  Search,
  UserCog,
} from 'lucide-react'
import { ConfirmDeleteModal } from '../components/ConfirmDeleteModal'
import { BusinessActionsOverflowMenu } from '../components/BusinessActionsOverflowMenu'
import { ToggleSwitch } from '../components/ToggleSwitch'
import { formatCellForDisplay, toE164CellNumber } from '../lib/cellNumber'
import type {
  BusinessesListResponse,
  BusinessListItem,
  MigrateEntityResult,
  MigrateFromOldEntity,
  MigrateFromOldResponse,
  PurgeBusinessDataEntity,
  PurgeBusinessDataResponse,
  PurgeEntityResult,
} from '../types/business'
import type { BusinessCategory } from '../types/category'
import type { ListBusinessesParams } from '../services/businessService'
import { ApiError, isAbortError } from '../lib/api'
import {
  addBusinessDomain,
  createBusiness,
  listBusinesses,
  migrateBusinessFromOld,
  purgeBusinessData,
  removeBusiness,
  setBusinessActive,
  updateBusiness,
  updateBusinessDomain,
} from '../services/businessService'
import { listBusinessCategories } from '../services/categoryService'
import { Modal } from '../components/Modal'
import { MultiSelectDropdown } from '../components/MultiSelectDropdown'
import { PrimaryColorPicker } from '../components/PrimaryColorPicker'
import { PrimaryColorSwatchControl } from '../components/PrimaryColorSwatchControl'
import { useToast } from '../context/ToastContext'
import {
  DEFAULT_BUSINESS_PRIMARY_COLOR_ID,
  normalizeBusinessPrimaryColorId,
  type BusinessPrimaryColorId,
} from '../utils/businessPrimaryColors'
import {
  getBusinessSettings,
  updateBusinessBranding,
  updateBusinessDefaultLocale,
  updateBusinessPrimaryColor,
  type DashboardLocale,
} from '../services/businessSettingsService'
import { flattenBusinessCategories } from '../utils/categories'
import { Pagination } from '@meshkee/dashboard-ui'
import pageStyles from '../components/PageContent.module.css'
import styles from './BusinessesPage.module.css'

const DEFAULT_PAGE_SIZE = 10
const DEFAULT_LOCALE: DashboardLocale = 'fa'

function normalizeDefaultLocale(value: unknown): DashboardLocale {
  return value === 'en' || value === 'fa' ? value : DEFAULT_LOCALE
}

function formatDate(value: string) {
  const d = new Date(value)
  if (Number.isNaN(d.getTime())) return value
  return d.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: '2-digit' })
}

const MIGRATE_ENTITY_LABELS: Record<MigrateFromOldEntity, string> = {
  product_categories: 'Product categories',
  product: 'Products',
  customer_categories: 'Customer categories',
  customer: 'Customers',
  blog_categories: 'Blog categories',
  blog: 'Blogs',
  portfolio_categories: 'Portfolio categories',
  portfolio: 'Portfolios',
}

const DATA_ENTITY_GROUPS = [
  {
    title: 'Products',
    items: [
      ['product_categories', 'Categories'],
      ['product', 'Products'],
    ],
  },
  {
    title: 'Customers',
    items: [
      ['customer_categories', 'Categories'],
      ['customer', 'Customers'],
    ],
  },
  {
    title: 'Blogs',
    items: [
      ['blog_categories', 'Categories'],
      ['blog', 'Blogs'],
    ],
  },
  {
    title: 'Portfolios',
    items: [
      ['portfolio_categories', 'Categories'],
      ['portfolio', 'Portfolios'],
    ],
  },
] as const

function formatMigrateEntityResult(result: MigrateEntityResult): string {
  if ('created' in result) {
    const base = `${result.created} created, ${result.skipped} skipped (${result.total} total)`
    const extras = [
      result.imagesCopied != null ? `${result.imagesCopied} images copied` : null,
      result.imagesResized != null && result.imagesResized > 0
        ? `${result.imagesResized} resized (≤1280px)`
        : null,
      result.titlesUpdated != null && result.titlesUpdated > 0
        ? `${result.titlesUpdated} titles updated`
        : null,
      result.imagesFailed != null && result.imagesFailed > 0
        ? `${result.imagesFailed} images failed`
        : null,
      result.skippedInvalidCell != null && result.skippedInvalidCell > 0
        ? `${result.skippedInvalidCell} invalid/missing cell`
        : null,
      result.skippedAlreadyLinked != null && result.skippedAlreadyLinked > 0
        ? `${result.skippedAlreadyLinked} already linked`
        : null,
      result.skippedCreateFailed != null && result.skippedCreateFailed > 0
        ? `${result.skippedCreateFailed} create failed`
        : null,
    ].filter(Boolean)
    return extras.length ? `${base}; ${extras.join(', ')}` : base
  }
  return 'Not implemented yet'
}

function formatPurgeEntityResult(result: PurgeEntityResult): string {
  if ('deleted' in result) {
    const extras = [
      result.imagesDeleted != null ? `${result.imagesDeleted} images deleted` : null,
    ].filter(Boolean)
    const base = `${result.deleted} deleted`
    return extras.length ? `${base}; ${extras.join(', ')}` : base
  }
  return 'Not implemented yet'
}

function emptyMigrateEntities(): Record<MigrateFromOldEntity, boolean> {
  return {
    product_categories: false,
    product: false,
    customer_categories: false,
    customer: false,
    blog_categories: false,
    blog: false,
    portfolio_categories: false,
    portfolio: false,
  }
}

export function BusinessesPage() {
  const { showToast } = useToast()
  const navigate = useNavigate()
  const [data, setData] = useState<BusinessesListResponse | null>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState('')

  const [categories, setCategories] = useState<BusinessCategory[]>([])

  const [appliedFilters, setAppliedFilters] = useState<Omit<ListBusinessesParams, 'page' | 'pageSize'>>(
    {},
  )
  const [page, setPage] = useState(1)
  const [pageSize] = useState(DEFAULT_PAGE_SIZE)

  const [draftName, setDraftName] = useState('')
  const [draftDomain, setDraftDomain] = useState('')
  const [draftCategory, setDraftCategory] = useState('')

  const [editOpen, setEditOpen] = useState(false)
  const [editBusiness, setEditBusiness] = useState<BusinessListItem | null>(null)
  const [editName, setEditName] = useState('')
  const [editPrimaryColor, setEditPrimaryColor] = useState<BusinessPrimaryColorId>(
    DEFAULT_BUSINESS_PRIMARY_COLOR_ID,
  )
  const [editDefaultLocale, setEditDefaultLocale] = useState<DashboardLocale>(DEFAULT_LOCALE)
  const [editLoadingSettings, setEditLoadingSettings] = useState(false)
  const [editSubmitting, setEditSubmitting] = useState(false)
  const [editError, setEditError] = useState('')

  const [domainOpen, setDomainOpen] = useState(false)
  const [domainBusiness, setDomainBusiness] = useState<BusinessListItem | null>(null)
  const [domainId, setDomainId] = useState<number | null>(null)
  const [domainHost, setDomainHost] = useState('')
  const [domainSubmitting, setDomainSubmitting] = useState(false)
  const [domainError, setDomainError] = useState('')

  const [createOpen, setCreateOpen] = useState(false)
  const [createName, setCreateName] = useState('')
  const [createNameFa, setCreateNameFa] = useState('')
  const [createAbout, setCreateAbout] = useState('')
  const [createCategoryIds, setCreateCategoryIds] = useState<number[]>([])
  const [createOwnerFirstName, setCreateOwnerFirstName] = useState('')
  const [createOwnerLastName, setCreateOwnerLastName] = useState('')
  const [createOwnerFirstNameEn, setCreateOwnerFirstNameEn] = useState('')
  const [createOwnerLastNameEn, setCreateOwnerLastNameEn] = useState('')
  const [createOwnerCell, setCreateOwnerCell] = useState('')
  const [createOwnerPassword, setCreateOwnerPassword] = useState('')
  const [createSubmitting, setCreateSubmitting] = useState(false)
  const [createError, setCreateError] = useState('')

  const [removeTarget, setRemoveTarget] = useState<BusinessListItem | null>(null)
  const [togglingId, setTogglingId] = useState<string | null>(null)
  const [savingColorId, setSavingColorId] = useState<string | null>(null)
  const [savingLocaleId, setSavingLocaleId] = useState<string | null>(null)

  const [migrateOpen, setMigrateOpen] = useState(false)
  const [migrateBusiness, setMigrateBusiness] = useState<BusinessListItem | null>(null)
  const [migrateOldId, setMigrateOldId] = useState('')
  const [migrateEntities, setMigrateEntities] = useState<Record<MigrateFromOldEntity, boolean>>(
    () => emptyMigrateEntities(),
  )
  const [migrateSubmitting, setMigrateSubmitting] = useState(false)
  const [migrateError, setMigrateError] = useState('')
  const [migrateResult, setMigrateResult] = useState<MigrateFromOldResponse | null>(null)

  const [purgeOpen, setPurgeOpen] = useState(false)
  const [purgeBusiness, setPurgeBusiness] = useState<BusinessListItem | null>(null)
  const [purgeEntities, setPurgeEntities] = useState<Record<PurgeBusinessDataEntity, boolean>>(
    () => emptyMigrateEntities(),
  )
  const [purgeSubmitting, setPurgeSubmitting] = useState(false)
  const [purgeError, setPurgeError] = useState('')
  const [purgeResult, setPurgeResult] = useState<PurgeBusinessDataResponse | null>(null)

  async function fetchList() {
    setLoading(true)
    setError('')
    try {
      const result = await listBusinesses({
        page,
        pageSize,
        ...appliedFilters,
      })
      setData(result)
    } catch (err) {
      setError(err instanceof ApiError ? err.message : 'Unable to load businesses.')
    } finally {
      setLoading(false)
    }
  }

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

    async function load() {
      setLoading(true)
      setError('')
      try {
        const [result, categoryResult] = await Promise.all([
          listBusinesses(
            {
              page,
              pageSize,
              ...appliedFilters,
            },
            controller.signal,
          ),
          listBusinessCategories(controller.signal),
        ])
        if (controller.signal.aborted) return
        setData(result)
        setCategories(categoryResult.items)
      } catch (err) {
        if (isAbortError(err) || controller.signal.aborted) return
        setError(err instanceof ApiError ? err.message : 'Unable to load businesses.')
      } finally {
        if (!controller.signal.aborted) setLoading(false)
      }
    }

    void load()

    return () => {
      controller.abort()
    }
  }, [page, pageSize, appliedFilters.name, appliedFilters.domain, appliedFilters.category])

  const totalPages = useMemo(() => {
    const total = data?.total ?? 0
    return Math.max(1, Math.ceil(total / pageSize))
  }, [data?.total, pageSize])

  const showingFrom = useMemo(() => {
    if (!data) return 0
    return (page - 1) * pageSize + 1
  }, [data, page, pageSize])

  const showingTo = useMemo(() => {
    if (!data) return 0
    return Math.min(data.total, page * pageSize)
  }, [data, page, pageSize])

  const categoryOptions = useMemo(() => flattenBusinessCategories(categories), [categories])

  function applyFilters() {
    setPage(1)
    setAppliedFilters({
      ...(draftName.trim() ? { name: draftName.trim() } : {}),
      ...(draftDomain.trim() ? { domain: draftDomain.trim() } : {}),
      ...(draftCategory.trim() ? { category: draftCategory.trim() } : {}),
    })
  }

  function clearFilters() {
    setDraftName('')
    setDraftDomain('')
    setDraftCategory('')
    setPage(1)
    setAppliedFilters({})
  }

  function openEdit(b: BusinessListItem) {
    setEditBusiness(b)
    setEditName(b.name)
    setEditPrimaryColor(normalizeBusinessPrimaryColorId(b.primaryColor))
    setEditDefaultLocale(normalizeDefaultLocale(b.defaultLocale))
    setEditError('')
    setEditOpen(true)
    setEditLoadingSettings(true)

    const controller = new AbortController()
    void getBusinessSettings(b.id, controller.signal)
      .then((data) => {
        setEditPrimaryColor(data.settings.branding.primaryColor)
        setEditDefaultLocale(normalizeDefaultLocale(data.settings.branding.defaultLocale))
      })
      .catch((err) => {
        if (isAbortError(err)) return
        setEditError(err instanceof ApiError ? err.message : 'Unable to load business theme.')
      })
      .finally(() => {
        if (!controller.signal.aborted) setEditLoadingSettings(false)
      })
  }

  function goToBusinessUsers(b: BusinessListItem, membership: 'staff' | 'all') {
    const params = new URLSearchParams({
      businessId: String(b.id),
      membership,
      businessName: b.name,
    })
    navigate(`/users?${params.toString()}`)
  }

  async function handlePrimaryColorChange(
    b: BusinessListItem,
    primaryColor: BusinessPrimaryColorId,
  ) {
    const currentColor = normalizeBusinessPrimaryColorId(b.primaryColor)
    if (currentColor === primaryColor) return

    setSavingColorId(b.id)
    setError('')

    setData((prev) => {
      if (!prev) return prev
      return {
        ...prev,
        items: prev.items.map((item) =>
          item.id === b.id ? { ...item, primaryColor } : item,
        ),
      }
    })

    if (editBusiness?.id === b.id) {
      setEditPrimaryColor(primaryColor)
    }

    try {
      await updateBusinessPrimaryColor(b.id, primaryColor)
      showToast(`Theme updated for "${b.name}".`, 'success')
    } catch (err) {
      setData((prev) => {
        if (!prev) return prev
        return {
          ...prev,
          items: prev.items.map((item) =>
            item.id === b.id ? { ...item, primaryColor: currentColor } : item,
          ),
        }
      })

      if (editBusiness?.id === b.id) {
        setEditPrimaryColor(currentColor)
      }

      showToast(
        err instanceof ApiError ? err.message : 'Unable to update theme.',
        'error',
      )
    } finally {
      setSavingColorId(null)
    }
  }

  async function handleDefaultLocaleChange(b: BusinessListItem, defaultLocale: DashboardLocale) {
    const currentLocale = normalizeDefaultLocale(b.defaultLocale)
    if (currentLocale === defaultLocale) return

    setSavingLocaleId(b.id)
    setError('')

    setData((prev) => {
      if (!prev) return prev
      return {
        ...prev,
        items: prev.items.map((item) =>
          item.id === b.id ? { ...item, defaultLocale } : item,
        ),
      }
    })

    if (editBusiness?.id === b.id) {
      setEditDefaultLocale(defaultLocale)
    }

    try {
      await updateBusinessDefaultLocale(b.id, defaultLocale)
      showToast(`Default language updated for "${b.name}".`, 'success')
    } catch (err) {
      setData((prev) => {
        if (!prev) return prev
        return {
          ...prev,
          items: prev.items.map((item) =>
            item.id === b.id ? { ...item, defaultLocale: currentLocale } : item,
          ),
        }
      })

      if (editBusiness?.id === b.id) {
        setEditDefaultLocale(currentLocale)
      }

      showToast(
        err instanceof ApiError ? err.message : 'Unable to update default language.',
        'error',
      )
    } finally {
      setSavingLocaleId(null)
    }
  }

  async function submitEdit() {
    if (!editBusiness) return
    setEditSubmitting(true)
    setEditError('')
    try {
      await updateBusiness(editBusiness.id, { name: editName })
      await updateBusinessBranding(editBusiness.id, {
        primaryColor: editPrimaryColor,
        defaultLocale: editDefaultLocale,
      })
      setData((prev) => {
        if (!prev) return prev
        return {
          ...prev,
          items: prev.items.map((item) =>
            item.id === editBusiness.id
              ? {
                  ...item,
                  name: editName.trim(),
                  primaryColor: editPrimaryColor,
                  defaultLocale: editDefaultLocale,
                }
              : item,
          ),
        }
      })
      setEditOpen(false)
      setEditBusiness(null)
      showToast('Business updated.', 'success')
      await fetchList()
    } catch (err) {
      setEditError(err instanceof ApiError ? err.message : 'Unable to update business.')
    } finally {
      setEditSubmitting(false)
    }
  }

  function openDomainEdit(b: BusinessListItem) {
    setDomainBusiness(b)
    setDomainId(b.domainId)
    setDomainHost(b.domain ?? '')
    setDomainError('')
    setDomainOpen(true)
  }

  function openMigrate(b: BusinessListItem) {
    setMigrateBusiness(b)
    setMigrateOldId(b.oldBusinessId != null ? String(b.oldBusinessId) : '')
    setMigrateEntities(emptyMigrateEntities())
    setMigrateError('')
    setMigrateResult(null)
    setMigrateOpen(true)
  }

  const migrateSubmittingRef = useRef(false)
  migrateSubmittingRef.current = migrateSubmitting

  const closeMigrate = useCallback(() => {
    if (migrateSubmittingRef.current) return
    setMigrateOpen(false)
    setMigrateBusiness(null)
    setMigrateError('')
    setMigrateResult(null)
  }, [])

  function selectMigrateEntity(entity: MigrateFromOldEntity) {
    setMigrateResult(null)
    setMigrateError('')
    setMigrateEntities({ ...emptyMigrateEntities(), [entity]: true })
  }

  async function submitMigrate() {
    if (!migrateBusiness) return
    const oldBusinessId = Number(String(migrateOldId).trim())
    if (!Number.isInteger(oldBusinessId) || oldBusinessId <= 0) {
      setMigrateResult(null)
      setMigrateError('Enter a valid old business id (positive integer).')
      return
    }

    const entities = (Object.keys(migrateEntities) as MigrateFromOldEntity[]).filter(
      (key) => migrateEntities[key],
    )
    if (entities.length === 0) {
      setMigrateResult(null)
      setMigrateError('Select a data type to migrate.')
      return
    }

    setMigrateSubmitting(true)
    setMigrateError('')
    setMigrateResult(null)
    try {
      const result = await migrateBusinessFromOld(migrateBusiness.id, {
        oldBusinessId,
        entities,
      })
      setData((prev) => {
        if (!prev) return prev
        return {
          ...prev,
          items: prev.items.map((item) =>
            item.id === migrateBusiness.id
              ? { ...item, oldBusinessId: String(oldBusinessId) }
              : item,
          ),
        }
      })
      setMigrateResult(result)
    } catch (err) {
      setMigrateError(
        err instanceof ApiError ? err.message : 'Unable to migrate data from old CMS.',
      )
    } finally {
      setMigrateSubmitting(false)
    }
  }

  function openPurge(b: BusinessListItem) {
    setPurgeBusiness(b)
    setPurgeEntities(emptyMigrateEntities())
    setPurgeError('')
    setPurgeResult(null)
    setPurgeOpen(true)
  }

  const purgeSubmittingRef = useRef(false)
  purgeSubmittingRef.current = purgeSubmitting

  const closePurge = useCallback(() => {
    if (purgeSubmittingRef.current) return
    setPurgeOpen(false)
    setPurgeBusiness(null)
    setPurgeError('')
    setPurgeResult(null)
  }, [])

  function selectPurgeEntity(entity: PurgeBusinessDataEntity) {
    setPurgeResult(null)
    setPurgeError('')
    setPurgeEntities({ ...emptyMigrateEntities(), [entity]: true })
  }

  async function submitPurge() {
    if (!purgeBusiness) return
    const entities = (Object.keys(purgeEntities) as PurgeBusinessDataEntity[]).filter(
      (key) => purgeEntities[key],
    )
    if (entities.length === 0) {
      setPurgeResult(null)
      setPurgeError('Select a data type to delete.')
      return
    }

    setPurgeSubmitting(true)
    setPurgeError('')
    setPurgeResult(null)
    try {
      const result = await purgeBusinessData(purgeBusiness.id, { entities })
      setPurgeResult(result)
      showToast(result.message, 'success')
    } catch (err) {
      setPurgeError(
        err instanceof ApiError ? err.message : 'Unable to delete selected business data.',
      )
    } finally {
      setPurgeSubmitting(false)
    }
  }

  async function submitDomain() {
    if (!domainBusiness) return
    const host = domainHost.trim()
    if (!host) return

    setDomainSubmitting(true)
    setDomainError('')
    try {
      if (domainId) {
        await updateBusinessDomain(domainBusiness.id, domainId, { host })
        setData((prev) => {
          if (!prev) return prev
          return {
            ...prev,
            items: prev.items.map((item) =>
              item.id === domainBusiness.id ? { ...item, domain: host } : item,
            ),
          }
        })
        showToast(`Domain updated to "${host}".`, 'success')
      } else {
        const created = (await addBusinessDomain(domainBusiness.id, {
          host,
          isPrimary: true,
        })) as { id: number; host: string; sslEnabled: boolean }
        setData((prev) => {
          if (!prev) return prev
          return {
            ...prev,
            items: prev.items.map((item) =>
              item.id === domainBusiness.id
                ? {
                    ...item,
                    domainId: created.id,
                    domain: created.host,
                    sslEnabled: created.sslEnabled ?? false,
                  }
                : item,
            ),
          }
        })
        showToast(`Domain "${host}" added.`, 'success')
      }
      setDomainOpen(false)
      setDomainBusiness(null)
      setDomainId(null)
    } catch (err) {
      setDomainError(err instanceof ApiError ? err.message : 'Unable to save domain.')
    } finally {
      setDomainSubmitting(false)
    }
  }

  function resetCreateForm() {
    setCreateName('')
    setCreateNameFa('')
    setCreateAbout('')
    setCreateCategoryIds([])
    setCreateOwnerFirstName('')
    setCreateOwnerLastName('')
    setCreateOwnerFirstNameEn('')
    setCreateOwnerLastNameEn('')
    setCreateOwnerCell('')
    setCreateOwnerPassword('')
    setCreateError('')
  }

  function openCreate() {
    resetCreateForm()
    setCreateOpen(true)
  }

  async function submitCreate() {
    const ownerCellNumber = toE164CellNumber(createOwnerCell.trim())
    if (!ownerCellNumber) return

    setCreateSubmitting(true)
    setCreateError('')
    try {
      await createBusiness({
        name: createName.trim(),
        nameFa: createNameFa.trim(),
        about: createAbout.trim() || undefined,
        categoryIds: createCategoryIds,
        ownerFirstName: createOwnerFirstName.trim(),
        ownerLastName: createOwnerLastName.trim(),
        ownerFirstNameEn: createOwnerFirstNameEn.trim(),
        ownerLastNameEn: createOwnerLastNameEn.trim(),
        ownerCellNumber,
        ownerPassword: createOwnerPassword,
      })
      setCreateOpen(false)
      resetCreateForm()
      showToast(`"${createName.trim()}" has been created.`, 'success')
      await fetchList()
    } catch (err) {
      setCreateError(err instanceof ApiError ? err.message : 'Unable to create business.')
    } finally {
      setCreateSubmitting(false)
    }
  }

  async function handleToggleActive(b: BusinessListItem, isActive: boolean) {
    setTogglingId(b.id)
    setError('')

    setData((prev) => {
      if (!prev) return prev
      return {
        ...prev,
        items: prev.items.map((item) => (item.id === b.id ? { ...item, isActive } : item)),
      }
    })

    try {
      await setBusinessActive(b.id, { isActive })
      showToast(`"${b.name}" has been ${isActive ? 'enabled' : 'disabled'}.`, 'success')
    } catch (err) {
      setData((prev) => {
        if (!prev) return prev
        return {
          ...prev,
          items: prev.items.map((item) =>
            item.id === b.id ? { ...item, isActive: !isActive } : item,
          ),
        }
      })
      setError(err instanceof ApiError ? err.message : 'Unable to update business status.')
    } finally {
      setTogglingId(null)
    }
  }

  async function confirmRemove() {
    if (!removeTarget) return
    setError('')
    try {
      await removeBusiness(removeTarget.id)
      setRemoveTarget(null)
      await fetchList()
    } catch (err) {
      setError(err instanceof ApiError ? err.message : 'Unable to remove business.')
    }
  }

  const canSubmitCreate =
    createName.trim().length >= 2 &&
    createNameFa.trim().length >= 2 &&
    createCategoryIds.length > 0 &&
    createOwnerFirstName.trim().length >= 2 &&
    createOwnerLastName.trim().length >= 2 &&
    createOwnerFirstNameEn.trim().length >= 2 &&
    createOwnerLastNameEn.trim().length >= 2 &&
    toE164CellNumber(createOwnerCell.trim()).length > 0 &&
    createOwnerPassword.length >= 8

  const canSubmitMigrate =
    Number.isInteger(Number(String(migrateOldId).trim())) &&
    Number(String(migrateOldId).trim()) > 0 &&
    Object.values(migrateEntities).some(Boolean)

  const canSubmitPurge = Object.values(purgeEntities).some(Boolean)

  return (
    <main className={pageStyles.content}>
      <div className={pageStyles.pageHeader}>
        <div>
          <h2 className={pageStyles.pageTitle}>Businesses</h2>
          <p className={pageStyles.pageSubtitle}>
            Manage businesses, domains, and SSL settings.
          </p>
        </div>
      </div>

      <div className={styles.filtersPanel}>
        <div className={styles.filtersTitle}>Filters</div>

        <div className={styles.filtersGrid}>
          <div className={styles.filtersInputs}>
            <div className={`${styles.field} ${styles.fieldCol3}`}>
              <label htmlFor="filter-name">Name</label>
              <input
                id="filter-name"
                value={draftName}
                onChange={(e) => setDraftName(e.target.value)}
                placeholder="Search by business name"
              />
            </div>

            <div className={`${styles.field} ${styles.fieldCol3}`}>
              <label htmlFor="filter-domain">Domain</label>
              <input
                id="filter-domain"
                value={draftDomain}
                onChange={(e) => setDraftDomain(e.target.value)}
                placeholder="shop-a.local"
              />
            </div>

            <div className={`${styles.field} ${styles.fieldCol3}`}>
              <label htmlFor="filter-category">Category</label>
              <input
                id="filter-category"
                value={draftCategory}
                onChange={(e) => setDraftCategory(e.target.value)}
                placeholder="e.g. electronics / phones"
              />
            </div>
          </div>

          <div className={styles.filterActions}>
            <button
              type="button"
              className={`${styles.iconActionBtn} ${styles.iconActionBtnPrimary}`}
              onClick={applyFilters}
              disabled={loading}
              aria-label="Search"
              title="Search"
            >
              <Search size={18} />
            </button>
            <button
              type="button"
              className={`${styles.iconActionBtn} ${styles.iconActionBtnGhost}`}
              onClick={clearFilters}
              disabled={loading}
              aria-label="Clear filters"
              title="Clear filters"
            >
              <RotateCcw size={18} />
            </button>
          </div>
        </div>
      </div>

      <div className={styles.tablePanel}>
        <div className={styles.tableWrap}>
          <div className={styles.tableHeader}>
            <div className={styles.tableHeaderTitle}>Business list</div>
            <div className={styles.meta}>
              {data ? (
                <>
                  Showing {showingFrom} - {showingTo} of {data.total}
                </>
              ) : (
                ' '
              )}
            </div>
          </div>

          {error && (
            <div style={{ padding: 16 }}>
              <div className={styles.meta} style={{ color: '#b91c1c' }}>
                {error}
              </div>
            </div>
          )}

          <div style={{ overflowX: 'auto' }}>
            <table className={styles.table}>
              <thead>
                <tr>
                  <th className={styles.th}>Name</th>
                  <th className={styles.th}>Date created</th>
                  <th className={styles.th}>Domain</th>
                  <th className={styles.th}>Owner</th>
                  <th className={`${styles.th} ${styles.thTheme}`}>Theme</th>
                  <th className={`${styles.th} ${styles.thLocale}`}>Lang</th>
                  <th className={`${styles.th} ${styles.thActions}`}>Actions</th>
                </tr>
              </thead>
              <tbody>
                {loading && (
                  <tr>
                    <td className={styles.td} colSpan={7}>
                      Loading...
                    </td>
                  </tr>
                )}

                {!loading && data?.items?.length === 0 && (
                  <tr>
                    <td className={styles.td} colSpan={7}>
                      No results found.
                    </td>
                  </tr>
                )}

                {!loading &&
                  data?.items?.map((b) => (
                    <tr key={b.id}>
                      <td className={styles.td}>{b.name}</td>
                      <td className={styles.td}>{formatDate(b.createdAt)}</td>
                      <td className={styles.td}>
                        {b.domain ? (
                          <div className={styles.domainCell}>
                            <span>{b.domain}</span>
                            {b.sslEnabled ? (
                              <span
                                className={styles.sslIcon}
                                title="SSL certificate valid"
                                aria-label="SSL certificate valid"
                              >
                                <Lock size={16} className={styles.sslOk} aria-hidden="true" />
                              </span>
                            ) : (
                              <span
                                className={styles.sslIcon}
                                title="SSL certificate missing or invalid"
                                aria-label="SSL certificate missing or invalid"
                              >
                                <AlertTriangle
                                  size={16}
                                  className={styles.sslWarn}
                                  aria-hidden="true"
                                />
                              </span>
                            )}
                          </div>
                        ) : (
                          <span className={styles.subText}>No domain</span>
                        )}
                      </td>
                      <td className={styles.td}>
                        <div className={styles.ownerCell}>
                          <div className={styles.ownerName}>{b.ownerNameEn || '—'}</div>
                          <div className={styles.ownerPhone}>
                            {b.ownerCellNumber ? formatCellForDisplay(b.ownerCellNumber) : '—'}
                          </div>
                        </div>
                      </td>
                      <td className={`${styles.td} ${styles.tdTheme}`}>
                        <PrimaryColorSwatchControl
                          value={normalizeBusinessPrimaryColorId(b.primaryColor)}
                          disabled={savingColorId === b.id}
                          onChange={(primaryColor) =>
                            void handlePrimaryColorChange(b, primaryColor)
                          }
                        />
                      </td>
                      <td className={`${styles.td} ${styles.tdLocale}`}>
                        <select
                          className={styles.localeSelect}
                          value={normalizeDefaultLocale(b.defaultLocale)}
                          disabled={savingLocaleId === b.id}
                          aria-label={`Default language for ${b.name}`}
                          onChange={(e) =>
                            void handleDefaultLocaleChange(
                              b,
                              normalizeDefaultLocale(e.target.value),
                            )
                          }
                        >
                          <option value="fa">FA</option>
                          <option value="en">EN</option>
                        </select>
                      </td>
                      <td className={`${styles.td} ${styles.tdActions}`}>
                        <div className={styles.rowActions}>
                          <span className={styles.toggleInActions}>
                            <ToggleSwitch
                              checked={b.isActive}
                              disabled={togglingId === b.id}
                              ariaLabel={`${b.isActive ? 'Disable' : 'Enable'} ${b.name}`}
                              onChange={(isActive) => void handleToggleActive(b, isActive)}
                            />
                          </span>
                          <button
                            type="button"
                            className={styles.controlBtn}
                            onClick={() => navigate(`/businesses/${b.id}/invoices`)}
                            title="Invoices"
                            aria-label="View invoices"
                          >
                            <FileText size={16} />
                          </button>
                          <button
                            type="button"
                            className={styles.controlBtn}
                            onClick={() => goToBusinessUsers(b, 'staff')}
                            title="Staff"
                            aria-label="View staff"
                          >
                            <UserCog size={16} />
                          </button>
                          <button
                            type="button"
                            className={styles.controlBtn}
                            onClick={(e) => {
                              e.preventDefault()
                              e.stopPropagation()
                              openMigrate(b)
                            }}
                            title="Migrate from old CMS"
                            aria-label="Migrate from old CMS"
                          >
                            <Database size={16} />
                          </button>
                          <button
                            type="button"
                            className={styles.controlBtn}
                            onClick={() => openEdit(b)}
                            title="Edit"
                            aria-label="Edit"
                          >
                            <Pencil size={16} />
                          </button>
                          <button
                            type="button"
                            className={styles.controlBtn}
                            onClick={() => openDomainEdit(b)}
                            title="Edit domain"
                            aria-label="Edit domain"
                          >
                            <Globe size={16} />
                          </button>
                          <BusinessActionsOverflowMenu
                            businessName={b.name}
                            onAllUsers={() => goToBusinessUsers(b, 'all')}
                            onWipeData={() => openPurge(b)}
                            onRemove={() => setRemoveTarget(b)}
                          />
                        </div>
                      </td>
                    </tr>
                  ))}
              </tbody>
            </table>
          </div>

          <div className={styles.pagination}>
            <div>
              Page {page} / {totalPages} · {pageSize} per page · {data?.total ?? 0} total
            </div>
            <Pagination
              currentPage={page}
              totalPages={totalPages}
              onPageChange={setPage}
              disabled={loading}
              variant="inline"
            />
          </div>
        </div>
      </div>

      <button
        type="button"
        className={styles.fab}
        onClick={openCreate}
        aria-label="Add business"
        title="Add business"
      >
        <Plus size={24} />
      </button>

      <Modal
        open={editOpen}
        title="Edit business"
        onClose={() => {
          setEditOpen(false)
          setEditBusiness(null)
          setEditError('')
        }}
      >
        {editError ? (
          <p className={styles.alertError} role="alert">
            {editError}
          </p>
        ) : null}
        <div className={styles.field}>
          <label htmlFor="edit-name">Business name</label>
          <input
            id="edit-name"
            value={editName}
            onChange={(e) => setEditName(e.target.value)}
            disabled={editSubmitting}
          />
        </div>
        <div className={styles.field}>
          <label>Dashboard primary color</label>
          {editLoadingSettings ? (
            <p className={styles.helperText}>Loading theme...</p>
          ) : (
            <PrimaryColorPicker
              value={editPrimaryColor}
              onChange={setEditPrimaryColor}
              disabled={editSubmitting}
            />
          )}
        </div>
        <div className={styles.field}>
          <label htmlFor="edit-default-locale">Default dashboard language</label>
          {editLoadingSettings ? (
            <p className={styles.helperText}>Loading language...</p>
          ) : (
            <select
              id="edit-default-locale"
              className={styles.localeSelect}
              value={editDefaultLocale}
              disabled={editSubmitting}
              onChange={(e) => setEditDefaultLocale(normalizeDefaultLocale(e.target.value))}
            >
              <option value="fa">Farsi (FA)</option>
              <option value="en">English (EN)</option>
            </select>
          )}
          <p className={styles.helperText}>
            Business and customer dashboards open in this language.
          </p>
        </div>
        <div style={{ height: 12 }} />
        <div className={styles.actionsRow}>
          <button
            type="button"
            className={`${styles.btn} ${styles.btnGhost}`}
            onClick={() => setEditOpen(false)}
            disabled={editSubmitting}
          >
            Cancel
          </button>
          <button
            type="button"
            className={`${styles.btn} ${styles.btnPrimary}`}
            onClick={() => void submitEdit()}
            disabled={editSubmitting || !editName.trim() || editLoadingSettings}
          >
            Save
          </button>
        </div>
      </Modal>

      <Modal
        open={domainOpen}
        title={domainId ? 'Edit domain' : 'Add domain'}
        onClose={() => {
          setDomainOpen(false)
          setDomainBusiness(null)
          setDomainId(null)
          setDomainError('')
        }}
      >
        {domainError ? (
          <p className={styles.alertError} role="alert">
            {domainError}
          </p>
        ) : null}
        <div className={styles.field}>
          <label htmlFor="domain-host">Domain</label>
          <input
            id="domain-host"
            value={domainHost}
            onChange={(e) => setDomainHost(e.target.value)}
            placeholder="shop-a.local"
            disabled={domainSubmitting}
          />
        </div>
        <div style={{ height: 12 }} />
        <div className={styles.actionsRow}>
          <button
            type="button"
            className={`${styles.btn} ${styles.btnGhost}`}
            onClick={() => setDomainOpen(false)}
            disabled={domainSubmitting}
          >
            Cancel
          </button>
          <button
            type="button"
            className={`${styles.btn} ${styles.btnPrimary}`}
            onClick={() => void submitDomain()}
            disabled={domainSubmitting || !domainHost.trim()}
          >
            Save
          </button>
        </div>
      </Modal>

      <Modal
        open={migrateOpen}
        title={
          migrateBusiness
            ? `Migrate from old CMS — ${migrateBusiness.name}`
            : 'Migrate from old CMS'
        }
        onClose={closeMigrate}
      >
        {migrateSubmitting ? (
          <p className={styles.alertInfo} role="status" aria-live="polite">
            Migrating selected data… This can take a moment.
          </p>
        ) : null}
        {migrateError ? (
          <p className={styles.alertError} role="alert">
            {migrateError}
          </p>
        ) : null}
        {migrateResult ? (
          <div className={styles.alertSuccess} role="status" aria-live="polite">
            <p className={styles.migrateResultTitle}>{migrateResult.message}</p>
            {migrateResult.results ? (
              <ul className={styles.migrateResultList}>
                {(Object.keys(migrateResult.results) as MigrateFromOldEntity[]).map((key) => {
                  const item = migrateResult.results?.[key]
                  if (!item) return null
                  return (
                    <li key={key}>
                      <strong>{MIGRATE_ENTITY_LABELS[key]}:</strong>{' '}
                      {formatMigrateEntityResult(item)}
                    </li>
                  )
                })}
              </ul>
            ) : null}
          </div>
        ) : null}
        <p className={styles.helperText}>
          Link this business to a legacy WillaEngine business id, then choose one
          data type to migrate. Selecting blogs also migrates news under a top-level
          News category. Selecting customers also migrates client categories when
          needed.
        </p>
        <div className={styles.field}>
          <label htmlFor="migrate-old-id">Old business id</label>
          <input
            id="migrate-old-id"
            type="number"
            min={1}
            step={1}
            value={String(migrateOldId)}
            onChange={(e) => {
              setMigrateOldId(e.target.value)
              setMigrateResult(null)
              setMigrateError('')
            }}
            placeholder="e.g. 2410"
            disabled={migrateSubmitting}
          />
        </div>
        <div className={styles.field} style={{ marginTop: 12 }}>
          <span className={styles.entityGroupLabel}>Data to migrate (one)</span>
          <div className={styles.entityChecks}>
            {DATA_ENTITY_GROUPS.map((group) => (
              <div key={group.title} className={styles.entityGroup}>
                <span className={styles.entityGroupTitle}>{group.title}</span>
                <div className={styles.entityNestedChecks}>
                  {group.items.map(([value, label]) => (
                    <label key={value} className={styles.entityCheck}>
                      <input
                        type="radio"
                        name="migrate-entity"
                        checked={migrateEntities[value]}
                        onChange={() => selectMigrateEntity(value)}
                        disabled={migrateSubmitting}
                      />
                      <span>{label}</span>
                    </label>
                  ))}
                </div>
              </div>
            ))}
          </div>
        </div>
        <div style={{ height: 12 }} />
        <div className={styles.actionsRow}>
          <button
            type="button"
            className={`${styles.btn} ${styles.btnGhost}`}
            onClick={closeMigrate}
            disabled={migrateSubmitting}
          >
            {migrateResult ? 'Close' : 'Cancel'}
          </button>
          <button
            type="button"
            className={`${styles.btn} ${styles.btnPrimary}`}
            onClick={() => void submitMigrate()}
            disabled={migrateSubmitting || !canSubmitMigrate}
          >
            {migrateSubmitting
              ? 'Migrating…'
              : migrateResult
                ? 'Migrate again'
                : 'Save & migrate'}
          </button>
        </div>
      </Modal>

      <Modal
        open={purgeOpen}
        title={
          purgeBusiness ? `Delete data — ${purgeBusiness.name}` : 'Delete data'
        }
        onClose={closePurge}
      >
        {purgeSubmitting ? (
          <p className={styles.alertInfo} role="status" aria-live="polite">
            Deleting selected data… This can take a moment.
          </p>
        ) : null}
        {purgeError ? (
          <p className={styles.alertError} role="alert">
            {purgeError}
          </p>
        ) : null}
        {purgeResult ? (
          <div className={styles.alertSuccess} role="status" aria-live="polite">
            <p className={styles.migrateResultTitle}>{purgeResult.message}</p>
            {purgeResult.results ? (
              <ul className={styles.migrateResultList}>
                {(Object.keys(purgeResult.results) as PurgeBusinessDataEntity[]).map((key) => {
                  const item = purgeResult.results?.[key]
                  if (!item) return null
                  return (
                    <li key={key}>
                      <strong>{MIGRATE_ENTITY_LABELS[key]}:</strong>{' '}
                      {formatPurgeEntityResult(item)}
                    </li>
                  )
                })}
              </ul>
            ) : null}
          </div>
        ) : null}
        <p className={styles.helperText}>
          Permanently remove one selected data type from this business so you can
          migrate again. Deleting blogs or portfolios also removes their images
          from storage. Deleting customers removes business links (not global user
          accounts).
        </p>
        <div className={styles.field} style={{ marginTop: 12 }}>
          <span className={styles.entityGroupLabel}>Data to delete (one)</span>
          <div className={styles.entityChecks}>
            {DATA_ENTITY_GROUPS.map((group) => (
              <div key={group.title} className={styles.entityGroup}>
                <span className={styles.entityGroupTitle}>{group.title}</span>
                <div className={styles.entityNestedChecks}>
                  {group.items.map(([value, label]) => (
                    <label key={value} className={styles.entityCheck}>
                      <input
                        type="radio"
                        name="purge-entity"
                        checked={purgeEntities[value]}
                        onChange={() => selectPurgeEntity(value)}
                        disabled={purgeSubmitting}
                      />
                      <span>{label}</span>
                    </label>
                  ))}
                </div>
              </div>
            ))}
          </div>
        </div>
        <div style={{ height: 12 }} />
        <div className={styles.actionsRow}>
          <button
            type="button"
            className={`${styles.btn} ${styles.btnGhost}`}
            onClick={closePurge}
            disabled={purgeSubmitting}
          >
            {purgeResult ? 'Close' : 'Cancel'}
          </button>
          <button
            type="button"
            className={`${styles.btn} ${styles.btnDanger}`}
            onClick={() => void submitPurge()}
            disabled={purgeSubmitting || !canSubmitPurge}
          >
            {purgeSubmitting
              ? 'Deleting…'
              : purgeResult
                ? 'Delete again'
                : 'Delete selected data'}
          </button>
        </div>
      </Modal>

      <Modal
        open={createOpen}
        title="Add business"
        wide
        onClose={() => {
          setCreateOpen(false)
          resetCreateForm()
        }}
      >
        {createError ? (
          <p className={styles.alertError} role="alert">
            {createError}
          </p>
        ) : null}
        <div className={styles.formGrid}>
          <div className={styles.field}>
            <label htmlFor="create-name-en">Name (EN)</label>
            <input
              id="create-name-en"
              value={createName}
              onChange={(e) => setCreateName(e.target.value)}
              placeholder="New Shop"
              disabled={createSubmitting}
            />
          </div>

          <div className={styles.field}>
            <label htmlFor="create-name-fa">Name (FA)</label>
            <input
              id="create-name-fa"
              className="faText"
              value={createNameFa}
              onChange={(e) => setCreateNameFa(e.target.value)}
              placeholder="نام فارسی"
              dir="rtl"
              disabled={createSubmitting}
            />
          </div>

          <div className={`${styles.field} ${styles.formFull}`}>
            <label htmlFor="create-categories">Categories</label>
            <MultiSelectDropdown
              id="create-categories"
              options={categoryOptions}
              value={createCategoryIds}
              onChange={setCreateCategoryIds}
              placeholder="Select categories"
              disabled={createSubmitting || categories.length === 0}
            />
          </div>

          <div className={`${styles.field} ${styles.formFull}`}>
            <div className={styles.sectionLabel}>Owner</div>
          </div>

          <div className={styles.field}>
            <label htmlFor="create-owner-first-name-en">First name (EN)</label>
            <input
              id="create-owner-first-name-en"
              value={createOwnerFirstNameEn}
              onChange={(e) => setCreateOwnerFirstNameEn(e.target.value)}
              placeholder="First name"
              disabled={createSubmitting}
            />
          </div>

          <div className={styles.field}>
            <label htmlFor="create-owner-last-name-en">Last name (EN)</label>
            <input
              id="create-owner-last-name-en"
              value={createOwnerLastNameEn}
              onChange={(e) => setCreateOwnerLastNameEn(e.target.value)}
              placeholder="Last name"
              disabled={createSubmitting}
            />
          </div>

          <div className={styles.field}>
            <label htmlFor="create-owner-first-name">First name (FA)</label>
            <input
              id="create-owner-first-name"
              className="faText"
              value={createOwnerFirstName}
              onChange={(e) => setCreateOwnerFirstName(e.target.value)}
              placeholder="نام"
              dir="rtl"
              lang="fa"
              disabled={createSubmitting}
            />
          </div>

          <div className={styles.field}>
            <label htmlFor="create-owner-last-name">Last name (FA)</label>
            <input
              id="create-owner-last-name"
              className="faText"
              value={createOwnerLastName}
              onChange={(e) => setCreateOwnerLastName(e.target.value)}
              placeholder="نام خانوادگی"
              dir="rtl"
              lang="fa"
              disabled={createSubmitting}
            />
          </div>

          <div className={`${styles.field} ${styles.formFull}`}>
            <label htmlFor="create-owner-cell">Cell number</label>
            <input
              id="create-owner-cell"
              value={createOwnerCell}
              onChange={(e) => setCreateOwnerCell(e.target.value)}
              placeholder="0912..."
              name="owner-cell"
              autoComplete="off"
              disabled={createSubmitting}
            />
          </div>

          <div className={`${styles.field} ${styles.formFull}`}>
            <label htmlFor="create-owner-password">Password</label>
            <input
              id="create-owner-password"
              type="password"
              value={createOwnerPassword}
              onChange={(e) => setCreateOwnerPassword(e.target.value)}
              placeholder="Min. 8 characters"
              name="owner-password"
              autoComplete="new-password"
              disabled={createSubmitting}
            />
          </div>

          <div className={`${styles.field} ${styles.formFull}`}>
            <label htmlFor="create-about">About business</label>
            <textarea
              id="create-about"
              value={createAbout}
              onChange={(e) => setCreateAbout(e.target.value)}
              placeholder="Short description about the business"
              disabled={createSubmitting}
            />
          </div>
        </div>

        <div style={{ height: 12 }} />
        <div className={styles.actionsRow}>
          <button
            type="button"
            className={`${styles.btn} ${styles.btnGhost}`}
            onClick={() => setCreateOpen(false)}
            disabled={createSubmitting}
          >
            Cancel
          </button>
          <button
            type="button"
            className={`${styles.btn} ${styles.btnPrimary}`}
            onClick={() => void submitCreate()}
            disabled={createSubmitting || !canSubmitCreate}
          >
            Create
          </button>
        </div>
      </Modal>

      <ConfirmDeleteModal
        open={removeTarget !== null}
        title="Remove business?"
        message={
          removeTarget
            ? `Are you sure you want to remove "${removeTarget.name}"? This action cannot be undone.`
            : ''
        }
        onCancel={() => setRemoveTarget(null)}
        onConfirm={() => void confirmRemove()}
      />
    </main>
  )
}
