import { useEffect, useMemo, useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import {
  ArrowLeft,
  Copy,
  Eye,
  FilePlus2,
  Pencil,
  Plus,
  Trash2,
  X,
} from 'lucide-react'
import { ConfirmDeleteModal } from '../components/ConfirmDeleteModal'
import { Modal } from '../components/Modal'
import { useToast } from '../context/ToastContext'
import { ApiError, isAbortError } from '../lib/api'
import { getPlatformInvoicePublicUrl } from '../lib/config'
import { getBusiness, type BusinessDetail } from '../services/businessService'
import {
  createBusinessInvoice,
  deleteBusinessInvoice,
  listBusinessInvoices,
  listInvoiceItemTemplates,
  updateBusinessInvoiceStatus,
} from '../services/invoiceService'
import type {
  Invoice,
  InvoiceItemInput,
  InvoiceItemTemplate,
  InvoiceStatus,
} from '../types/invoice'
import { formatIrtInput, formatIrtPrice, parseIrtInput } from '../utils/irtPrice'
import pageStyles from '../components/PageContent.module.css'
import tableStyles from './BusinessesPage.module.css'
import styles from './BusinessInvoicesPage.module.css'

type DraftItem = {
  key: string
  templateId?: string
  title: string
  duration: string
  worktime: string
  description: string
  price: string
  discountedPrice: string
}

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

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 emptyDraftItem(): DraftItem {
  return {
    key: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
    title: '',
    duration: '',
    worktime: '',
    description: '',
    price: '',
    discountedPrice: '',
  }
}

function fromTemplate(template: InvoiceItemTemplate): DraftItem {
  return {
    key: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
    templateId: template.id,
    title: template.title,
    duration: template.duration ?? '',
    worktime: template.worktime ?? '',
    description: template.description ?? '',
    price: formatIrtInput(String(Math.round(template.price))),
    discountedPrice:
      template.discountedPrice === null || template.discountedPrice === undefined
        ? ''
        : formatIrtInput(String(Math.round(template.discountedPrice))),
  }
}

function statusLabel(status: InvoiceStatus) {
  return status.charAt(0).toUpperCase() + status.slice(1)
}

function effectivePrice(price: number, discountedPrice: number | null | undefined) {
  if (discountedPrice !== null && discountedPrice !== undefined && discountedPrice < price) {
    return discountedPrice
  }
  return price
}

export function BusinessInvoicesPage() {
  const { businessId = '' } = useParams()
  const { showToast } = useToast()

  const [business, setBusiness] = useState<BusinessDetail | null>(null)
  const [invoices, setInvoices] = useState<Invoice[]>([])
  const [templates, setTemplates] = useState<InvoiceItemTemplate[]>([])
  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 [createOpen, setCreateOpen] = useState(false)
  const [draftItems, setDraftItems] = useState<DraftItem[]>([emptyDraftItem()])
  const [invoiceName, setInvoiceName] = useState('')
  const [notes, setNotes] = useState('')
  const [submitting, setSubmitting] = useState(false)
  const [formError, setFormError] = useState('')
  const [selectedTemplateId, setSelectedTemplateId] = useState('')

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

  const createTotal = useMemo(() => {
    return draftItems.reduce((sum, item) => {
      const price = parseIrtInput(item.price) ?? 0
      const discounted = item.discountedPrice.trim()
        ? parseIrtInput(item.discountedPrice)
        : null
      return sum + effectivePrice(price, discounted)
    }, 0)
  }, [draftItems])

  async function reload(signal?: AbortSignal) {
    if (!businessId) return
    setLoading(true)
    setError('')
    try {
      const [biz, list, tpl] = await Promise.all([
        getBusiness(businessId, signal),
        listBusinessInvoices(businessId, { page, pageSize: 20 }, signal),
        listInvoiceItemTemplates(signal),
      ])
      setBusiness(biz)
      setInvoices(list.items)
      setTotalPages(list.totalPages)
      setTotal(list.total)
      setTemplates(tpl.items.filter((t) => t.isActive))
    } catch (err) {
      if (isAbortError(err)) return
      setError(err instanceof ApiError ? err.message : 'Unable to load invoices.')
    } finally {
      setLoading(false)
    }
  }

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

  function openCreate() {
    setDraftItems([emptyDraftItem()])
    setInvoiceName('')
    setNotes('')
    setSelectedTemplateId('')
    setFormError('')
    setCreateOpen(true)
  }

  function updateDraftItem(key: string, patch: Partial<DraftItem>) {
    setDraftItems((items) => items.map((item) => (item.key === key ? { ...item, ...patch } : item)))
  }

  function removeDraftItem(key: string) {
    setDraftItems((items) => (items.length <= 1 ? items : items.filter((item) => item.key !== key)))
  }

  function addCustomItem() {
    setDraftItems((items) => [...items, emptyDraftItem()])
  }

  function addFromTemplate() {
    const template = templates.find((t) => t.id === selectedTemplateId)
    if (!template) return
    setDraftItems((items) => {
      const onlyEmpty =
        items.length === 1 &&
        !items[0].title.trim() &&
        !items[0].price.trim() &&
        !items[0].description.trim()
      return onlyEmpty ? [fromTemplate(template)] : [...items, fromTemplate(template)]
    })
    setSelectedTemplateId('')
  }

  function buildItemsPayload(): InvoiceItemInput[] {
    return draftItems.map((item) => {
      const title = item.title.trim()
      const price = parseIrtInput(item.price)
      if (!title) throw new Error('Each item needs a title.')
      if (price === null) throw new Error(`Price is required for “${title || 'item'}”.`)
      const discountedPrice = item.discountedPrice.trim()
        ? parseIrtInput(item.discountedPrice)
        : null
      if (item.discountedPrice.trim() && discountedPrice === null) {
        throw new Error(`Discounted price is invalid for “${title}”.`)
      }
      if (discountedPrice !== null && discountedPrice > price) {
        throw new Error(`Discounted price cannot exceed price for “${title}”.`)
      }
      return {
        templateId: item.templateId,
        title,
        duration: item.duration.trim() || undefined,
        worktime: item.worktime.trim() || undefined,
        description: item.description.trim() || undefined,
        price,
        discountedPrice,
      }
    })
  }

  async function handleCreate() {
    setFormError('')
    let items: InvoiceItemInput[]
    try {
      items = buildItemsPayload()
    } catch (err) {
      setFormError(err instanceof Error ? err.message : 'Invalid invoice items.')
      return
    }

    setSubmitting(true)
    try {
      await createBusinessInvoice(businessId, {
        items,
        name: invoiceName.trim() || undefined,
        notes: notes.trim() || undefined,
      })
      showToast('Invoice issued.', 'success')
      setCreateOpen(false)
      setPage(1)
      await reload()
    } catch (err) {
      setFormError(err instanceof ApiError ? err.message : 'Unable to create invoice.')
    } finally {
      setSubmitting(false)
    }
  }

  async function handleStatusChange(next: InvoiceStatus) {
    if (!detailInvoice) return
    setStatusUpdating(true)
    try {
      const updated = await updateBusinessInvoiceStatus(businessId, detailInvoice.id, {
        status: next,
      })
      setDetailInvoice(updated)
      setInvoices((rows) => rows.map((row) => (row.id === updated.id ? updated : row)))
      showToast('Invoice status updated.', 'success')
    } catch (err) {
      showToast(err instanceof ApiError ? err.message : 'Unable to update status.', 'error')
    } finally {
      setStatusUpdating(false)
    }
  }

  async function handleRemove() {
    if (!removeTarget) return
    try {
      await deleteBusinessInvoice(businessId, removeTarget.id)
      showToast('Invoice removed.', 'success')
      setRemoveTarget(null)
      if (detailInvoice?.id === removeTarget.id) setDetailInvoice(null)
      await reload()
    } catch (err) {
      showToast(err instanceof ApiError ? err.message : 'Unable to remove invoice.', 'error')
    }
  }

  async function copyPublicLink(invoice: Invoice) {
    const url = invoice.publicUrl || getPlatformInvoicePublicUrl(invoice.id)
    try {
      await navigator.clipboard.writeText(url)
      showToast('Invoice link copied.', 'success')
    } catch {
      showToast('Unable to copy link.', 'error')
    }
  }

  function invoicePublicUrl(invoice: Invoice) {
    return invoice.publicUrl || getPlatformInvoicePublicUrl(invoice.id)
  }

  const businessName = business?.nameFa || business?.name || 'Business'

  return (
    <main className={pageStyles.content}>
      <div className={pageStyles.pageHeader}>
        <div>
          <Link to="/businesses" className={styles.backLink}>
            <ArrowLeft size={16} />
            Back to businesses
          </Link>
          <h2 className={pageStyles.pageTitle}>Invoices · {businessName}</h2>
          <p className={pageStyles.pageSubtitle}>
            List invoices issued to this business, or create a new one from predefined or custom
            items.
          </p>
        </div>
        <button
          type="button"
          className={`${tableStyles.btn} ${tableStyles.btnPrimary}`}
          onClick={openCreate}
        >
          <FilePlus2 size={16} />
          Issue invoice
        </button>
      </div>

      {error ? <p className={styles.alertError}>{error}</p> : null}

      <div className={tableStyles.tableWrap}>
        <div className={tableStyles.tableHeader}>
          <div className={tableStyles.tableHeaderTitle}>Invoices</div>
          <div className={tableStyles.meta}>
            {loading ? 'Loading…' : `${total} invoice${total === 1 ? '' : 's'}`}
          </div>
        </div>
        <table className={tableStyles.table}>
            <thead>
              <tr>
                <th className={tableStyles.th}>Name</th>
                <th className={tableStyles.th}>Issued</th>
                <th className={tableStyles.th}>Status</th>
                <th className={tableStyles.th}>Total</th>
                <th className={tableStyles.th}>Link</th>
                <th className={`${tableStyles.th} ${tableStyles.thActions}`}>Actions</th>
              </tr>
            </thead>
            <tbody>
              {!loading && invoices.length === 0 ? (
                <tr>
                  <td className={tableStyles.td} colSpan={6}>
                    No invoices yet for this business.
                  </td>
                </tr>
              ) : null}
              {invoices.map((invoice) => (
                <tr key={invoice.id}>
                  <td className={tableStyles.td}>
                    <div className={styles.itemTitle}>{invoice.name || `Invoice #${invoice.id}`}</div>
                    <div className={tableStyles.subText}>
                      {invoice.items?.length ?? 0} item{(invoice.items?.length ?? 0) === 1 ? '' : 's'}
                    </div>
                  </td>
                  <td className={tableStyles.td}>{formatDate(invoice.issuedAt)}</td>
                  <td className={tableStyles.td}>
                    <span className={`${styles.statusChip} ${styles[`status_${invoice.status}`]}`}>
                      {statusLabel(invoice.status)}
                    </span>
                  </td>
                  <td className={tableStyles.td}>{formatIrtPrice(invoice.total ?? 0)}</td>
                  <td className={tableStyles.td}>
                    <div className={styles.linkRow}>
                      <a
                        className={styles.publicLink}
                        href={invoicePublicUrl(invoice)}
                        target="_blank"
                        rel="noreferrer"
                        title={invoicePublicUrl(invoice)}
                      >
                        {invoicePublicUrl(invoice).replace(/^https?:\/\//, '')}
                      </a>
                      <button
                        type="button"
                        className={styles.copyLinkBtn}
                        onClick={() => void copyPublicLink(invoice)}
                        title="Copy link"
                        aria-label="Copy invoice link"
                      >
                        <Copy size={14} />
                      </button>
                    </div>
                  </td>
                  <td className={`${tableStyles.td} ${tableStyles.tdActions}`}>
                    <div className={tableStyles.rowActions}>
                      <button
                        type="button"
                        className={tableStyles.controlBtn}
                        onClick={() => setDetailInvoice(invoice)}
                        title="View"
                        aria-label="View invoice"
                      >
                        <Eye size={16} />
                      </button>
                      <button
                        type="button"
                        className={`${tableStyles.controlBtn} ${tableStyles.controlBtnDanger}`}
                        onClick={() => setRemoveTarget(invoice)}
                        title="Remove"
                        aria-label="Remove invoice"
                      >
                        <Trash2 size={16} />
                      </button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
        </table>
      </div>

      {totalPages > 1 ? (
        <div className={tableStyles.pagination}>
          <div>
            Page {page} / {totalPages}
          </div>
          <div className={tableStyles.pagerBtns}>
            <button
              type="button"
              className={tableStyles.pageBtn}
              disabled={page <= 1 || loading}
              onClick={() => setPage((p) => Math.max(1, p - 1))}
            >
              Prev
            </button>
            <button
              type="button"
              className={tableStyles.pageBtn}
              disabled={page >= totalPages || loading}
              onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
            >
              Next
            </button>
          </div>
        </div>
      ) : null}

      <Modal
        open={createOpen}
        title={`Issue invoice · ${businessName}`}
        onClose={() => !submitting && setCreateOpen(false)}
        xl
      >
        <div className={styles.metaGrid}>
          <div className={tableStyles.field}>
            <label htmlFor="invoice-name">Name (optional)</label>
            <input
              id="invoice-name"
              value={invoiceName}
              onChange={(e) => setInvoiceName(e.target.value)}
              placeholder="e.g. Website redesign package"
            />
          </div>
          <div className={tableStyles.field}>
            <label htmlFor="invoice-notes">Notes</label>
            <input
              id="invoice-notes"
              value={notes}
              onChange={(e) => setNotes(e.target.value)}
              placeholder="Optional notes for this invoice"
            />
          </div>
        </div>

        <div className={styles.templateBar}>
          <div className={tableStyles.field}>
            <label htmlFor="template-pick">Add from predefined</label>
            <select
              id="template-pick"
              value={selectedTemplateId}
              onChange={(e) => setSelectedTemplateId(e.target.value)}
            >
              <option value="">Select an item…</option>
              {templates.map((template) => (
                <option key={template.id} value={template.id}>
                  {template.title} · {formatIrtPrice(template.price)}
                </option>
              ))}
            </select>
          </div>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnGhost}`}
            onClick={addFromTemplate}
            disabled={!selectedTemplateId}
          >
            <Plus size={16} />
            Add item
          </button>
        </div>

        {templates.length === 0 ? (
          <p className={styles.templateHint}>
            No predefined items yet. Manage them in{' '}
            <Link to="/settings">Settings → Invoices</Link>, or add custom lines below.
          </p>
        ) : null}

        <div className={styles.itemsStack}>
          {draftItems.map((item, index) => (
            <div key={item.key} className={styles.itemCard}>
              <div className={styles.itemCardHeader}>
                <span>Item {index + 1}</span>
                <button
                  type="button"
                  className={styles.removeItemBtn}
                  onClick={() => removeDraftItem(item.key)}
                  disabled={draftItems.length <= 1}
                  aria-label="Remove item"
                  title="Remove item"
                >
                  <X size={16} />
                </button>
              </div>
              <div className={styles.itemGrid}>
                <div className={tableStyles.field}>
                  <label>Title</label>
                  <input
                    value={item.title}
                    onChange={(e) => updateDraftItem(item.key, { title: e.target.value })}
                    placeholder="Service title"
                  />
                </div>
                <div className={tableStyles.field}>
                  <label>Duration</label>
                  <input
                    value={item.duration}
                    onChange={(e) => updateDraftItem(item.key, { duration: e.target.value })}
                    placeholder="e.g. 3 months"
                  />
                </div>
                <div className={tableStyles.field}>
                  <label>Worktime</label>
                  <input
                    value={item.worktime}
                    onChange={(e) => updateDraftItem(item.key, { worktime: e.target.value })}
                    placeholder="e.g. 40 hours"
                  />
                </div>
                <div className={tableStyles.field}>
                  <label>Price (IRT)</label>
                  <input
                    inputMode="numeric"
                    value={item.price}
                    onChange={(e) =>
                      updateDraftItem(item.key, { price: formatIrtInput(e.target.value) })
                    }
                    placeholder="0"
                  />
                </div>
                <div className={tableStyles.field}>
                  <label>Discounted price (IRT)</label>
                  <input
                    inputMode="numeric"
                    value={item.discountedPrice}
                    onChange={(e) =>
                      updateDraftItem(item.key, {
                        discountedPrice: formatIrtInput(e.target.value),
                      })
                    }
                    placeholder="Optional"
                  />
                </div>
                <div className={`${tableStyles.field} ${styles.descField}`}>
                  <label>Description</label>
                  <textarea
                    rows={2}
                    value={item.description}
                    onChange={(e) => updateDraftItem(item.key, { description: e.target.value })}
                    placeholder="Optional details"
                  />
                </div>
              </div>
            </div>
          ))}
        </div>

        <div className={styles.itemActions}>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnGhost}`}
            onClick={addCustomItem}
          >
            <Pencil size={16} />
            Add custom item
          </button>
          <div className={styles.createTotal}>Total: {formatIrtPrice(createTotal)}</div>
        </div>

        {formError ? <p className={styles.alertError}>{formError}</p> : null}

        <div className={tableStyles.actionsRow}>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnGhost}`}
            onClick={() => setCreateOpen(false)}
            disabled={submitting}
          >
            Cancel
          </button>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnPrimary}`}
            onClick={() => void handleCreate()}
            disabled={submitting}
          >
            {submitting ? 'Issuing…' : 'Issue invoice'}
          </button>
        </div>
      </Modal>

      <Modal
        open={!!detailInvoice}
        title={
          detailInvoice
            ? detailInvoice.name || `Invoice · ${formatDate(detailInvoice.issuedAt)}`
            : 'Invoice'
        }
        onClose={() => setDetailInvoice(null)}
        xl
      >
        {detailInvoice ? (
          <>
            <div className={styles.detailMeta}>
              <div>
                <span className={styles.detailLabel}>Status</span>
                <select
                  value={detailInvoice.status}
                  disabled={statusUpdating}
                  onChange={(e) => void handleStatusChange(e.target.value as InvoiceStatus)}
                >
                  {STATUS_OPTIONS.map((option) => (
                    <option key={option} value={option}>
                      {statusLabel(option)}
                    </option>
                  ))}
                </select>
              </div>
              <div>
                <span className={styles.detailLabel}>Total</span>
                <strong>{formatIrtPrice(detailInvoice.total ?? 0)}</strong>
              </div>
              <div>
                <span className={styles.detailLabel}>Public link</span>
                <div className={styles.linkRow}>
                  <a
                    className={styles.publicLink}
                    href={invoicePublicUrl(detailInvoice)}
                    target="_blank"
                    rel="noreferrer"
                  >
                    {invoicePublicUrl(detailInvoice).replace(/^https?:\/\//, '')}
                  </a>
                  <button
                    type="button"
                    className={styles.copyLinkBtn}
                    onClick={() => void copyPublicLink(detailInvoice)}
                    title="Copy link"
                    aria-label="Copy invoice link"
                  >
                    <Copy size={14} />
                  </button>
                </div>
              </div>
            </div>

            {detailInvoice.notes ? (
              <p className={styles.detailNotes}>{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>Duration: {item.duration}</span> : null}
                    {item.worktime ? <span>Worktime: {item.worktime}</span> : null}
                  </div>
                  {item.description ? (
                    <p className={styles.detailItemDesc}>{item.description}</p>
                  ) : null}
                </div>
              ))}
            </div>
          </>
        ) : null}
      </Modal>

      <ConfirmDeleteModal
        open={!!removeTarget}
        title="Remove invoice"
        message="Remove this invoice permanently? This cannot be undone."
        onCancel={() => setRemoveTarget(null)}
        onConfirm={() => void handleRemove()}
      />
    </main>
  )
}
