import { useEffect, useMemo, useState } from 'react'
import { Link, useLocation, useNavigate, useSearchParams } from 'react-router-dom'
import { Copy, Eye, Pencil, Plus, Trash2 } from 'lucide-react'
import { useLocale } from '@meshkee/dashboard-ui'
import { Pagination } from '../components/Pagination'
import { Breadcrumbs } from '../components/Breadcrumbs'
import { ConfirmDeleteModal } from '../components/ConfirmDeleteModal'
import { Modal } from '../components/Modal'
import { PageTitle } from '../components/PageTitle'
import { isEmptyRichText } from '../components/RichTextEditor'
import { Tooltip } from '../components/Tooltip'
import { useToast } from '../context/ToastContext'
import { useT } from '../i18n/useT'
import type { BusinessMessageKey } from '../i18n/messages'
import { ApiError, isAbortError } from '../lib/api'
import { getInvoicePublicUrlFallback } from '../lib/config'
import { getActiveBusinessDomain } from '../lib/businessContext'
import { formatCellForDisplay } from '../lib/cellNumber'
import { deleteInvoice, listInvoices, updateInvoiceStatus } from '../services/invoiceService'
import type { BusinessCustomer } from '../services/customerService'
import type { Invoice, InvoiceStatus } from '../types/invoice'
import { formatIrtPrice } from '../utils/irtPrice'
import pageStyles from '../components/PageContent.module.css'
import formStyles from '../components/InvoiceForm.module.css'
import styles from './InvoicesPage.module.css'

const PAGE_SIZE = 20
const STATUS_OPTIONS: InvoiceStatus[] = ['draft', 'issued', 'approved', 'paid', 'cancelled']

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

function statusLabelKey(status: InvoiceStatus): BusinessMessageKey {
  return `invoices.status.${status}` as BusinessMessageKey
}

function statusClass(status: InvoiceStatus) {
  return styles[`status_${status}` as keyof typeof styles] ?? styles.status_draft
}

function canEditInvoice(status: InvoiceStatus) {
  return status !== 'approved'
}

function allowedStatusOptions(current: InvoiceStatus): InvoiceStatus[] {
  if (current !== 'approved') return STATUS_OPTIONS
  return STATUS_OPTIONS.filter(
    (option) => option === 'approved' || option === 'paid' || option === 'cancelled',
  )
}

function customerName(invoice: Invoice): string {
  const name = [invoice.user?.firstName, invoice.user?.lastName].filter(Boolean).join(' ').trim()
  return name || ''
}

