import { useEffect, useMemo, useState } from 'react'
import { Link, useNavigate, useParams } from 'react-router-dom'
import { ArrowLeft } from 'lucide-react'
import { InvoiceDraftFields } from '../components/InvoiceDraftFields'
import { isEmptyRichText, RichTextEditor } from '../components/RichTextEditor'
import { useToast } from '../context/ToastContext'
import { ApiError, isAbortError } from '../lib/api'
import { getBusiness, type BusinessDetail } from '../services/businessService'
import {
  createBusinessInvoice,
  getBusinessInvoice,
  listInvoiceItemTemplates,
  listInvoiceTemplates,
  updateBusinessInvoice,
} from '../services/invoiceService'
import type { InvoiceItemTemplate, InvoiceTemplate } from '../types/invoice'
import {
  buildAccountsPayload,
  buildKeyPointsPayload,
  buildLineItemsPayload,
  draftsFromInvoice,
  draftsFromInvoiceTemplate,
  emptyDraftItem,
  type DraftAccount,
  type DraftKeyPoint,
  type DraftLineItem,
} from '../utils/invoiceDraft'
import { formatIrtPrice, parseIrtInput } from '../utils/irtPrice'
import pageStyles from '../components/PageContent.module.css'
import tableStyles from './BusinessesPage.module.css'
import styles from './BusinessInvoicesPage.module.css'
import settingsStyles from './SettingsPage.module.css'

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

