'use client'

import { useState } from 'react'
import type { CarrierContact, ContactRole } from '@/types/db'
import { filterInviteContacts, inviteContactGroups, type InviteContact, type InviteContactRole } from '@/lib/domain/contacts'

/**
 * Pick a saved driver or broker instead of retyping them (Task 99, 2026-09-09).
 *
 * Nash: "when I go to create a trip, I have to invite drivers, and I have to
 * do it every time — put the name and the email and the phone number and the
 * extension. Can I have an ability to choose any of my existing drivers?
 * Maybe there is brokers that I worked with before, and drivers that I worked
 * with before should be displayed in there."
 *
 * The one firm rule he gave: "We do have to keep them distinguished —
 * separate drivers and brokers — when I go to choose." So the two groups are
 * never mixed into one list; picking a broker where a driver belongs would put
 * the wrong person in a role on a live load.
 *
 * Picking fills the existing draft fields and leaves them editable — the
 * caller's own validated "Add" path still does the adding, so there is no
 * second code path that can drift from it.
 */

export interface PickedContact {
  role: ContactRole | 'pilot'
  name: string
  email: string
  phone: string
  phone_ext: string
}

const ROLE_LABELS: Record<InviteContactRole, string> = {
  driver: 'Drivers',
  broker: 'Brokers',
  dispatcher: 'Dispatchers',
  pilot: 'Pilots',
}

/**
 * Generic mode (Nash, 2026-09-18): everyone this person may invite from —
 * saved contacts AND everyone they shared a trip with — grouped by every
 * role the inviter is allowed to invite. Used by the trip workspace's People
 * tab. The older driver/broker and dispatcher-only props still serve the
 * carrier wizard and the broker request form unchanged.
 */
