'use client'

import { useEffect, useMemo, useState } from 'react'
import { useRouter } from 'next/navigation'
import { api, type ApiError } from '@/lib/api'
import { useAuth } from '@/lib/auth'
import { useAuthModal } from '@/lib/authModal'
import { money } from '@/lib/format'
import type { Paginated, Address } from '@/lib/types'

interface LabTest {
  id: number; name: string; category?: string | null; description?: string | null
  sample_type?: string | null; preparation?: string | null; price?: number | string | null
  home_collection?: boolean; turnaround_hours?: number | null
}

interface LabBundle {
  id: number; name: string; description?: string | null; price?: number | string | null
  tests?: LabTest[]
}

function num(v: number | string | null | undefined): number {
  const n = typeof v === 'string' ? parseFloat(v) : (v ?? 0)
  return isFinite(n) ? n : 0
}

export default function LabsPage() {
  const router = useRouter()
  const { user } = useAuth()
  const showAuth = useAuthModal((s) => s.show)

  const [tests, setTests] = useState<LabTest[]>([])
  const [bundles, setBundles] = useState<LabBundle[]>([])
  const [loading, setLoading] = useState(true)
  const [selected, setSelected] = useState<Record<number, LabTest>>({})
  const [open, setOpen] = useState(false)

  const [q, setQ] = useState('')
  const [cat, setCat] = useState('')
  const [homeOnly, setHomeOnly] = useState(false)
  const [sort, setSort] = useState('')

  const [mode, setMode] = useState<'home' | 'at_lab'>('home')
  const [saved, setSaved] = useState<Address[]>([])
  const [addr, setAddr] = useState({ line1: '', city: '' })
  const [scheduledAt, setScheduledAt] = useState('')
  const [notes, setNotes] = useState('')
  const [placing, setPlacing] = useState(false)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    api.get<Paginated<LabTest>>('/lab/tests?per_page=200')
      .then((r) => setTests(r.data ?? []))
      .catch(() => setTests([]))
      .finally(() => setLoading(false))
    api.get<{ data?: LabBundle[] } | LabBundle[]>('/lab/bundles')
      .then((r) => setBundles((r as { data?: LabBundle[] }).data ?? (r as LabBundle[]) ?? []))
      .catch(() => setBundles([]))
  }, [])

  useEffect(() => {
    if (!user) return
    api.get<{ data?: Address[] } | Address[]>('/addresses', true)
      .then((r) => {
        const list = (r as { data?: Address[] }).data ?? (r as Address[])
        setSaved(list)
        if (list[0]) setAddr({ line1: list[0].formatted_address, city: list[0].city || '' })
      })
      .catch(() => setSaved([]))
  }, [user])

  const categories = useMemo(() => {
    const set = new Set<string>()
    tests.forEach((t) => { if (t.category) set.add(t.category) })
    return Array.from(set).sort()
  }, [tests])

  const visible = useMemo(() => {
    let list = tests
    if (cat) list = list.filter((t) => t.category === cat)
    if (homeOnly) list = list.filter((t) => t.home_collection)
    if (q.trim()) {
      const term = q.trim().toLowerCase()
      list = list.filter((t) => t.name.toLowerCase().includes(term) || (t.category || '').toLowerCase().includes(term))
    }
    if (sort === 'price_asc') list = [...list].sort((a, b) => num(a.price) - num(b.price))
    else if (sort === 'price_desc') list = [...list].sort((a, b) => num(b.price) - num(a.price))
    else if (sort === 'name') list = [...list].sort((a, b) => a.name.localeCompare(b.name))
    return list
  }, [tests, cat, homeOnly, q, sort])

  const ids = Object.keys(selected).map(Number)
  const total = ids.reduce((n, id) => n + num(selected[id]?.price), 0)

  const toggle = (t: LabTest) => {
    setSelected((s) => {
      const next = { ...s }
      if (next[t.id]) delete next[t.id]
      else next[t.id] = t
      return next
    })
  }

  const addBundle = (b: LabBundle) => {
    setSelected((s) => {
      const next = { ...s }
      ;(b.tests ?? []).forEach((t) => { next[t.id] = t })
      return next
    })
  }

  const book = async () => {
    if (!user) { showAuth('login'); return }
    if (ids.length === 0) { setError('Select at least one test.'); return }
    if (mode === 'home' && (!addr.line1 || !addr.city)) { setError('Enter a collection address.'); return }
    setPlacing(true); setError(null)
    try {
      const res = await api.post<{ lab_order?: { id?: number }; payment?: { checkout_url?: string | null } | null }>('/lab/orders', {
        test_ids: ids,
        collection_mode: mode,
        collection_address: mode === 'home' ? { line1: addr.line1, city: addr.city } : undefined,
        scheduled_at: scheduledAt || undefined,
        notes: notes || undefined,
        source: 'web',
      }, true)
      const url = res.payment?.checkout_url
      if (url) { window.location.href = url; return }
      router.push('/account?tab=lab&placed=1')
    } catch (e) {
      setError((e as ApiError).message || 'Could not place lab order.')
      setPlacing(false)
    }
  }

  return (
    <div className="container-x py-8 pb-28">
      <h1 className="h-section">Lab tests &amp; diagnostics</h1>
      <p className="mt-1 text-sm text-muted">Book tests from accredited labs — many with home sample collection.</p>

      {bundles.length > 0 && (
        <div className="mt-6">
          <div className="eyebrow mb-2">Popular packages</div>
          <div className="flex gap-3 overflow-x-auto pb-2">
            {bundles.map((b) => (
              <div key={b.id} className="card flex w-64 shrink-0 flex-col p-4">
                <h3 className="font-semibold">{b.name}</h3>
                {b.description && <p className="mt-1 line-clamp-2 text-[12px] text-muted">{b.description}</p>}
                <div className="text-[12px] text-muted">{(b.tests ?? []).length} tests</div>
                <div className="mt-auto flex items-center justify-between pt-3">
                  {b.price != null && <span className="font-bold text-brand">{money(b.price)}</span>}
                  <button onClick={() => addBundle(b)} className="btn btn-primary btn-sm">Add package</button>
                </div>
              </div>
            ))}
          </div>
        </div>
      )}

      <div className="mt-6 space-y-3">
        <div className="relative">
          <svg className="absolute left-3.5 top-1/2 -translate-y-1/2 text-muted" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="11" cy="11" r="7" /><path d="m21 21-4.3-4.3" /></svg>
          <input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search tests…" className="w-full rounded-xl border border-hair bg-soft py-2.5 pl-10 pr-4 text-sm outline-none focus:border-brand" />
        </div>
        <div className="flex items-center gap-3">
          <div className="flex flex-1 flex-wrap gap-1.5">
            <button onClick={() => setCat('')} className={chip(cat === '')}>All</button>
            {categories.map((c) => <button key={c} onClick={() => setCat(c)} className={chip(cat === c)}>{c}</button>)}
          </div>
        </div>
        <div className="flex items-center gap-3">
          <label className="flex cursor-pointer items-center gap-1.5 text-[13px] text-muted">
            <input type="checkbox" checked={homeOnly} onChange={(e) => setHomeOnly(e.target.checked)} /> Home collection
          </label>
          <span className="ml-auto text-sm text-muted">{visible.length} test{visible.length === 1 ? '' : 's'}</span>
          <select value={sort} onChange={(e) => setSort(e.target.value)} className="input w-auto py-1.5 text-[13px]">
            <option value="">Sort: Default</option>
            <option value="price_asc">Price: Low to High</option>
            <option value="price_desc">Price: High to Low</option>
            <option value="name">Name: A–Z</option>
          </select>
        </div>
      </div>

      <div className="mt-5 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
        {loading ? (
          Array.from({ length: 6 }).map((_, i) => <div key={i} className="card h-40 animate-pulse bg-soft" />)
        ) : visible.length === 0 ? (
          <div className="col-span-full card p-12 text-center text-muted">No lab tests match your search.</div>
        ) : (
          visible.map((t) => {
            const on = !!selected[t.id]
            return (
              <div key={t.id} className={`card flex flex-col p-5 ${on ? 'border-brand ring-1 ring-brand' : ''}`}>
                <div className="flex items-start justify-between gap-2">
                  <h2 className="font-semibold">{t.name}</h2>
                  {t.home_collection && <span className="tag tag-otc shrink-0">Home</span>}
                </div>
                {t.category && <div className="text-[12px] uppercase tracking-wide text-muted">{t.category}</div>}
                {t.description && <p className="mt-2 line-clamp-2 text-[13px] text-muted">{t.description}</p>}
                <div className="mt-3 flex items-center gap-3 text-[12px] text-muted">
                  {t.sample_type && <span>{t.sample_type}</span>}
                  {t.turnaround_hours ? <span>· {t.turnaround_hours}h</span> : null}
                </div>
                <div className="mt-auto flex items-center justify-between pt-3">
                  {t.price != null && <span className="font-bold text-brand">{money(t.price)}</span>}
                  <button onClick={() => toggle(t)} className={`btn btn-sm ${on ? 'btn-ghost' : 'btn-primary'}`}>{on ? 'Remove' : 'Add'}</button>
                </div>
              </div>
            )
          })
        )}
      </div>

      {ids.length > 0 && !open && (
        <div className="fixed inset-x-0 bottom-0 z-40 border-t border-hair bg-white/95 backdrop-blur">
          <div className="container-x flex items-center justify-between py-3">
            <div className="text-sm"><span className="font-bold">{ids.length}</span> test{ids.length > 1 ? 's' : ''} · <span className="font-bold text-brand">{money(total)}</span></div>
            <button onClick={() => setOpen(true)} className="btn btn-primary">Continue to booking</button>
          </div>
        </div>
      )}

      {open && (
        <div className="fixed inset-0 z-50 flex items-end justify-center bg-black/40 sm:items-center" onClick={() => setOpen(false)}>
          <div className="w-full max-w-lg rounded-t-2xl bg-white p-5 sm:rounded-2xl" onClick={(e) => e.stopPropagation()}>
            <div className="flex items-center justify-between">
              <h2 className="text-lg font-bold">Book lab tests</h2>
              <button onClick={() => setOpen(false)} className="text-muted hover:text-ink">✕</button>
            </div>

            <div className="mt-3 max-h-32 space-y-1 overflow-y-auto text-sm">
              {ids.map((id) => (
                <div key={id} className="flex justify-between"><span className="text-muted">{selected[id].name}</span><span>{money(num(selected[id].price))}</span></div>
              ))}
            </div>

            <div className="mt-3 border-t border-hair pt-3">
              <div className="mb-2 text-sm font-semibold">Sample collection</div>
              <div className="grid grid-cols-2 gap-2">
                <button onClick={() => setMode('home')} className={`rounded-lg border p-2.5 text-sm ${mode === 'home' ? 'border-brand bg-brand/5' : 'border-hair'}`}>Home collection</button>
                <button onClick={() => setMode('at_lab')} className={`rounded-lg border p-2.5 text-sm ${mode === 'at_lab' ? 'border-brand bg-brand/5' : 'border-hair'}`}>Visit lab</button>
              </div>
            </div>

            {mode === 'home' && (
              <div className="mt-3 grid gap-2">
                {saved.length > 0 && (
                  <select
                    className="input"
                    onChange={(e) => {
                      const a = saved.find((x) => String(x.id) === e.target.value)
                      if (a) setAddr({ line1: a.formatted_address, city: a.city || '' })
                    }}
                  >
                    {saved.map((a) => <option key={a.id} value={a.id}>{a.formatted_address}{a.city ? `, ${a.city}` : ''}</option>)}
                  </select>
                )}
                <input className="input" placeholder="Address" value={addr.line1} onChange={(e) => setAddr({ ...addr, line1: e.target.value })} />
                <input className="input" placeholder="City" value={addr.city} onChange={(e) => setAddr({ ...addr, city: e.target.value })} />
              </div>
            )}

            <div className="mt-3 grid gap-2">
              <label className="text-[12px] font-semibold uppercase tracking-wide text-muted">Preferred date &amp; time (optional)</label>
              <input type="datetime-local" className="input" value={scheduledAt} onChange={(e) => setScheduledAt(e.target.value)} />
              <textarea className="input" rows={2} placeholder="Notes (optional)" value={notes} onChange={(e) => setNotes(e.target.value)} />
            </div>

            <div className="mt-4 flex items-center justify-between border-t border-hair pt-3">
              <span className="text-sm text-muted">Total</span>
              <span className="text-lg font-bold">{money(total)}</span>
            </div>
            {error && <p className="mt-2 text-sm text-rose-600">{error}</p>}
            <button onClick={book} disabled={placing} className="btn btn-primary mt-3 w-full disabled:opacity-60">
              {placing ? 'Placing…' : user ? 'Proceed to payment' : 'Sign in to book'}
            </button>
          </div>
        </div>
      )}
    </div>
  )
}

function chip(active: boolean): string {
  return `rounded-full border px-3 py-1.5 text-[12px] transition ${active ? 'border-brand-strong bg-brand-strong text-white' : 'border-hair bg-white text-ink hover:border-brand'}`
}
