import { useEffect, useMemo, useState } from 'react'
import { Link, useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom'
import { ArrowLeft } from 'lucide-react'
import { CustomerSearchSelect } from '../components/CustomerSearchSelect'
import { InvoiceDraftFields } from '../components/InvoiceDraftFields'
import { isEmptyRichText, RichTextEditor } from '../components/RichTextEditor'
import { useToast } from '../context/ToastContext'
import { useT } from '../i18n/useT'
import { ApiError, isAbortError } from '../lib/api'
import {
  createInvoice,
  getInvoice,
  listInvoiceItemTemplates,
  listInvoiceTemplates,
  updateInvoice,
} from '../services/invoiceService'
import { listCustomers, type BusinessCustomer } from '../services/customerService'
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 formStyles from '../components/InvoiceForm.module.css'
import styles from './InvoicesPage.module.css'

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

function customerFromInvoiceUser(user: {
  id: string
  firstName: string | null
  lastName: string | null
  cell: string
}): BusinessCustomer {
  const name = [user.firstName, user.lastName].filter(Boolean).join(' ').trim()
  return {
    id: user.id,
    cellNumber: user.cell,
    firstName: user.firstName,
    lastName: user.lastName,
    email: null,
    label: name || user.cell,
  }
}

export function IssueInvoicePage() {
  const { invoiceId = '' } = useParams()
  const isEdit = Boolean(invoiceId)
  const navigate = useNavigate()
  const location = useLocation()
  const [searchParams] = useSearchParams()
  const { showToast } = useToast()
  const t = useT()

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

  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 [billedCustomer, setBilledCustomer] = useState<BusinessCustomer | null>(
    presetCustomer && presetCustomer.id === urlUserId ? presetCustomer : null,
  )
  const [billedUserId, setBilledUserId] = useState(urlUserId)
  const customerLocked = isEdit || Boolean(urlUserId)

  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 = '/invoices'

  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 [items, templates] = await Promise.all([
          listInvoiceItemTemplates(controller.signal),
          listInvoiceTemplates(controller.signal),
        ])
        setItemTemplates(items.items.filter((i) => i.isActive))
        setInvoiceTemplates(templates.items.filter((i) => i.isActive))

        if (invoiceId) {
          const invoice = await getInvoice(invoiceId, controller.signal)
          if (invoice.status === 'approved') {
            setLocked(true)
            setError(t('issueInvoice.approvedLocked'))
          }
          if (invoice.user) {
            setBilledCustomer(customerFromInvoiceUser(invoice.user))
          }
          setBilledUserId(invoice.userId)
          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('')
        } else if (urlUserId && !presetCustomer) {
          const listed = await listCustomers({ page: 1, pageSize: 100 }, controller.signal)
          const match = listed.items.find((c) => c.id === urlUserId)
          if (match) {
            setBilledCustomer({
              id: match.id,
              cellNumber: match.cellNumber,
              firstName: match.firstName,
              lastName: match.lastName,
              email: match.email,
              label: match.label,
            })
            setBilledUserId(match.id)
          }
        }
      } catch (err) {
        if (isAbortError(err)) return
        setError(err instanceof ApiError ? err.message : t('issueInvoice.loadError'))
      } finally {
        setLoading(false)
      }
    }

    void load()
    return () => controller.abort()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [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((tpl) => tpl.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('')
  }

  function handleCustomerChange(customer: BusinessCustomer | null) {
    setBilledCustomer(customer)
    setBilledUserId(customer?.id ?? '')
  }

  async function handleSubmit() {
    if (locked) return
    setFormError('')

    if (!billedUserId) {
      setFormError(t('issueInvoice.recipientRequired'))
      return
    }

    let items
    try {
      items = buildLineItemsPayload(draftItems, t)
    } catch (err) {
      setFormError(err instanceof Error ? err.message : t('issueInvoice.loadError'))
      return
    }

    setSubmitting(true)
    try {
      if (isEdit) {
        await updateInvoice(invoiceId, {
          userId: billedUserId,
          items,
          name: invoiceName.trim() || null,
          topText: isEmptyRichText(topText) ? null : topText,
          notes: notes.trim() || null,
          invoiceTemplateId: invoiceTemplateId ?? null,
          keyPoints: buildKeyPointsPayload(keyPoints),
          accounts: buildAccountsPayload(accounts),
        })
        showToast(t('issueInvoice.updated'), 'success')
      } else {
        await createInvoice({
          userId: billedUserId,
          items,
          name: invoiceName.trim() || undefined,
          topText: isEmptyRichText(topText) ? undefined : topText,
          notes: notes.trim() || undefined,
          invoiceTemplateId,
          keyPoints: buildKeyPointsPayload(keyPoints),
          accounts: buildAccountsPayload(accounts),
        })
        showToast(t('issueInvoice.issued'), 'success')
      }
      navigate(listPath)
    } catch (err) {
      setFormError(
        err instanceof ApiError
          ? err.message
          : isEdit
            ? t('issueInvoice.updateError')
            : t('issueInvoice.createError'),
      )
    } finally {
      setSubmitting(false)
    }
  }

  return (
    <main className={pageStyles.content}>
      <div className={pageStyles.pageHeader}>
        <div>
          <Link to={listPath} className={formStyles.backLink}>
            <ArrowLeft size={16} />
            {t('issueInvoice.backToInvoices')}
          </Link>
          <h2 className={pageStyles.pageTitle}>
            {isEdit ? t('title.editInvoice') : t('title.issueInvoice')}
          </h2>
          <p className={pageStyles.pageSubtitle}>
            {isEdit ? t('issueInvoice.subtitleEdit') : t('issueInvoice.subtitleNew')}
          </p>
        </div>
      </div>

      {error ? <p className={formStyles.alertError}>{error}</p> : null}
      {loading ? <p className={styles.meta}>{t('issueInvoice.loading')}</p> : null}

      {!loading && !locked ? (
        <section className={formStyles.section}>
          <div className={`${formStyles.metaGrid}${isEdit ? ` ${formStyles.metaGridTwo}` : ''}`}>
            <div className={formStyles.field}>
              <label htmlFor="invoice-recipient">{t('issueInvoice.recipient')}</label>
              <CustomerSearchSelect
                id="invoice-recipient"
                value={billedCustomer}
                onChange={handleCustomerChange}
                disabled={customerLocked}
              />
            </div>
            {!isEdit ? (
              <div className={formStyles.field}>
                <label htmlFor="source-template">{t('issueInvoice.startFromTemplate')}</label>
                <select
                  id="source-template"
                  value={sourceTemplateId}
                  onChange={(e) => applyInvoiceTemplate(e.target.value)}
                >
                  <option value="">{t('issueInvoice.blankInvoice')}</option>
                  {invoiceTemplates.map((template) => (
                    <option key={template.id} value={template.id}>
                      {template.name}
                    </option>
                  ))}
                </select>
              </div>
            ) : null}
            <div className={formStyles.field}>
              <label htmlFor="invoice-name">{t('issueInvoice.name')}</label>
              <input
                id="invoice-name"
                value={invoiceName}
                onChange={(e) => setInvoiceName(e.target.value)}
                placeholder={t('issueInvoice.namePlaceholder')}
              />
            </div>
          </div>

          {!isEdit && invoiceTemplates.length === 0 ? (
            <p className={styles.subText}>
              {t('issueInvoice.noTemplatesHint').split('{link}')[0]}
              <Link to="/invoices/templates">{t('issueInvoice.noTemplatesLink')}</Link>
              {t('issueInvoice.noTemplatesHint').split('{link}')[1]}
            </p>
          ) : null}

          <div className={`${formStyles.field} ${formStyles.fullField}`}>
            <label>{t('issueInvoice.topText')}</label>
            <RichTextEditor
              value={topText}
              onChange={setTopText}
              placeholder={t('issueInvoice.topTextPlaceholder')}
              editorMinHeight={88}
            />
          </div>

          <div className={`${formStyles.field} ${formStyles.fullField}`}>
            <label htmlFor="invoice-notes">{t('issueInvoice.notes')}</label>
            <input
              id="invoice-notes"
              value={notes}
              onChange={(e) => setNotes(e.target.value)}
              placeholder={t('issueInvoice.notesPlaceholder')}
            />
          </div>

          <InvoiceDraftFields
            itemTemplates={itemTemplates}
            items={draftItems}
            keyPoints={keyPoints}
            accounts={accounts}
            selectedItemTemplateId={selectedItemTemplateId}
            onSelectedItemTemplateId={setSelectedItemTemplateId}
            onItemsChange={setDraftItems}
            onKeyPointsChange={setKeyPoints}
            onAccountsChange={setAccounts}
            afterItems={
              <div className={formStyles.totalRow}>
                <span className={formStyles.totalLabel}>{t('issueInvoice.totalLabel')}</span>
                <strong className={formStyles.totalValue}>{formatIrtPrice(createTotal)}</strong>
              </div>
            }
          />

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

          <div className={formStyles.actionsRow}>
            <button
              type="button"
              className={`${formStyles.btn} ${formStyles.btnGhost}`}
              onClick={() => navigate(listPath)}
              disabled={submitting}
            >
              {t('issueInvoice.cancel')}
            </button>
            <button
              type="button"
              className={`${formStyles.btn} ${formStyles.btnPrimary}`}
              onClick={() => void handleSubmit()}
              disabled={submitting}
            >
              {submitting
                ? isEdit
                  ? t('issueInvoice.saving')
                  : t('issueInvoice.issuing')
                : isEdit
                  ? t('issueInvoice.save')
                  : t('issueInvoice.issue')}
            </button>
          </div>
        </section>
      ) : null}

      {!loading && locked ? (
        <div className={formStyles.actionsRow} style={{ justifyContent: 'flex-start' }}>
          <button
            type="button"
            className={`${formStyles.btn} ${formStyles.btnGhost}`}
            onClick={() => navigate(listPath)}
          >
            {t('issueInvoice.backToInvoices')}
          </button>
        </div>
      ) : null}
    </main>
  )
}
