import { useCallback, useEffect, useMemo, useState } from 'react'
import { Link, useNavigate, useSearchParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import {
  fetchAuthenticatedBlobUrl,
  fetchManualPayPage,
  fetchManualPaySuggest,
  manualPayCheckFileUrl,
  submitManualPayEdit,
  submitManualPayUpdate,
  type ManualPayPageResponse,
} from '../../api/paymentManagement'

function fmtMoney(n: unknown): string {
  const v = Number(n)
  return `$${Number.isFinite(v) ? v.toFixed(2) : '0.00'}`
}

function paymentDisplayDate(p: Record<string, unknown>): string {
  const raw = p.updated_at ?? p.update_at ?? p.payment_date
  if (raw == null || raw === '') return '—'
  const d = new Date(String(raw).replace(' ', 'T'))
  if (Number.isNaN(d.valueOf())) return String(raw)
  const pad = (n: number) => String(n).padStart(2, '0')
  return `${pad(d.getMonth() + 1)}-${pad(d.getDate())}-${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}`
}

function methodBadge(method: unknown) {
  const m = String(method ?? '').toLowerCase().trim()
  if (m === 'cash')
    return <span className="badge text-bg-success">Cash</span>
  if (m === 'check') return <span className="badge text-bg-info">Check</span>
  if (m === 'card' || m === 'debit/credit card')
    return <span className="badge text-bg-primary">Card</span>
  return <span className="badge bg-secondary">{String(method ?? '')}</span>
}

export function ManualPayPage() {
  const navigate = useNavigate()
  const [searchParams] = useSearchParams()
  const termFromUrl = searchParams.get('search_term') ?? ''

  const [searchInput, setSearchInput] = useState(termFromUrl)
  const [data, setData] = useState<ManualPayPageResponse | null>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [suggestOpen, setSuggestOpen] = useState(false)
  const [suggestions, setSuggestions] = useState<Array<{ label?: string; email?: string }>>([])
  const [previewBlobUrl, setPreviewBlobUrl] = useState<string | null>(null)
  const [showAddModal, setShowAddModal] = useState(false)
  const [editPaymentId, setEditPaymentId] = useState<number | string | null>(null)

  const activeTerm = termFromUrl

  const load = useCallback(
    (term: string) => {
      if (!term.trim()) {
        setData(null)
        return
      }
      setLoading(true)
      setError(null)
      fetchManualPayPage({ search_term: term.trim() })
        .then(setData)
        .catch((e: unknown) =>
          setError(e instanceof ApiHttpError ? e.message : 'Could not load manual pay data.'),
        )
        .finally(() => setLoading(false))
    },
    [],
  )

  useEffect(() => {
    setSearchInput(termFromUrl)
    load(termFromUrl)
  }, [termFromUrl, load])

  useEffect(() => {
    let t: ReturnType<typeof setTimeout>
    if (searchInput.trim().length < 2) {
      setSuggestions([])
      return
    }
    t = setTimeout(() => {
      fetchManualPaySuggest(searchInput.trim())
        .then((rows) => {
          setSuggestions(
            rows.map((r) => ({
              label: String(r.label ?? r.email ?? r.phone ?? ''),
              email: r.email ? String(r.email) : undefined,
            })),
          )
          setSuggestOpen(true)
        })
        .catch(() => setSuggestions([]))
    }, 250)
    return () => clearTimeout(t)
  }, [searchInput])

  function onSearchSubmit(e: React.FormEvent) {
    e.preventDefault()
    const q = searchInput.trim()
    if (!q) return
    navigate({ pathname: '/app/administrator/payment/manual-pay', search: `?search_term=${encodeURIComponent(q)}` })
  }

  function pickSuggestion(text: string) {
    setSearchInput(text)
    setSuggestOpen(false)
    navigate({
      pathname: '/app/administrator/payment/manual-pay',
      search: `?search_term=${encodeURIComponent(text)}`,
    })
  }

  const parent = data?.parent as Record<string, unknown> | null | undefined
  const students = (data?.students ?? []) as Array<Record<string, unknown>>
  const payments = (data?.payments ?? []) as Array<Record<string, unknown>>
  const invoices = (data?.invoices ?? []) as Array<Record<string, unknown>>

  const invoiceOptions = useMemo(() => invoices, [invoices])

  async function onAddPayment(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault()
    const fd = new FormData(e.currentTarget)
    fd.set('search_term', activeTerm)
    try {
      await submitManualPayUpdate(fd)
      setShowAddModal(false)
      load(activeTerm)
    } catch (err: unknown) {
      setError(err instanceof ApiHttpError ? err.message : 'Add payment failed.')
    }
  }

  async function onEditPayment(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault()
    const fd = new FormData(e.currentTarget)
    fd.set('search_term', activeTerm)
    try {
      await submitManualPayEdit(fd)
      setEditPaymentId(null)
      load(activeTerm)
    } catch (err: unknown) {
      setError(err instanceof ApiHttpError ? err.message : 'Edit failed.')
    }
  }

  async function openPreview(fileKey: string) {
    try {
      if (previewBlobUrl) URL.revokeObjectURL(previewBlobUrl)
      const url = await fetchAuthenticatedBlobUrl(manualPayCheckFileUrl(fileKey, 'inline'))
      setPreviewBlobUrl(url)
    } catch {
      setError('Could not load file preview.')
    }
  }

  useEffect(() => {
    return () => {
      if (previewBlobUrl) URL.revokeObjectURL(previewBlobUrl)
    }
  }, [previewBlobUrl])

  const editPayment = editPaymentId != null ? payments.find((p) => String(p.id) === String(editPaymentId)) : null

  return (
    <div className="container mt-4">
      <h2 className="text-center mt-4 mb-3">Manual Payment</h2>
      {error ? <div className="alert alert-danger">{error}</div> : null}

      <form onSubmit={onSearchSubmit} className="mb-3 position-relative">
        <div className="input-group">
          <input
            type="text"
            className="form-control"
            placeholder="Enter Parent Email or Phone"
            required
            autoComplete="off"
            value={searchInput}
            onChange={(e) => setSearchInput(e.target.value)}
            onFocus={() => suggestions.length > 0 && setSuggestOpen(true)}
          />
          <button className="btn btn-primary" type="submit" disabled={loading}>
            Search
          </button>
        </div>
        {suggestOpen && suggestions.length > 0 ? (
          <div className="list-group position-absolute w-100 shadow-sm" style={{ zIndex: 10 }}>
            {suggestions.map((s, i) => (
              <button
                key={i}
                type="button"
                className="list-group-item list-group-item-action"
                onClick={() => pickSuggestion(s.label ?? s.email ?? '')}
              >
                {s.label || s.email}
              </button>
            ))}
          </div>
        ) : null}
      </form>

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

      {parent ? (
        <>
          <div className="row mb-4">
            <div className="col-md-6">
              <div className="card">
                <div className="card-header">Parent Information</div>
                <div className="card-body">
                  <p>
                    <strong>Name:</strong> {String(parent.firstname ?? '')}{' '}
                    {String(parent.lastname ?? '')}
                  </p>
                  <p>
                    <strong>Phone:</strong> {String(parent.cellphone ?? '')}
                  </p>
                  <p>
                    <strong>Email:</strong> {String(parent.email ?? '')}
                  </p>
                </div>
              </div>
            </div>
            <div className="col-md-6">
              <div className="card">
                <div className="card-header">Students</div>
                <div className="card-body">
                  {students.length === 0 ? (
                    <p>No students found.</p>
                  ) : (
                    <ul className="list-group">
                      {students.map((st, idx) => (
                        <li key={idx} className="list-group-item">
                          {String(st.firstname ?? '')} {String(st.lastname ?? '')}
                        </li>
                      ))}
                    </ul>
                  )}
                </div>
              </div>
            </div>
          </div>

          <h5>Payments</h5>
          <div className="table-responsive">
            <table className="table table-bordered">
              <thead>
                <tr>
                  <th>Paid Date</th>
                  <th>Paid Amount</th>
                  <th>Balance</th>
                  <th>Payment Method</th>
                  <th>Check Number</th>
                  <th>Installments</th>
                  <th>Status</th>
                  <th>Check/Card File</th>
                  <th>Action</th>
                </tr>
              </thead>
              <tbody>
                {payments.map((payment) => {
                  const fid = payment.check_file ? String(payment.check_file) : ''
                  return (
                    <tr key={String(payment.id)}>
                      <td>{paymentDisplayDate(payment)}</td>
                      <td>{fmtMoney(payment.paid_amount)}</td>
                      <td>{fmtMoney(payment.balance)}</td>
                      <td>{methodBadge(payment.payment_method)}</td>
                      <td>{payment.check_number ? String(payment.check_number) : '—'}</td>
                      <td>{String(payment.number_of_installments ?? '')}</td>
                      <td>{String(payment.status ?? '')}</td>
                      <td>
                        {fid ? (
                          <>
                            <button
                              type="button"
                              className="btn btn-link btn-sm p-0 me-2"
                              onClick={() => openPreview(fid)}
                            >
                              View
                            </button>
                            <a
                              className="small"
                              href="#download"
                              onClick={async (ev) => {
                                ev.preventDefault()
                                try {
                                  const url = await fetchAuthenticatedBlobUrl(
                                    manualPayCheckFileUrl(fid, 'download'),
                                  )
                                  const a = document.createElement('a')
                                  a.href = url
                                  a.download = 'payment-file'
                                  a.click()
                                  URL.revokeObjectURL(url)
                                } catch {
                                  setError('Download failed.')
                                }
                              }}
                            >
                              Download
                            </a>
                          </>
                        ) : (
                          '—'
                        )}
                      </td>
                      <td>
                        <button
                          type="button"
                          className="btn btn-sm btn-secondary"
                          onClick={() => setEditPaymentId(payment.id as number | string)}
                        >
                          Edit
                        </button>
                      </td>
                    </tr>
                  )
                })}
              </tbody>
            </table>
          </div>

          {invoices.length > 0 ? (
            <>
              <h5 className="mt-4">Invoices</h5>
              <div className="table-responsive">
                <table className="table table-bordered">
                  <thead>
                    <tr>
                      <th>Invoice #</th>
                      <th>Total</th>
                      <th>Paid</th>
                      <th>Discount</th>
                      <th>Refunds</th>
                      <th>Balance</th>
                      <th>Status</th>
                      <th>Due Date</th>
                    </tr>
                  </thead>
                  <tbody>
                    {invoices.map((inv) => {
                      const total = Number(inv.total_amount ?? 0)
                      const paid = Number(inv.paid_amount ?? 0)
                      const disc = Number(inv.discount ?? 0)
                      const ref = Number(inv.refund_paid ?? 0)
                      const bal = Math.max(0, total - paid - disc - ref)
                      return (
                        <tr key={String(inv.id ?? inv.invoice_number)}>
                          <td>{String(inv.invoice_number ?? '')}</td>
                          <td>{fmtMoney(total)}</td>
                          <td>{fmtMoney(paid)}</td>
                          <td>{fmtMoney(disc)}</td>
                          <td>{fmtMoney(ref)}</td>
                          <td>{fmtMoney(bal)}</td>
                          <td>{String(inv.status ?? '')}</td>
                          <td>{inv.due_date ? String(inv.due_date) : ''}</td>
                        </tr>
                      )
                    })}
                  </tbody>
                </table>
              </div>
            </>
          ) : null}

          <div className="text-end mb-3">
            <button type="button" className="btn btn-primary" onClick={() => setShowAddModal(true)}>
              Add Payment
            </button>
          </div>
        </>
      ) : null}

      {!loading && activeTerm && !parent ? (
        <p className="text-muted">No parent found for this search.</p>
      ) : null}

      {showAddModal ? (
        <div className="modal show d-block" tabIndex={-1} style={{ background: 'rgba(0,0,0,.4)' }}>
          <div className="modal-dialog">
            <div className="modal-content">
              <form onSubmit={onAddPayment} encType="multipart/form-data">
                <div className="modal-header">
                  <h5 className="modal-title">Add Manual Payment</h5>
                  <button
                    type="button"
                    className="btn-close"
                    aria-label="Close"
                    onClick={() => setShowAddModal(false)}
                  />
                </div>
                <div className="modal-body">
                  <div className="mb-3">
                    <label className="form-label" htmlFor="invoice_id">
                      Select Invoice
                    </label>
                    <select name="invoice_id" id="invoice_id" className="form-select" required>
                      {invoiceOptions.map((inv) => (
                        <option key={String(inv.id)} value={String(inv.id)}>
                          Invoice {String(inv.invoice_number ?? inv.id)}
                        </option>
                      ))}
                    </select>
                  </div>
                  <div className="mb-3">
                    <label className="form-label" htmlFor="paid_amount">
                      Paid amount
                    </label>
                    <input
                      name="paid_amount"
                      id="paid_amount"
                      type="number"
                      step="0.01"
                      className="form-control"
                      required
                    />
                  </div>
                  <div className="mb-3">
                    <label className="form-label">Payment method</label>
                    <select name="payment_method" className="form-select" required>
                      <option value="Cash">Cash</option>
                      <option value="Check">Check</option>
                      <option value="Card">Debit/Credit Card</option>
                    </select>
                  </div>
                  <div className="mb-3">
                    <label className="form-label">Check number</label>
                    <input name="check_number" type="text" className="form-control" />
                  </div>
                  <div className="mb-3">
                    <label className="form-label">Payment file</label>
                    <input name="payment_file" type="file" className="form-control" accept=".jpg,.jpeg,.png,.pdf" />
                  </div>
                </div>
                <div className="modal-footer">
                  <button type="submit" className="btn btn-success">
                    Save
                  </button>
                  <button type="button" className="btn btn-secondary" onClick={() => setShowAddModal(false)}>
                    Cancel
                  </button>
                </div>
              </form>
            </div>
          </div>
        </div>
      ) : null}

      {editPayment ? (
        <div className="modal show d-block" tabIndex={-1} style={{ background: 'rgba(0,0,0,.4)' }}>
          <div className="modal-dialog">
            <div className="modal-content">
              <form onSubmit={onEditPayment} encType="multipart/form-data">
                <input type="hidden" name="payment_id" value={String(editPayment.id)} />
                <div className="modal-header">
                  <h5 className="modal-title">Edit Payment #{String(editPayment.id)}</h5>
                  <button
                    type="button"
                    className="btn-close"
                    aria-label="Close"
                    onClick={() => setEditPaymentId(null)}
                  />
                </div>
                <div className="modal-body">
                  <div className="mb-3">
                    <label className="form-label">Paid Amount</label>
                    <input
                      name="paid_amount"
                      type="number"
                      step="0.01"
                      className="form-control"
                      defaultValue={String(editPayment.paid_amount ?? '')}
                      required
                    />
                  </div>
                  <div className="mb-3">
                    <label className="form-label">Payment Method</label>
                    <select
                      name="payment_method"
                      className="form-select"
                      defaultValue={String(editPayment.payment_method ?? 'Cash')}
                      required
                    >
                      <option value="Cash">Cash</option>
                      <option value="Check">Check</option>
                      <option value="Card">Debit/Credit Card</option>
                    </select>
                  </div>
                  <div className="mb-3">
                    <label className="form-label">Check Number</label>
                    <input
                      name="check_number"
                      type="text"
                      className="form-control"
                      defaultValue={String(editPayment.check_number ?? '')}
                    />
                  </div>
                  <div className="mb-3">
                    <label className="form-label">Replace Payment File (optional)</label>
                    <input name="payment_file" type="file" className="form-control" accept=".jpg,.jpeg,.png,.pdf" />
                  </div>
                </div>
                <div className="modal-footer">
                  <button type="submit" className="btn btn-success">
                    Save Changes
                  </button>
                  <button type="button" className="btn btn-secondary" onClick={() => setEditPaymentId(null)}>
                    Cancel
                  </button>
                </div>
              </form>
            </div>
          </div>
        </div>
      ) : null}

      {previewBlobUrl ? (
        <div className="modal show d-block" tabIndex={-1} style={{ background: 'rgba(0,0,0,.5)' }}>
          <div className="modal-dialog modal-lg modal-dialog-centered">
            <div className="modal-content">
              <div className="modal-header">
                <h5 className="modal-title">Check/Card File</h5>
                <button
                  type="button"
                  className="btn-close"
                  onClick={() => {
                    if (previewBlobUrl) URL.revokeObjectURL(previewBlobUrl)
                    setPreviewBlobUrl(null)
                  }}
                />
              </div>
              <div className="modal-body text-center">
                <iframe src={previewBlobUrl} title="Preview" width="100%" height={480} style={{ border: 'none' }} />
              </div>
            </div>
          </div>
        </div>
      ) : null}

      <p className="small text-muted mt-4">
        <Link to="/app/administrator/family">Family directory</Link>
      </p>
    </div>
  )
}
