import { type FormEvent, useEffect, useMemo, useState } from 'react'
import { Link, useSearchParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import { useSchoolYearOptions } from '../../hooks/useSchoolYearOptions'
import {
  downloadBatchCsv,
  downloadReimbursementsExport,
  fetchReimbursementsIndex,
  postBatchEmail,
  type BatchDetailPayload,
  type BatchSummaryRow,
  type ReimbursementsIndexResponse,
} from '../../api/reimbursements'

function money(n: unknown): string {
  const x = typeof n === 'number' ? n : parseFloat(String(n ?? 0))
  return Number.isFinite(x) ? x.toFixed(2) : '0.00'
}

type AttachmentEntry = {
  receipts?: Array<Record<string, unknown>>
  checks?: Array<Record<string, unknown>>
}

function groupItemsByPurchaser(items: Array<Record<string, unknown>>) {
  const map: Record<string, { total: number; items: Array<Record<string, unknown>> }> = {}
  for (const item of items) {
    let p = String(item.purchased_by ?? '').trim()
    if (!p) p = 'Unknown'
    if (!map[p]) map[p] = { total: 0, items: [] }
    const amt = parseFloat(String(item.amount ?? 0)) || 0
    map[p].total += amt
    map[p].items.push(item)
  }
  return Object.keys(map)
    .sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' }))
    .map((k) => ({ purchaser: k, ...map[k] }))
}

export function ReimbursementsIndexPage() {
  const [searchParams, setSearchParams] = useSearchParams()
  const semester = searchParams.get('semester') ?? ''
  const status = searchParams.get('status') ?? ''
  const schoolYear = searchParams.get('school_year') ?? ''
  const userId = searchParams.get('user_id') ?? ''

  const [data, setData] = useState<ReimbursementsIndexResponse | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [openBatches, setOpenBatches] = useState<Record<string, boolean>>({})

  const [emailOpen, setEmailOpen] = useState(false)
  const [emailBatchId, setEmailBatchId] = useState<number | null>(null)
  const [emailTitle, setEmailTitle] = useState('')
  const [recipientEmail, setRecipientEmail] = useState('')
  const [emailMessage, setEmailMessage] = useState('')
  const [receiptIds, setReceiptIds] = useState<number[]>([])
  const [checkIds, setCheckIds] = useState<number[]>([])
  const [emailStatus, setEmailStatus] = useState<string | null>(null)

  function load() {
    setError(null)
    fetchReimbursementsIndex({
      semester: semester || undefined,
      status: status || undefined,
      school_year: schoolYear || undefined,
      user_id: userId || undefined,
    })
      .then(setData)
      .catch((e: unknown) =>
        setError(e instanceof ApiHttpError ? e.message : 'Failed to load reimbursements.'),
      )
  }

  useEffect(() => {
    load()
  }, [semester, status, schoolYear, userId])

  const batchAttachments = data?.batchAttachments ?? {}

  function applyFilter(e: FormEvent<HTMLFormElement>) {
    e.preventDefault()
    const fd = new FormData(e.currentTarget)
    const next = new URLSearchParams()
    const s = String(fd.get('semester') ?? '')
    const st = String(fd.get('status') ?? '')
    const sy = String(fd.get('school_year') ?? '')
    const uid = String(fd.get('user_id') ?? '')
    if (s) next.set('semester', s)
    if (st) next.set('status', st)
    if (sy) next.set('school_year', sy)
    if (uid) next.set('user_id', uid)
    setSearchParams(next)
  }

  const schoolYears = data?.schoolYears ?? []
  const { options } = useSchoolYearOptions({
    legacyYears: schoolYears,
    preferredYear: schoolYear,
  })
  const users = data?.users ?? []
  const batchSummaries = (data?.batchSummaries ?? []) as BatchSummaryRow[]
  const batchDetails = data?.batchDetails ?? {}
  const donationBatch = data?.donationBatch ?? null
  const donationDetails = (data?.donationDetails ?? { items: [], checks: [] }) as BatchDetailPayload

  const attachmentMeta = useMemo(() => batchAttachments, [batchAttachments])

  function openEmailModal(batchId: number, title: string) {
    setEmailBatchId(batchId)
    setEmailTitle(title ? `Email ${title}` : 'Email Batch')
    setRecipientEmail('')
    setEmailMessage('')
    setEmailStatus(null)
    const entry = attachmentMeta[String(batchId)] as AttachmentEntry | undefined
    const receipts = entry?.receipts ?? []
    const checks = entry?.checks ?? []
    setReceiptIds(
      receipts
        .map((r) => Number((r as { expense_id?: unknown }).expense_id))
        .filter((n) => n > 0),
    )
    setCheckIds(
      checks.map((c) => Number((c as { file_id?: unknown }).file_id)).filter((n) => n > 0),
    )
    setEmailOpen(true)
  }

  async function submitEmail(e: FormEvent) {
    e.preventDefault()
    if (emailBatchId == null) return
    setEmailStatus('Sending…')
    const fd = new FormData()
    fd.set('batch_id', String(emailBatchId))
    fd.set('recipient_email', recipientEmail)
    fd.set('message', emailMessage)
    fd.set('receipts', JSON.stringify(receiptIds))
    fd.set('checks', JSON.stringify(checkIds))
    try {
      await postBatchEmail(fd)
      setEmailStatus('Sent.')
      setEmailOpen(false)
      load()
    } catch (err: unknown) {
      setEmailStatus(err instanceof ApiHttpError ? err.message : 'Send failed.')
    }
  }

  function toggleReceipt(expenseId: number, checked: boolean) {
    setReceiptIds((prev) => {
      const s = new Set(prev)
      if (checked) s.add(expenseId)
      else s.delete(expenseId)
      return [...s]
    })
  }

  function toggleCheck(fileId: number, checked: boolean) {
    setCheckIds((prev) => {
      const s = new Set(prev)
      if (checked) s.add(fileId)
      else s.delete(fileId)
      return [...s]
    })
  }

  return (
    <div className="container-fluid mt-4">
      <h2 className="text-center mt-4 mb-3">Reimbursed Expenses</h2>

      {error ? <div className="alert alert-danger">{error}</div> : null}

      <form onSubmit={applyFilter} className="row g-3 mb-4">
        <div className="col-md-2">
          <label className="form-label">Semester</label>
          <select name="semester" className="form-select" defaultValue={semester}>
            <option value="">All</option>
            <option value="Fall">Fall</option>
            <option value="Spring">Spring</option>
          </select>
        </div>
        <div className="col-md-2">
          <label className="form-label">Status</label>
          <select name="status" className="form-select" defaultValue={status}>
            <option value="">All</option>
            {['Pending', 'Approved', 'Rejected', 'Paid'].map((opt) => (
              <option key={opt} value={opt}>
                {opt}
              </option>
            ))}
          </select>
        </div>
        <div className="col-md-2">
          <label className="form-label">School Year</label>
          <select name="school_year" className="form-select" defaultValue={schoolYear}>
            <option value="">All</option>
            {options.map((option) => (
              <option key={option.value} value={option.value}>
                {option.label}
              </option>
            ))}
          </select>
        </div>
        <div className="col-md-3">
          <label className="form-label">Reimbursed To</label>
          <select name="user_id" className="form-select" defaultValue={userId}>
            <option value="">All</option>
            {users.map((u) => (
              <option key={String(u.id)} value={String(u.id)}>
                {`${u.firstname ?? ''} ${u.lastname ?? ''}`.trim()}
              </option>
            ))}
          </select>
        </div>
        <div className="col-md-3 d-flex gap-2 justify-content-end align-items-end mb-3">
          <button className="btn btn-primary" type="submit">
            Filter
          </button>
          <button
            type="button"
            className="btn btn-success"
            onClick={() =>
              downloadReimbursementsExport({
                semester: semester || undefined,
                status: status || undefined,
                school_year: schoolYear || undefined,
                user_id: userId || undefined,
              }).catch(() => alert('Export failed.'))
            }
          >
            Export CSV
          </button>
          <Link to="/app/administrator/reimbursements/under-processing" className="btn btn-warning">
            Reimbursement Under Processing
          </Link>
        </div>
      </form>

      {!batchSummaries.length && !donationBatch ? (
        <p className="text-muted">No batch data for the current filters.</p>
      ) : (
        <div className="mb-4">
          <div className="d-flex align-items-center gap-2 mb-2">
            <h5 className="mb-0">Submitted Batches</h5>
          </div>
          <div className="row g-3">
            {batchSummaries.map((batch) => {
              const bid = Number(batch.batch_id ?? 0)
              const title = String(batch.title ?? `Batch #${bid}`)
              const details = (batchDetails[String(bid)] ?? {
                items: [],
                checks: [],
              }) as BatchDetailPayload
              const items = details.items ?? []
              const checks = details.checks ?? []
              const isOpen = openBatches[String(bid)] ?? false
              const groups = groupItemsByPurchaser(items)
              return (
                <div key={bid} className="col-12">
                  <div className="card shadow-sm h-100">
                    <button
                      type="button"
                      className="card-body text-start w-100 border-0 bg-white p-3"
                      onClick={() =>
                        setOpenBatches((o) => ({ ...o, [String(bid)]: !o[String(bid)] }))
                      }
                    >
                      <div className="d-flex justify-content-between align-items-start">
                        <div>
                          <h6 className="card-title mb-1">{title}</h6>
                          <div className="text-muted small">
                            Items: {Number(batch.items ?? 0)} • Amount: ${money(batch.amount)}
                            {batch.closed_at ? <> • Closed: {String(batch.closed_at)}</> : null}
                          </div>
                        </div>
                        <span className="badge bg-light text-dark">{isOpen ? 'Collapse' : 'Expand'}</span>
                      </div>
                    </button>
                    {isOpen ? (
                      <div className="px-3 pb-3">
                        {groups.length > 0 ? (
                          <div className="mt-2">
                            <div className="fw-semibold small text-muted mb-2">Items</div>
                            {groups.map((g) => (
                              <div
                                key={g.purchaser}
                                className="p-3 mb-3 rounded border bg-light"
                                style={{ borderColor: '#e5e7eb' }}
                              >
                                <div className="d-flex justify-content-between border-bottom pb-2 mb-2">
                                  <div className="fw-semibold">{g.purchaser}</div>
                                  <div className="text-muted small">Total: ${money(g.total)}</div>
                                </div>
                                <ul className="list-group list-group-flush">
                                  {g.items.map((item, idx) => (
                                    <li
                                      key={idx}
                                      className="list-group-item px-0 d-flex justify-content-between bg-transparent"
                                    >
                                      <div>
                                        <div className="fw-semibold">
                                          {String(item.description || 'No description')}
                                        </div>
                                        <div className="text-muted small">
                                          {String(item.vendor || 'Vendor N/A')}
                                          {item.receipt_url ? (
                                            <>
                                              {' '}
                                              •{' '}
                                              <a
                                                href={String(item.receipt_url)}
                                                target="_blank"
                                                rel="noopener noreferrer"
                                              >
                                                Receipt
                                              </a>
                                            </>
                                          ) : null}
                                        </div>
                                      </div>
                                      <div className="fw-semibold">${money(item.amount)}</div>
                                    </li>
                                  ))}
                                </ul>
                              </div>
                            ))}
                          </div>
                        ) : null}
                        {checks.length > 0 ? (
                          <div className="mt-3">
                            <div className="fw-semibold small text-muted mb-2">Uploaded Checks</div>
                            <ul className="list-group list-group-flush">
                              {checks.map((file, idx) => (
                                <li
                                  key={idx}
                                  className="list-group-item px-0 d-flex justify-content-between align-items-center"
                                >
                                  <div>
                                    <div className="fw-semibold">{String(file.admin ?? 'Admin')}</div>
                                    <div className="text-muted small">
                                      {String(file.original ?? file.filename ?? '')}
                                    </div>
                                  </div>
                                  {file.url ? (
                                    <a
                                      className="btn btn-sm btn-outline-primary"
                                      href={String(file.url)}
                                      target="_blank"
                                      rel="noopener noreferrer"
                                    >
                                      View
                                    </a>
                                  ) : null}
                                </li>
                              ))}
                            </ul>
                          </div>
                        ) : null}
                      </div>
                    ) : null}
                    <div className="card-footer bg-light d-flex justify-content-between align-items-center flex-wrap gap-2">
                      <span className="text-muted small">ID: {bid}</span>
                      <div className="d-flex gap-2">
                        <button
                          type="button"
                          className="btn btn-sm btn-outline-primary"
                          onClick={() => openEmailModal(bid, title)}
                        >
                          Send To
                        </button>
                        <button
                          type="button"
                          className="btn btn-sm btn-outline-success"
                          onClick={() =>
                            downloadBatchCsv(bid).catch(() => alert('Download failed.'))
                          }
                        >
                          Download CSV
                        </button>
                      </div>
                    </div>
                  </div>
                </div>
              )
            })}

            {donationBatch ? (
              <div className="col-12">
                <div className="card shadow-sm h-100 border-secondary">
                  <button
                    type="button"
                    className="card-body text-start w-100 border-0 bg-white p-3"
                      onClick={() =>
                      setOpenBatches((o) => ({ ...o, donation: !o['donation'] }))
                    }
                  >
                    <div className="d-flex justify-content-between align-items-start">
                      <div>
                        <h6 className="card-title mb-1">
                          {String(donationBatch.title ?? 'Donations')}
                        </h6>
                        <div className="text-muted small">
                          Items: {Number(donationBatch.items ?? 0)} • Amount: $
                          {money(donationBatch.amount)}
                        </div>
                      </div>
                      <span className="badge bg-light text-dark">
                        {openBatches['donation'] ? 'Collapse' : 'Expand'}
                      </span>
                    </div>
                  </button>
                  {openBatches['donation'] ? (
                    <div className="px-3 pb-3">
                      {groupItemsByPurchaser(donationDetails.items ?? []).map((g) => (
                        <div
                          key={g.purchaser}
                          className="p-3 mb-3 rounded border bg-light"
                          style={{ borderColor: '#e5e7eb' }}
                        >
                          <div className="d-flex justify-content-between border-bottom pb-2 mb-2">
                            <div className="fw-semibold">{g.purchaser}</div>
                            <div className="text-muted small">Total: ${money(g.total)}</div>
                          </div>
                          <ul className="list-group list-group-flush">
                            {g.items.map((item, idx) => (
                              <li
                                key={idx}
                                className="list-group-item px-0 d-flex justify-content-between bg-transparent"
                              >
                                <div>
                                  <div className="fw-semibold">
                                    {String(item.description || 'No description')}
                                  </div>
                                  <div className="text-muted small">
                                    {String(item.vendor || 'Vendor N/A')}
                                  </div>
                                </div>
                                <div className="fw-semibold">${money(item.amount)}</div>
                              </li>
                            ))}
                          </ul>
                        </div>
                      ))}
                    </div>
                  ) : null}
                  <div className="card-footer bg-light d-flex justify-content-between align-items-center">
                    <span className="text-muted small">Category: Donation</span>
                    <span className="text-muted small">Not reimbursable</span>
                  </div>
                </div>
              </div>
            ) : null}
          </div>
        </div>
      )}

      <div className="alert alert-secondary mb-0">
        Individual reimbursement table is hidden. Use the submitted batch cards above or export CSV for
        details.
      </div>

      {emailOpen ? (
        <div className="modal show d-block" tabIndex={-1} style={{ background: 'rgba(0,0,0,.35)' }}>
          <div className="modal-dialog modal-dialog-centered modal-lg">
            <div className="modal-content">
              <form onSubmit={submitEmail}>
                <div className="modal-header">
                  <h5 className="modal-title">{emailTitle}</h5>
                  <button type="button" className="btn-close" onClick={() => setEmailOpen(false)} />
                </div>
                <div className="modal-body">
                  <div className="mb-3">
                    <label className="form-label" htmlFor="batchEmailRecipient">
                      Recipient Email
                    </label>
                    <input
                      type="email"
                      id="batchEmailRecipient"
                      className="form-control"
                      required
                      value={recipientEmail}
                      onChange={(e) => setRecipientEmail(e.target.value)}
                      placeholder="recipient@example.com"
                    />
                  </div>
                  <div className="mb-3">
                    <label className="form-label" htmlFor="batchEmailMessage">
                      Message (optional)
                    </label>
                    <textarea
                      id="batchEmailMessage"
                      className="form-control"
                      rows={4}
                      value={emailMessage}
                      onChange={(e) => setEmailMessage(e.target.value)}
                    />
                  </div>
                  <div className="mb-3">
                    <div className="d-flex justify-content-between align-items-center mb-2">
                      <span className="fw-semibold">Attachments</span>
                      <small className="text-muted">Uncheck to omit from the email.</small>
                    </div>
                    <div className="list-group list-group-flush">
                      {(attachmentMeta[String(emailBatchId ?? '')] as AttachmentEntry | undefined)?.receipts?.map(
                        (item, idx) => {
                          const id = Number(item.expense_id)
                          const vendor = String(item.vendor ?? 'Vendor N/A')
                          return (
                            <label
                              key={`r-${idx}`}
                              className="list-group-item d-flex align-items-start gap-2"
                            >
                              <input
                                type="checkbox"
                                className="form-check-input mt-1"
                                checked={receiptIds.includes(id)}
                                onChange={(e) => toggleReceipt(id, e.target.checked)}
                              />
                              <span>
                                <strong>{vendor}</strong>
                                <span className="text-muted small d-block">
                                  {String(item.description ?? '')}
                                </span>
                              </span>
                            </label>
                          )
                        },
                      )}
                      {(attachmentMeta[String(emailBatchId ?? '')] as AttachmentEntry | undefined)?.checks?.map(
                        (file, idx) => {
                          const id = Number(file.file_id)
                          return (
                            <label
                              key={`c-${idx}`}
                              className="list-group-item d-flex align-items-start gap-2"
                            >
                              <input
                                type="checkbox"
                                className="form-check-input mt-1"
                                checked={checkIds.includes(id)}
                                onChange={(e) => toggleCheck(id, e.target.checked)}
                              />
                              <span>
                                <strong>{String(file.admin ?? 'Check')}</strong>
                                <span className="text-muted small d-block">
                                  {String(file.original_filename ?? file.filename ?? '')}
                                </span>
                              </span>
                            </label>
                          )
                        },
                      )}
                    </div>
                    <p className="text-muted small mt-2 mb-0">
                      Receipts and check scans are packaged into zipped archives.
                    </p>
                  </div>
                  {emailStatus ? <div className="alert alert-info py-2">{emailStatus}</div> : null}
                </div>
                <div className="modal-footer">
                  <button type="button" className="btn btn-secondary" onClick={() => setEmailOpen(false)}>
                    Cancel
                  </button>
                  <button type="submit" className="btn btn-primary">
                    Send Email
                  </button>
                </div>
              </form>
            </div>
          </div>
        </div>
      ) : null}

      <style>{`
        .wrap-headers thead th { white-space: normal !important; vertical-align: middle; }
      `}</style>
    </div>
  )
}