export function IssueInvoicePage() {
  const { businessId = '', invoiceId = '' } = useParams()
  const isEdit = Boolean(invoiceId)
  const navigate = useNavigate()
  const { showToast } = useToast()

  const [business, setBusiness] = useState<BusinessDetail | null>(null)
  const [itemTemplates, setItemTemplates] = useState<InvoiceItemTemplate[]>([])
  const [invoiceTemplates, setInvoiceTemplates] = useState<InvoiceTemplate[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState('')
  const [locked, setLocked] = useState(false)

  const [sourceTemplateId, setSourceTemplateId] = useState('')
  const [invoiceTemplateId, setInvoiceTemplateId] = useState<string | undefined>()
  const [invoiceName, setInvoiceName] = useState('')
  const [topText, setTopText] = useState('')
  const [notes, setNotes] = useState('')
  const [draftItems, setDraftItems] = useState<DraftLineItem[]>([emptyDraftItem()])
  const [keyPoints, setKeyPoints] = useState<DraftKeyPoint[]>([])
  const [accounts, setAccounts] = useState<DraftAccount[]>([])
  const [selectedItemTemplateId, setSelectedItemTemplateId] = useState('')
  const [submitting, setSubmitting] = useState(false)
  const [formError, setFormError] = useState('')

  const listPath = `/businesses/${businessId}/invoices`
  const businessName = business?.name || business?.nameFa || 'Business'

  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])

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

    async function load() {
      setLoading(true)
      setError('')
      setLocked(false)
      try {
        const [biz, items, templates] = await Promise.all([
          getBusiness(businessId, controller.signal),
          listInvoiceItemTemplates(controller.signal),
          listInvoiceTemplates(controller.signal),
        ])
        setBusiness(biz)
        setItemTemplates(items.items.filter((t) => t.isActive))
        setInvoiceTemplates(templates.items.filter((t) => t.isActive))

        if (invoiceId) {
          const invoice = await getBusinessInvoice(businessId, invoiceId, controller.signal)
          if (invoice.status === 'approved') {
            setLocked(true)
            setError('This invoice is approved and can no longer be edited.')
          }
          const drafts = draftsFromInvoice(invoice)
          setSourceTemplateId('')
          setInvoiceTemplateId(invoice.invoiceTemplateId ?? undefined)
          setInvoiceName(drafts.name)
          setTopText(drafts.topText)
          setNotes(drafts.notes)
          setDraftItems(drafts.items)
          setKeyPoints(drafts.keyPoints)
          setAccounts(drafts.accounts)
          setSelectedItemTemplateId('')
        }
      } catch (err) {
        if (isAbortError(err)) return
        setError(err instanceof ApiError ? err.message : 'Unable to load invoice form.')
      } finally {
        setLoading(false)
      }
    }

    void load()
    return () => controller.abort()
  }, [businessId, invoiceId])

  function resetBlankDraft() {
    setSourceTemplateId('')
    setInvoiceTemplateId(undefined)
    setInvoiceName('')
    setTopText('')
    setNotes('')
    setDraftItems([emptyDraftItem()])
    setKeyPoints([])
    setAccounts([])
    setSelectedItemTemplateId('')
    setFormError('')
  }

  function applyInvoiceTemplate(templateId: string) {
    if (locked) return
    setSourceTemplateId(templateId)
    if (!templateId) {
      resetBlankDraft()
      return
    }
    const template = invoiceTemplates.find((t) => t.id === templateId)
    if (!template) return
    const drafts = draftsFromInvoiceTemplate(template)
    setInvoiceTemplateId(template.id)
    setInvoiceName(drafts.name)
    setTopText(drafts.topText)
    setDraftItems(drafts.items)
    setKeyPoints(drafts.keyPoints)
    setAccounts(drafts.accounts)
    setSelectedItemTemplateId('')
    setFormError('')
  }

  async function handleSubmit() {
    if (locked) return
    setFormError('')
    let items
    try {
      items = buildLineItemsPayload(draftItems)
    } catch (err) {
      setFormError(err instanceof Error ? err.message : 'Invalid invoice items.')
      return
    }

    setSubmitting(true)
    try {
      if (isEdit) {
        await updateBusinessInvoice(businessId, invoiceId, {
          items,
          name: invoiceName.trim() || null,
          topText: isEmptyRichText(topText) ? null : topText,
          notes: notes.trim() || null,
          invoiceTemplateId: invoiceTemplateId ?? null,
          keyPoints: buildKeyPointsPayload(keyPoints),
          accounts: buildAccountsPayload(accounts),
        })
        showToast('Invoice updated.', 'success')
      } else {
        await createBusinessInvoice(businessId, {
          items,
          name: invoiceName.trim() || undefined,
          topText: isEmptyRichText(topText) ? undefined : topText,
          notes: notes.trim() || undefined,
          invoiceTemplateId,
          keyPoints: buildKeyPointsPayload(keyPoints),
          accounts: buildAccountsPayload(accounts),
        })
        showToast('Invoice issued.', 'success')
      }
      navigate(listPath)
    } catch (err) {
      setFormError(
        err instanceof ApiError
          ? err.message
          : isEdit
            ? 'Unable to update invoice.'
            : 'Unable to create invoice.',
      )
    } finally {
      setSubmitting(false)
    }
  }

  return (
    <main className={pageStyles.content}>
      <div className={pageStyles.pageHeader}>
        <div>
          <Link to={listPath} className={styles.backLink}>
            <ArrowLeft size={16} />
            Back to invoices
          </Link>
          <h2 className={pageStyles.pageTitle}>
            {isEdit ? 'Edit invoice' : 'Issue invoice'} · {businessName}
          </h2>
          <p className={pageStyles.pageSubtitle}>
            {isEdit
              ? 'Update invoice content for this business. Approved invoices cannot be changed.'
              : 'Select an invoice template and edit it for this business, or create a blank invoice.'}
          </p>
        </div>
      </div>

      {error ? <p className={styles.alertError}>{error}</p> : null}
      {loading ? <p className={tableStyles.meta}>Loading…</p> : null}

      {!loading && !locked ? (
        <section className={settingsStyles.section}>
          {!isEdit ? (
            <div className={styles.metaGrid}>
              <div className={tableStyles.field}>
                <label htmlFor="source-template">Start from template</label>
                <select
                  id="source-template"
                  value={sourceTemplateId}
                  onChange={(e) => applyInvoiceTemplate(e.target.value)}
                >
                  <option value="">Blank invoice</option>
                  {invoiceTemplates.map((template) => (
                    <option key={template.id} value={template.id}>
                      {template.name} · {template.items.length} items
                    </option>
                  ))}
                </select>
              </div>
              <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>
          ) : (
            <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>
          )}

          {!isEdit && invoiceTemplates.length === 0 ? (
            <p className={styles.templateHint}>
              No invoice templates yet. Manage them in{' '}
              <Link to="/settings">Settings → Invoice templates</Link>, or fill a blank invoice
              below.
            </p>
          ) : null}

          <div className={`${tableStyles.field} ${styles.fullField}`}>
            <label>Top text</label>
            <RichTextEditor
              value={topText}
              onChange={setTopText}
              placeholder="Optional intro text at the top of the invoice"
              editorMinHeight={88}
            />
          </div>

          <div className={`${tableStyles.field} ${styles.fullField}`}>
            <label htmlFor="invoice-notes">Notes</label>
            <input
              id="invoice-notes"
              value={notes}
              onChange={(e) => setNotes(e.target.value)}
              placeholder="Optional internal notes"
            />
          </div>

          <InvoiceDraftFields
            itemTemplates={itemTemplates}
            items={draftItems}
            keyPoints={keyPoints}
            accounts={accounts}
            selectedItemTemplateId={selectedItemTemplateId}
            onSelectedItemTemplateId={setSelectedItemTemplateId}
            onItemsChange={setDraftItems}
            onKeyPointsChange={setKeyPoints}
            onAccountsChange={setAccounts}
          />

          <div className={styles.createTotalRow}>
            <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={() => navigate(listPath)}
              disabled={submitting}
            >
              Cancel
            </button>
            <button
              type="button"
              className={`${tableStyles.btn} ${tableStyles.btnPrimary}`}
              onClick={() => void handleSubmit()}
              disabled={submitting}
            >
              {submitting
                ? isEdit
                  ? 'Saving…'
                  : 'Issuing…'
                : isEdit
                  ? 'Save changes'
                  : 'Issue invoice'}
            </button>
          </div>
        </section>
      ) : null}

      {!loading && locked ? (
        <div className={tableStyles.actionsRow}>
          <button
            type="button"
            className={`${tableStyles.btn} ${tableStyles.btnGhost}`}
            onClick={() => navigate(listPath)}
          >
            Back to invoices
          </button>
        </div>
      ) : null}
    </main>
  )
}
