import { useEffect, useMemo, useState } from 'react'
import { MessageSquare, Pencil, Plus, RotateCcw, Search, Ticket, Trash2 } from 'lucide-react'
import { AddCustomerModal } from '../components/AddCustomerModal'
import { Breadcrumbs } from '../components/Breadcrumbs'
import { ConfirmDeleteModal } from '../components/ConfirmDeleteModal'
import { EditCustomerModal } from '../components/EditCustomerModal'
import { Pagination } from '../components/Pagination'
import { ToggleSwitch } from '../components/ToggleSwitch'
import { Tooltip } from '../components/Tooltip'
import { useToast } from '../context/ToastContext'
import { ApiError, isAbortError } from '../lib/api'
import { formatCellForDisplay } from '../lib/cellNumber'
import {
  listCustomers,
  removeCustomer,
  updateCustomerEnabled,
  type BusinessCustomerListItem,
  type CustomersListResponse,
} from '../services/customerService'
import { formatIrtPrice } from '../utils/irtPrice'
import { textLocaleAttrs } from '../utils/textLocale'
import filterStyles from '../components/ListFiltersPanel.module.css'
import pageStyles from '../components/PageContent.module.css'
import styles from './CustomersPage.module.css'

const PAGE_SIZE = 24
const COLUMN_COUNT = 7

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' })
}

function displayName(customer: BusinessCustomerListItem) {
  const name = [customer.firstName, customer.lastName].filter(Boolean).join(' ').trim()
  return name || '—'
}

function formatOrderCount(count: number | null | undefined) {
  if (count == null || count === 0) {
    return <span className={styles.subText}>No order yet</span>
  }
  return count
}