export function ContactPicker({
  drivers = [],
  brokers = [],
  dispatchers,
  contacts,
  roles = [],
  onPick,
  alreadyAdded = [],
  className = '',
}: {
  drivers?: CarrierContact[]
  brokers?: CarrierContact[]
  /** A freight broker's saved carrier dispatchers (2026-09-13). When given, this is the only group shown. */
  dispatchers?: CarrierContact[]
  /** Generic mode: the merged contact list; groups follow `roles`. */
  contacts?: InviteContact[]
  /** Generic mode: the roles this inviter may invite, in display order. */
  roles?: readonly string[]
  onPick: (c: PickedContact) => void
  /** Emails already on this trip — shown as added rather than offered twice. */
  alreadyAdded?: string[]
  className?: string
}) {
  const generic = contacts !== undefined
  const groups = generic ? inviteContactGroups(contacts, roles) : []
  const [query, setQuery] = useState('')
  const [group, setGroup] = useState<string>(generic ? (groups.find((g) => g.contacts.length > 0)?.role ?? groups[0]?.role ?? 'driver') : dispatchers ? 'dispatcher' : 'driver')
  // Nothing saved yet: render nothing at all, so a dispatcher with no contacts
  // sees exactly the form they see today.
  if (generic ? groups.every((g) => g.contacts.length === 0) : dispatchers ? dispatchers.length === 0 : drivers.length === 0 && brokers.length === 0) return null

  const taken = new Set(alreadyAdded.map((e) => e.trim().toLowerCase()))
  type Row = { id: string; name: string; email: string; phone: string | null; phone_ext: string | null; role: ContactRole | 'pilot'; source?: 'saved' | 'trip'; company?: string | null; last_trip_ref?: string | null }
  const groupList: Row[] = generic
    ? (groups.find((g) => g.role === group)?.contacts ?? [])
    : dispatchers
      ? dispatchers
      : group === 'driver'
        ? drivers
        : brokers
  // Search as you type (Nash, 2026-09-18): 400 drivers is a list to search,
  // not to scroll. Every word must match name, email, company, phone or the
  // last trip shared. Long lists are capped; the count says what is hidden.
  const list = filterInviteContacts(groupList, query)
  const SHOW = 25
  const shown = list.slice(0, SHOW)
  const countFor = (rows: Row[]) => (query.trim() ? `${filterInviteContacts(rows, query).length}/${rows.length}` : String(rows.length))

  return (
    <div className={`rounded-xl border border-line bg-paper p-3 ${className}`}>
      <div className="flex flex-wrap items-center justify-between gap-2">
        <p className="text-[11px] font-bold uppercase tracking-wide text-slate-body/70">
          Choose from your contacts
        </p>
        {/* Drivers and brokers stay separate — Nash's explicit rule. */}
        {generic ? (
          <div className="flex flex-wrap gap-1 rounded-lg bg-white p-0.5 ring-1 ring-line">
            {groups.map((g) => (
              <button
                key={g.role}
                type="button"
                onClick={() => setGroup(g.role)}
                className={`rounded-md px-2.5 py-1 text-[11px] font-bold transition ${
                  group === g.role ? 'bg-navy-900 text-white' : 'text-slate-body hover:text-ink'
                }`}
              >
                {ROLE_LABELS[g.role]} ({countFor(g.contacts)})
              </button>
            ))}
          </div>
        ) : dispatchers ? (
          <span className="rounded-md bg-white px-2.5 py-1 text-[11px] font-bold text-slate-body ring-1 ring-line">Dispatchers ({dispatchers.length})</span>
        ) : (
        <div className="flex gap-1 rounded-lg bg-white p-0.5 ring-1 ring-line">
          {(
            [
              ['driver', `Drivers (${countFor(drivers)})`],
              ['broker', `Brokers (${countFor(brokers)})`],
            ] as const
          ).map(([key, label]) => (
            <button
              key={key}
              type="button"
              onClick={() => setGroup(key)}
              className={`rounded-md px-2.5 py-1 text-[11px] font-bold transition ${
                group === key ? 'bg-navy-900 text-white' : 'text-slate-body hover:text-ink'
              }`}
            >
              {label}
            </button>
          ))}
        </div>
        )}
      </div>

      <input
        type="search"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder={`Search ${groupList.length} by name, email, company or phone…`}
        aria-label="Search contacts"
        className="mt-2 w-full rounded-lg border border-line bg-white px-3 py-1.5 text-xs"
      />

      {list.length === 0 ? (
        <p className="mt-2 text-xs text-slate-body">
          {query.trim()
            ? `No match for “${query.trim()}” here.`
            : generic
              ? `No ${ROLE_LABELS[group as InviteContactRole]?.toLowerCase() ?? group + 's'} you have worked with yet.`
              : `No saved ${group === 'driver' ? 'drivers' : group === 'broker' ? 'brokers' : 'dispatchers'} yet.`}
        </p>
      ) : (
        <ul className="mt-2 max-h-64 divide-y overflow-y-auto rounded-lg border border-line bg-white">
          {shown.map((c) => {
            const added = taken.has(c.email.toLowerCase())
            // Two people with the same name are told apart by company, email
            // and phone — shown on every row, not only on hover.
            const detail = [c.company, c.email, c.phone ? `${c.phone}${c.phone_ext ? ` ext. ${c.phone_ext}` : ''}` : null].filter(Boolean).join(' · ')
            return (
              <li key={c.id}>
                <button
                  type="button"
                  disabled={added}
                  onClick={() =>
                    onPick({
                      role: c.role,
                      name: c.name,
                      email: c.email,
                      phone: c.phone ?? '',
                      phone_ext: c.phone_ext ?? '',
                    })
                  }
                  title={added ? `${c.name} is already on this trip` : `Fill the form with ${c.name}`}
                  className={`flex w-full items-start justify-between gap-3 px-3 py-2 text-left text-xs transition ${
                    added ? 'cursor-not-allowed text-slate-body/40' : 'hover:bg-paper'
                  }`}
                >
                  <span className="min-w-0">
                    <span className="block truncate font-semibold">
                      {c.name}
                      {added ? ' ✓ on this trip' : ''}
                    </span>
                    <span className="block truncate text-slate-body">{detail || '—'}</span>
                  </span>
                  {c.last_trip_ref && (
                    <span className="shrink-0 font-mono text-[10px] text-slate-body/70" title="Last trip you shared">{c.last_trip_ref}</span>
                  )}
                </button>
              </li>
            )
          })}
          {list.length > SHOW && (
            <li className="px-3 py-2 text-[11px] text-slate-body">
              {list.length - SHOW} more — keep typing to narrow it down.
            </li>
          )}
        </ul>
      )}
      <p className="mt-2 text-[10px] text-slate-body/60">
        Picking someone fills the fields below — you can still edit them before adding.
      </p>
    </div>
  )
}
