import { type FormEvent, useEffect, useState } from 'react'
import { Link, useNavigate, useParams, useSearchParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import { fetchExpenseEdit, updateExpense } from '../../api/session'
import type { ExpenseDetail, ExpenseUserOption } from '../../api/types'
import { EXPENSE_CATEGORIES, expensePurchasedByValue, toDateInputValue } from './expenseUtils'
import { ExpenseVendorFields } from './ExpenseVendorFields'

export function ExpenseEditPage() {
  const { expenseId } = useParams()
  const id = Number(expenseId ?? '')
  const navigate = useNavigate()
  const [searchParams] = useSearchParams()
  const listQs = searchParams.toString()
  const cancelHref = listQs
    ? `/app/administrator/expenses?${listQs}`
    : '/app/administrator/expenses'

  const [retailors, setRetailors] = useState<string[]>([])
  const [users, setUsers] = useState<ExpenseUserOption[]>([])
  const [expense, setExpense] = useState<ExpenseDetail | null>(null)
  const [receiptUrl, setReceiptUrl] = useState<string | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [submitting, setSubmitting] = useState(false)

  useEffect(() => {
    if (!Number.isFinite(id) || id <= 0) {
      setError('Invalid expense.')
      setLoading(false)
      return
    }
    let cancelled = false
    fetchExpenseEdit(id)
      .then((d) => {
        if (cancelled) return
        setExpense(d.expense)
        setRetailors(d.retailors ?? [])
        setUsers(d.users ?? [])
        setReceiptUrl(d.receipt_url ?? null)
        setError(null)
      })
      .catch((e: unknown) => {
        if (!cancelled)
          setError(e instanceof ApiHttpError ? e.message : 'Could not load expense.')
      })
      .finally(() => {
        if (!cancelled) setLoading(false)
      })
    return () => {
      cancelled = true
    }
  }, [id])

  async function onSubmit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault()
    if (!Number.isFinite(id) || id <= 0) return
    setSubmitting(true)
    setError(null)
    const form = e.currentTarget
    const fd = new FormData(form)
    const fileInput = form.querySelector<HTMLInputElement>('input[name="receipt"]')
    const file = fileInput?.files?.[0]
    if (!file) {
      fd.delete('receipt')
    }
    const remove = form.querySelector<HTMLInputElement>('input[name="remove_receipt"]')
    if (!remove?.checked) {
      fd.delete('remove_receipt')
    }
    try {
      await updateExpense(id, fd)
      navigate(cancelHref)
    } catch (err: unknown) {
      setError(err instanceof Error ? err.message : 'Save failed.')
    } finally {
      setSubmitting(false)
    }
  }

  const retailorInitial = expense
    ? String(expense.retailor ?? expense.retailer ?? '')
    : ''

  return (
    <div className="container mt-4">
      <h2>Edit Expense #{Number.isFinite(id) ? id : '—'}</h2>

      {loading ? <p className="text-muted">Loading…</p> : null}
      {error ? <div className="alert alert-danger">{error}</div> : null}

      {!loading && expense ? (
        <form onSubmit={onSubmit} encType="multipart/form-data">
          <div className="mb-3">
            <label className="form-label">Category</label>
            <select
              name="category"
              className="form-control form-select"
              required
              defaultValue={expense.category}
            >
              {EXPENSE_CATEGORIES.map((opt) => (
                <option key={opt} value={opt}>
                  {opt === 'Donation' ? 'Donation (non-reimbursable)' : opt}
                </option>
              ))}
            </select>
            <div className="form-text text-muted">
              Donation entries are tracked as expenses but will not move through reimbursement batches.
            </div>
          </div>

          <div className="mb-3">
            <label className="form-label">Amount</label>
            <input
              type="number"
              step="0.01"
              name="amount"
              className="form-control"
              required
              defaultValue={String(expense.amount ?? '')}
            />
          </div>

          <div className="mb-3">
            <label className="form-label">Vendor</label>
            <ExpenseVendorFields
              key={retailorInitial}
              retailors={retailors}
              initialRetailor={retailorInitial}
            />
          </div>

          <div className="mb-3">
            <label className="form-label">Purchased By</label>
            <select
              name="purchased_by"
              className="form-control form-select"
              required
              defaultValue={(() => {
                const uid = Number(expense.purchased_by)
                const match = users.find((u) => Number(u.id) === uid)
                return match ? expensePurchasedByValue(match) : ''
              })()}
            >
              {users.map((u) => (
                <option key={u.id} value={expensePurchasedByValue(u)}>
                  {`${String(u.firstname ?? '').trim()} ${String(u.lastname ?? '').trim()}`.trim()}
                </option>
              ))}
            </select>
          </div>

          <div className="mb-3">
            <label className="form-label">Date of Purchase</label>
            <input
              type="date"
              name="date_of_purchase"
              className="form-control"
              defaultValue={toDateInputValue(
                expense.date_of_purchase ??
                  expense.purchase_date ??
                  expense.purchased_at ??
                  expense.date_purchased,
              )}
            />
          </div>

          <div className="mb-3">
            <label className="form-label">Description</label>
            <textarea
              name="description"
              className="form-control"
              rows={4}
              defaultValue={expense.description ?? ''}
            />
          </div>

          <div className="mb-3">
            <label className="form-label">Receipt (optional to replace)</label>
            {receiptUrl ? (
              <div className="mb-2">
                <a href={receiptUrl} target="_blank" rel="noreferrer">
                  Current receipt
                </a>
              </div>
            ) : null}
            <input
              type="file"
              name="receipt"
              className="form-control"
              accept=".jpg,.jpeg,.png,.webp,.gif,.pdf"
            />
            {expense.receipt_path ? (
              <div className="form-check mt-2">
                <input
                  className="form-check-input"
                  type="checkbox"
                  name="remove_receipt"
                  value="1"
                  id="rmr"
                />
                <label className="form-check-label" htmlFor="rmr">
                  Remove existing receipt
                </label>
              </div>
            ) : null}
          </div>

          <button type="submit" className="btn btn-primary" disabled={submitting}>
            {submitting ? 'Saving…' : 'Save'}
          </button>
          <Link to={cancelHref} className="btn btn-secondary ms-2">
            Cancel
          </Link>
        </form>
      ) : null}
    </div>
  )
}