function formatTransactionTotal(total: number | null | undefined) {
  if (total == null || total === 0) {
    return <span className={styles.subText}>—</span>
  }
  return formatIrtPrice(total)
}

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

  const [appliedFilters, setAppliedFilters] = useState<{ name?: string; cellNumber?: string }>({})
  const [page, setPage] = useState(1)

  const [draftName, setDraftName] = useState('')
  const [draftCell, setDraftCell] = useState('')

  const [togglingId, setTogglingId] = useState<string | null>(null)
  const [editTarget, setEditTarget] = useState<BusinessCustomerListItem | null>(null)
  const [createOpen, setCreateOpen] = useState(false)
  const [removeTarget, setRemoveTarget] = useState<BusinessCustomerListItem | null>(null)
  const [removing, setRemoving] = useState(false)

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

    async function load() {
      setLoading(true)
      setError('')
      try {
        const result = await listCustomers(
          {
            page,
            pageSize: PAGE_SIZE,
            ...appliedFilters,
          },
          controller.signal,
        )
        if (controller.signal.aborted) return
        setData(result)
      } catch (err) {
        if (isAbortError(err) || controller.signal.aborted) return
        setError(err instanceof ApiError ? err.message : 'Unable to load customers.')
      } finally {
        if (!controller.signal.aborted) setLoading(false)
      }
    }

    void load()

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

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

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

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

  function applyFilters() {
    setPage(1)
    setAppliedFilters({
      ...(draftName.trim() ? { name: draftName.trim() } : {}),
      ...(draftCell.trim() ? { cellNumber: draftCell.trim() } : {}),
    })
  }

  function clearFilters() {
    setDraftName('')
    setDraftCell('')
    setPage(1)
    setAppliedFilters({})
  }

  async function handleToggleEnabled(customer: BusinessCustomerListItem, isEnabled: boolean) {
    setTogglingId(customer.id)
    setError('')
    try {
      await updateCustomerEnabled(customer.id, isEnabled)
      setData((prev) => {
        if (!prev) return prev
        return {
          ...prev,
          items: prev.items.map((item) =>
            item.id === customer.id ? { ...item, isEnabled } : item,
          ),
        }
      })
      showToast(
        isEnabled
          ? `"${displayName(customer)}" has been enabled.`
          : `"${displayName(customer)}" has been disabled.`,
        'success',
      )
    } catch (err) {
      setError(err instanceof ApiError ? err.message : 'Unable to update customer.')
    } finally {
      setTogglingId(null)
    }
  }

  async function confirmRemove() {
    if (!removeTarget) return
    setRemoving(true)
    setError('')
    try {
      await removeCustomer(removeTarget.id)
      setData((prev) => {
        if (!prev) return prev
        return {
          ...prev,
          total: Math.max(0, prev.total - 1),
          items: prev.items.filter((item) => item.id !== removeTarget.id),
        }
      })
      showToast(`"${displayName(removeTarget)}" has been removed.`, 'success')
      setRemoveTarget(null)
    } catch (err) {
      setError(err instanceof ApiError ? err.message : 'Unable to remove customer.')
    } finally {
      setRemoving(false)
    }
  }

  function handleSendSms(customer: BusinessCustomerListItem) {
    showToast(`SMS to ${formatCellForDisplay(customer.cellNumber)} is not available yet.`, 'info')
  }

  function handleTickets(customer: BusinessCustomerListItem) {
    showToast(`Tickets for "${displayName(customer)}" are not available yet.`, 'info')
  }

  function handleCustomerSaved(updated: BusinessCustomerListItem) {
    setData((prev) => {
      if (!prev) return prev
      return {
        ...prev,
        items: prev.items.map((item) => (item.id === updated.id ? updated : item)),
      }
    })
    showToast(`"${displayName(updated)}" has been updated.`, 'success')
  }

  function handleCustomerCreated(customer: BusinessCustomerListItem) {
    setPage(1)
    setData((prev) => {
      if (!prev) {
        return {
          items: [customer],
          total: 1,
          page: 1,
          pageSize: PAGE_SIZE,
        }
      }
      return {
        ...prev,
        total: prev.total + 1,
        page: 1,
        items: [customer, ...prev.items.filter((item) => item.id !== customer.id)].slice(
          0,
          PAGE_SIZE,
        ),
      }
    })
    showToast(`"${displayName(customer)}" has been added.`, 'success')
  }

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

      <div className={pageStyles.pageHeader}>
        <div>
          <h2 className={pageStyles.pageTitle}>Customers</h2>
          <p className={pageStyles.pageSubtitle}>
            View customers who have registered or ordered from your business.
          </p>
        </div>
      </div>

      <div className={filterStyles.filtersPanel}>
        <div className={filterStyles.filtersTitle}>Filters</div>
        <div className={filterStyles.filtersGrid}>
          <div className={filterStyles.filtersInputs}>
            <div className={`${filterStyles.field} ${filterStyles.fieldCol3}`}>
              <label htmlFor="filter-customer-name">Name</label>
              <input
                id="filter-customer-name"
                value={draftName}
                onChange={(e) => setDraftName(e.target.value)}
                placeholder="Search by name"
              />
            </div>
            <div className={`${filterStyles.field} ${styles.filterCellNarrow}`}>
              <label htmlFor="filter-customer-cell">Cell number</label>
              <input
                id="filter-customer-cell"
                value={draftCell}
                onChange={(e) => setDraftCell(e.target.value)}
                placeholder="0912..."
                autoComplete="off"
              />
            </div>
          </div>
          <div className={filterStyles.filterActions}>
            <button
              type="button"
              className={`${filterStyles.iconActionBtn} ${filterStyles.iconActionBtnPrimary}`}
              onClick={applyFilters}
              disabled={loading}
              aria-label="Search"
              title="Search"
            >
              <Search size={18} />
            </button>
            <button
              type="button"
              className={`${filterStyles.iconActionBtn} ${filterStyles.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}>Customer list</div>
            <div className={styles.meta}>
              {data ? (
                data.total > 0 ? (
                  <>
                    Showing {showingFrom} - {showingTo} of {data.total}
                  </>
                ) : (
                  'No customers'
                )
              ) : (
                ' '
              )}
            </div>
          </div>

          {error && <div className={styles.errorBanner}>{error}</div>}

          <table className={styles.table}>
            <colgroup>
              <col className={styles.colName} />
              <col className={styles.colCell} />
              <col className={styles.colEmail} />
              <col className={styles.colOrders} />
              <col className={styles.colTransactions} />
              <col className={styles.colDate} />
              <col className={styles.colActions} />
            </colgroup>
            <thead>
              <tr>
                <th className={styles.th}>Name</th>
                <th className={styles.th}>Cell number</th>
                <th className={styles.th}>Email</th>
                <th className={styles.th}>Orders</th>
                <th className={styles.th}>Transactions</th>
                <th className={styles.th}>Date joined</th>
                <th className={`${styles.th} ${styles.thActions}`}>Actions</th>
              </tr>
            </thead>
            <tbody>
                {loading && (
                  <tr>
                    <td className={styles.td} colSpan={COLUMN_COUNT}>
                      Loading...
                    </td>
                  </tr>
                )}

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

                {!loading &&
                  data?.items?.map((customer) => (
                    <tr
                      key={customer.id}
                      className={!customer.isEnabled ? styles.inactiveRow : undefined}
                    >
                      <td className={styles.td}>
                        {(() => {
                          const name = displayName(customer)
                          const locale = textLocaleAttrs(name)
                          return (
                            <div
                              className={[
                                styles.customerName,
                                locale.className,
                              ]
                                .filter(Boolean)
                                .join(' ')}
                              lang={locale.lang}
                              dir={locale.dir}
                            >
                              {name}
                            </div>
                          )
                        })()}
                        {!customer.isEnabled && (
                          <div className={styles.statusDisabled}>Disabled</div>
                        )}
                      </td>
                      <td className={styles.td}>{formatCellForDisplay(customer.cellNumber)}</td>
                      <td className={`${styles.td} ${styles.emailCell}`}>
                        {customer.email ?? <span className={styles.subText}>—</span>}
                      </td>
                      <td className={styles.td}>{formatOrderCount(customer.orderCount)}</td>
                      <td className={styles.td}>
                        {formatTransactionTotal(customer.totalTransactionsIrt)}
                      </td>
                      <td className={`${styles.td} ${styles.dateCell}`}>
                        {formatDate(customer.createdAt)}
                      </td>
                      <td className={`${styles.td} ${styles.tdActions}`}>
                        <div className={styles.rowActions}>
                          <Tooltip
                            label={`${customer.isEnabled ? 'Disable' : 'Enable'} customer`}
                          >
                            <span className={styles.toggleInActions}>
                              <ToggleSwitch
                                checked={customer.isEnabled}
                                disabled={togglingId === customer.id || removing}
                                size="compact"
                                ariaLabel={`${customer.isEnabled ? 'Disable' : 'Enable'} ${displayName(customer)}`}
                                onChange={(isEnabled) => void handleToggleEnabled(customer, isEnabled)}
                              />
                            </span>
                          </Tooltip>
                          <Tooltip label="Edit customer">
                            <button
                              type="button"
                              className={styles.actionBtn}
                              onClick={() => setEditTarget(customer)}
                              aria-label="Edit customer"
                            >
                              <Pencil size={15} />
                            </button>
                          </Tooltip>
                          <Tooltip label="Send SMS">
                            <button
                              type="button"
                              className={styles.actionBtn}
                              onClick={() => handleSendSms(customer)}
                              aria-label="Send SMS"
                            >
                              <MessageSquare size={15} />
                            </button>
                          </Tooltip>
                          <Tooltip label="Tickets">
                            <button
                              type="button"
                              className={styles.actionBtn}
                              onClick={() => handleTickets(customer)}
                              aria-label="Tickets"
                            >
                              <Ticket size={15} />
                            </button>
                          </Tooltip>
                          <Tooltip label="Remove customer">
                            <button
                              type="button"
                              className={`${styles.actionBtn} ${styles.actionBtnDanger}`}
                              onClick={() => setRemoveTarget(customer)}
                              aria-label="Remove customer"
                              disabled={removing}
                            >
                              <Trash2 size={15} />
                            </button>
                          </Tooltip>
                        </div>
                      </td>
                    </tr>
                  ))}
              </tbody>
            </table>

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

      <AddCustomerModal
        open={createOpen}
        onClose={() => setCreateOpen(false)}
        onCreated={handleCustomerCreated}
      />

      <EditCustomerModal
        open={editTarget !== null}
        customer={editTarget}
        onClose={() => setEditTarget(null)}
        onSaved={handleCustomerSaved}
      />

      <ConfirmDeleteModal
        open={removeTarget !== null}
        title="Remove customer?"
        message={
          removeTarget
            ? `Remove "${displayName(removeTarget)}" from your business? Their account will not be deleted.`
            : ''
        }
        onCancel={() => setRemoveTarget(null)}
        onConfirm={() => void confirmRemove()}
      />

      <button
        type="button"
        className={styles.fab}
        onClick={() => setCreateOpen(true)}
        aria-label="Add customer"
      >
        <Plus size={24} />
      </button>
    </main>
  )
}