export function InvoicesPage() {
  const navigate = useNavigate()
  const location = useLocation()
  const [searchParams, setSearchParams] = useSearchParams()
  const t = useT()
  const { locale } = useLocale()
  const { showToast } = useToast()

  const filterUserId = searchParams.get('userId') || ''
  const presetCustomer = (location.state as { presetCustomer?: BusinessCustomer } | null)
    ?.presetCustomer

  const [invoices, setInvoices] = useState<Invoice[]>([])
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState('')
  const [page, setPage] = useState(1)
  const [totalPages, setTotalPages] = useState(1)
  const [total, setTotal] = useState(0)

  const [detailInvoice, setDetailInvoice] = useState<Invoice | null>(null)
  const [statusTarget, setStatusTarget] = useState<Invoice | null>(null)
  const [statusUpdating, setStatusUpdating] = useState<InvoiceStatus | null>(null)
  const [removeTarget, setRemoveTarget] = useState<Invoice | null>(null)

  async function reload(signal?: AbortSignal) {
    setLoading(true)
    setError('')
    try {
      const list = await listInvoices(
        { page, pageSize: PAGE_SIZE, userId: filterUserId || undefined },
        signal,
      )
      setInvoices(list.items)
      setTotalPages(list.totalPages)
      setTotal(list.total)
    } catch (err) {
      if (isAbortError(err)) return
      setError(err instanceof ApiError ? err.message : t('invoices.loadError'))
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    const controller = new AbortController()
    void reload(controller.signal)
    return () => controller.abort()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [page, filterUserId])

  useEffect(() => {
    setPage(1)
  }, [filterUserId])

  const filterCustomerMatch = useMemo(() => {
    if (!filterUserId) return undefined
    return invoices.find((inv) => inv.userId === filterUserId)
  }, [invoices, filterUserId])

  const filterCustomerName = useMemo(() => {
    if (!filterUserId) return ''
    if (presetCustomer && presetCustomer.id === filterUserId) {
      const fromPreset = [presetCustomer.firstName, presetCustomer.lastName]
        .filter(Boolean)
        .join(' ')
        .trim()
      if (fromPreset) return fromPreset
      if (presetCustomer.label?.trim()) return presetCustomer.label.trim()
      if (presetCustomer.cellNumber) return formatCellForDisplay(presetCustomer.cellNumber)
    }
    if (filterCustomerMatch) {
      const fromInvoice = customerName(filterCustomerMatch)
      if (fromInvoice) return fromInvoice
    }
    return ''
  }, [filterUserId, presetCustomer, filterCustomerMatch])

  const issueState =
    presetCustomer && presetCustomer.id === filterUserId
      ? { presetCustomer }
      : filterCustomerMatch?.user
        ? {
            presetCustomer: {
              id: filterCustomerMatch.user.id,
              cellNumber: filterCustomerMatch.user.cell,
              firstName: filterCustomerMatch.user.firstName,
              lastName: filterCustomerMatch.user.lastName,
              email: null,
              label: filterCustomerName || filterCustomerMatch.user.cell,
            },
          }
        : undefined

  function clearFilter() {
    const next = new URLSearchParams(searchParams)
    next.delete('userId')
    setSearchParams(next, { replace: true, state: null })
  }

  function openStatusModal(invoice: Invoice) {
    setStatusTarget(invoice)
  }

  async function handleStatusSelect(next: InvoiceStatus) {
    if (!statusTarget || statusUpdating) return
    if (next === statusTarget.status) {
      setStatusTarget(null)
      return
    }

    setStatusUpdating(next)
    try {
      const updated = await updateInvoiceStatus(statusTarget.id, { status: next })
      setInvoices((rows) => rows.map((row) => (row.id === updated.id ? updated : row)))
      setDetailInvoice((current) => (current?.id === updated.id ? updated : current))
      showToast(t('invoices.statusUpdated'), 'success')
      setStatusTarget(null)
    } catch (err) {
      showToast(err instanceof ApiError ? err.message : t('invoices.statusUpdateError'), 'error')
    } finally {
      setStatusUpdating(null)
    }
  }

  async function handleRemove() {
    if (!removeTarget) return
    try {
      await deleteInvoice(removeTarget.id)
      showToast(t('invoices.removed'), 'success')
      setRemoveTarget(null)
      if (detailInvoice?.id === removeTarget.id) setDetailInvoice(null)
      await reload()
    } catch (err) {
      showToast(err instanceof ApiError ? err.message : t('invoices.removeError'), 'error')
    }
  }

  function invoicePublicUrl(invoice: Invoice) {
    // Local: public viewer is on super-admin Vite (port 5174), not the apex domain.
    if (import.meta.env.DEV || import.meta.env.VITE_INVOICE_PUBLIC_BASE_URL) {
      return getInvoicePublicUrlFallback(invoice.publicId, getActiveBusinessDomain())
    }
    return (
      invoice.publicUrl ||
      getInvoicePublicUrlFallback(invoice.publicId, getActiveBusinessDomain())
    )
  }

  async function copyPublicLink(invoice: Invoice) {
    const url = invoicePublicUrl(invoice)
    try {
      await navigator.clipboard.writeText(url)
      showToast(t('invoices.linkCopied'), 'success')
    } catch {
      showToast(t('invoices.linkCopyError'), 'error')
    }
  }

  const issueHref = filterUserId ? `/invoices/new?userId=${filterUserId}` : '/invoices/new'
  const countLabel =
    total === 1 ? t('invoices.countOne', { count: total }) : t('invoices.countMany', { count: total })

  return (
    <main className={pageStyles.content}>
      <Breadcrumbs
        items={[
          { label: t('nav.home'), href: '/' },
          { label: t('nav.finance'), href: '/finance' },
          { label: t('title.invoices') },
        ]}
      />

      <div className={pageStyles.pageHeader}>
        <div>
          <PageTitle en="INVOICES">{t('title.invoices')}</PageTitle>
          <p className={pageStyles.pageSubtitle}>{t('invoices.subtitle')}</p>
        </div>
        <Link to="/invoices/templates" className={`${formStyles.btn} ${formStyles.btnGhost}`}>
          {t('invoices.templatesLink')}
        </Link>
      </div>

      {filterUserId ? (
        <div className={styles.filterBanner}>
          <span>
            {filterCustomerName
              ? t('invoices.filterBannerNamed', { name: filterCustomerName })
              : t('invoices.filterBannerGeneric')}
          </span>
          <button type="button" className={styles.filterBannerCancel} onClick={clearFilter}>
            {t('invoices.filterCancel')}
          </button>
        </div>
      ) : null}

      {error ? <p className={pageStyles.pageSubtitleContent}>{error}</p> : null}

      <div className={styles.tablePanel}>
        <div className={styles.tableWrap}>
          <div className={styles.tableHeader}>
            <div className={styles.meta}>{loading ? t('invoices.loading') : countLabel}</div>
          </div>
          <table className={styles.table}>
            <colgroup>
              <col className={styles.colName} />
              <col className={styles.colCustomer} />
              <col className={styles.colIssued} />
              <col className={styles.colStatus} />
              <col className={styles.colTotal} />
              <col className={styles.colLink} />
              <col className={styles.colActions} />
            </colgroup>
            <thead>
              <tr>
                <th className={styles.th}>{t('invoices.col.name')}</th>
                <th className={styles.th}>{t('invoices.col.customer')}</th>
                <th className={styles.th}>{t('invoices.col.issued')}</th>
                <th className={styles.th}>{t('invoices.col.status')}</th>
                <th className={styles.th}>{t('invoices.col.total')}</th>
                <th className={styles.th}>{t('invoices.col.link')}</th>
                <th className={`${styles.th} ${styles.thActions}`}>{t('invoices.col.actions')}</th>
              </tr>
            </thead>
            <tbody>
              {!loading && invoices.length === 0 ? (
                <tr>
                  <td className={styles.td} colSpan={7}>
                    {t('invoices.empty')}
                  </td>
                </tr>
              ) : null}
              {invoices.map((invoice) => {
                const itemCount = invoice.items?.length ?? 0
                const name = customerName(invoice)
                return (
                  <tr key={invoice.id}>
                    <td className={styles.td}>
                      <div className={styles.itemTitle}>{invoice.name || `#${invoice.id}`}</div>
                      <div className={styles.subText}>
                        {itemCount === 1
                          ? t('invoices.itemCountOne', { count: itemCount })
                          : t('invoices.itemCountMany', { count: itemCount })}
                      </div>
                    </td>
                    <td className={`${styles.td} ${styles.tdCustomer}`}>
                      <div className={styles.customerStack}>
                        <div className={styles.customerCell}>{name || '—'}</div>
                        {invoice.user?.cell ? (
                          <div className={styles.customerPhone} dir="ltr">
                            {formatCellForDisplay(invoice.user.cell)}
                          </div>
                        ) : null}
                      </div>
                    </td>
                    <td className={styles.td}>{formatDate(invoice.issuedAt, locale)}</td>
                    <td className={styles.td}>
                      <button
                        type="button"
                        className={`${styles.statusChip} ${styles.statusChipBtn} ${statusClass(invoice.status)}`}
                        onClick={() => openStatusModal(invoice)}
                        title={t('invoices.changeStatus')}
                        aria-label={t('invoices.changeStatusAria', {
                          status: t(statusLabelKey(invoice.status)),
                        })}
                      >
                        {t(statusLabelKey(invoice.status))}
                      </button>
                    </td>
                    <td className={styles.td}>{formatIrtPrice(invoice.total ?? 0)}</td>
                    <td className={styles.td}>
                      <div className={styles.linkRow}>
                        <a
                          className={styles.publicLink}
                          href={invoicePublicUrl(invoice)}
                          target="_blank"
                          rel="noreferrer"
                          title={invoicePublicUrl(invoice)}
                        >
                          {invoicePublicUrl(invoice).replace(/^https?:\/\//, '')}
                        </a>
                        <Tooltip label={t('invoices.copyLink')}>
                          <button
                            type="button"
                            className={styles.copyLinkBtn}
                            onClick={() => void copyPublicLink(invoice)}
                            aria-label={t('invoices.copyLinkAria')}
                          >
                            <Copy size={14} />
                          </button>
                        </Tooltip>
                      </div>
                    </td>
                    <td className={`${styles.td} ${styles.tdActions}`}>
                      <div className={styles.rowActions}>
                        <Tooltip label={t('invoices.view')}>
                          <button
                            type="button"
                            className={styles.actionBtn}
                            onClick={() => setDetailInvoice(invoice)}
                            aria-label={t('invoices.viewAria')}
                          >
                            <Eye size={16} />
                          </button>
                        </Tooltip>
                        <Tooltip
                          label={
                            canEditInvoice(invoice.status)
                              ? t('invoices.edit')
                              : t('invoices.editDisabledTitle')
                          }
                        >
                          <span>
                            <button
                              type="button"
                              className={styles.actionBtn}
                              disabled={!canEditInvoice(invoice.status)}
                              onClick={() => navigate(`/invoices/${invoice.id}/edit`)}
                              aria-label={
                                canEditInvoice(invoice.status)
                                  ? t('invoices.editAria')
                                  : t('invoices.editDisabledAria')
                              }
                            >
                              <Pencil size={16} />
                            </button>
                          </span>
                        </Tooltip>
                        <Tooltip label={t('invoices.remove')}>
                          <button
                            type="button"
                            className={`${styles.actionBtn} ${styles.actionBtnDanger}`}
                            onClick={() => setRemoveTarget(invoice)}
                            aria-label={t('invoices.removeAria')}
                          >
                            <Trash2 size={16} />
                          </button>
                        </Tooltip>
                      </div>
                    </td>
                  </tr>
                )
              })}
            </tbody>
          </table>

          {totalPages > 1 ? (
            <div className={styles.pagination}>
              <div>{countLabel}</div>
              <Pagination
                currentPage={page}
                totalPages={totalPages}
                onPageChange={setPage}
                disabled={loading}
                variant="inline"
              />
            </div>
          ) : null}
        </div>
      </div>

      <Modal
        open={!!detailInvoice}
        title={detailInvoice ? detailInvoice.name || t('invoices.detailFallbackTitle') : ''}
        onClose={() => setDetailInvoice(null)}
        xl
      >
        {detailInvoice ? (
          <>
            <div className={styles.detailMeta}>
              <div>
                <span className={styles.detailLabel}>{t('invoices.detail.billedTo')}</span>
                <strong>{customerName(detailInvoice) || '—'}</strong>
                {detailInvoice.user?.cell ? (
                  <div className={styles.subText} dir="ltr">
                    {formatCellForDisplay(detailInvoice.user.cell)}
                  </div>
                ) : null}
              </div>
              <div>
                <span className={styles.detailLabel}>{t('invoices.detail.status')}</span>
                <button
                  type="button"
                  className={`${styles.statusChip} ${styles.statusChipBtn} ${statusClass(detailInvoice.status)}`}
                  onClick={() => openStatusModal(detailInvoice)}
                  title={t('invoices.changeStatus')}
                  aria-label={t('invoices.changeStatusAria', {
                    status: t(statusLabelKey(detailInvoice.status)),
                  })}
                >
                  {t(statusLabelKey(detailInvoice.status))}
                </button>
              </div>
              <div>
                <span className={styles.detailLabel}>{t('invoices.detail.total')}</span>
                <strong>{formatIrtPrice(detailInvoice.total ?? 0)}</strong>
              </div>
            </div>

            <div className={styles.detailMeta} style={{ gridTemplateColumns: '1fr' }}>
              <div>
                <span className={styles.detailLabel}>{t('invoices.detail.link')}</span>
                <div className={styles.linkRow}>
                  <a
                    className={styles.publicLink}
                    href={invoicePublicUrl(detailInvoice)}
                    target="_blank"
                    rel="noreferrer"
                  >
                    {invoicePublicUrl(detailInvoice).replace(/^https?:\/\//, '')}
                  </a>
                  <Tooltip label={t('invoices.copyLink')}>
                    <button
                      type="button"
                      className={styles.copyLinkBtn}
                      onClick={() => void copyPublicLink(detailInvoice)}
                      aria-label={t('invoices.copyLinkAria')}
                    >
                      <Copy size={14} />
                    </button>
                  </Tooltip>
                </div>
              </div>
            </div>

            {detailInvoice.topText && !isEmptyRichText(detailInvoice.topText) ? (
              <div
                className={styles.detailNotes}
                dangerouslySetInnerHTML={{ __html: detailInvoice.topText }}
              />
            ) : null}
            {detailInvoice.notes ? (
              <p className={styles.detailNotes}>
                {t('invoices.detail.notes', { notes: detailInvoice.notes })}
              </p>
            ) : null}

            <div className={styles.detailItems}>
              {(detailInvoice.items ?? []).map((item) => (
                <div key={item.id} className={styles.detailItem}>
                  <div className={styles.detailItemTop}>
                    <strong>{item.title}</strong>
                    <span>
                      {item.discountedPrice !== null && item.discountedPrice < item.price ? (
                        <>
                          <span className={styles.strike}>{formatIrtPrice(item.price)}</span>{' '}
                          {formatIrtPrice(item.discountedPrice)}
                        </>
                      ) : (
                        formatIrtPrice(item.price)
                      )}
                    </span>
                  </div>
                  <div className={styles.detailItemMeta}>
                    {item.duration ? <span>{item.duration}</span> : null}
                    {item.worktime ? <span>{item.worktime}</span> : null}
                  </div>
                  {item.description ? (
                    <p className={styles.detailItemDesc}>{item.description}</p>
                  ) : null}
                </div>
              ))}
            </div>

            {(detailInvoice.keyPoints?.length ?? 0) > 0 ? (
              <div className={styles.blockSection}>
                <h4 className={styles.blockTitle}>{t('invoiceDraft.keyPoints')}</h4>
                <ul className={styles.keyPointList}>
                  {detailInvoice.keyPoints!.map((kp) => (
                    <li key={kp.id}>{kp.text}</li>
                  ))}
                </ul>
              </div>
            ) : null}

            {(detailInvoice.accounts?.length ?? 0) > 0 ? (
              <div className={styles.blockSection}>
                <h4 className={styles.blockTitle}>{t('invoiceDraft.accounts')}</h4>
                <div className={styles.detailItems}>
                  {detailInvoice.accounts!.map((acc) => (
                    <div key={acc.id} className={styles.detailItem}>
                      <strong>{acc.bankName}</strong>
                      <div className={styles.detailItemMeta}>
                        {acc.accountHolderName ? <span>{acc.accountHolderName}</span> : null}
                        {acc.cardNumber ? <span dir="ltr">{acc.cardNumber}</span> : null}
                        {acc.iban ? <span dir="ltr">{acc.iban}</span> : null}
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            ) : null}
          </>
        ) : null}
      </Modal>

      <Modal
        open={!!statusTarget}
        title={t('invoices.changeStatus')}
        onClose={() => {
          if (!statusUpdating) setStatusTarget(null)
        }}
      >
        {statusTarget ? (
          <div className={styles.statusOptionList} role="listbox" aria-label={t('invoices.col.status')}>
            {allowedStatusOptions(statusTarget.status).map((option) => {
              const selected = statusTarget.status === option
              const saving = statusUpdating === option
              return (
                <button
                  key={option}
                  type="button"
                  role="option"
                  aria-selected={selected}
                  className={`${styles.statusChip} ${styles.statusChipBtn} ${styles.statusOption} ${statusClass(option)} ${selected ? styles.statusOptionSelected : ''}`}
                  disabled={Boolean(statusUpdating)}
                  onClick={() => void handleStatusSelect(option)}
                >
                  {saving ? t('issueInvoice.saving') : t(statusLabelKey(option))}
                </button>
              )
            })}
          </div>
        ) : null}
      </Modal>

      <ConfirmDeleteModal
        open={!!removeTarget}
        title={t('invoices.deleteTitle')}
        message={t('invoices.deleteMessage')}
        onCancel={() => setRemoveTarget(null)}
        onConfirm={() => void handleRemove()}
      />

      <Tooltip label={t('invoices.issue')}>
        <button
          type="button"
          className={styles.fab}
          onClick={() => navigate(issueHref, { state: issueState })}
          aria-label={t('invoices.issue')}
        >
          <Plus size={24} />
        </button>
      </Tooltip>
    </main>
  )
}
