'use client'

import { useActionState, useState } from 'react'
import { toast } from 'sonner'
import { createCarrierTrip } from '@/app/trips/new/actions'
import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { ContactPicker } from '@/components/app/contact-picker'
import type { CarrierContact } from '@/types/db'
import { Alert, AlertDescription } from '@/components/ui/alert'

/**
 * Carrier "Create Trip" — 2-step wizard (Task 17).
 * Step 1: rate con drag-drop → extraction → EDITABLE fields + unit number +
 *         permits (upload own, or order from our trusted partner Synchron).
 * Step 2: invite drivers and/or brokers (multiple); existing users auto-attach
 *         by email — new people get accounts + a welcome email (backend later).
 */

interface Invite {
  role: 'driver' | 'broker'
  name: string
  email: string
  phone: string
  phone_ext: string
}

export function CarrierWizard({
  contacts = { drivers: [], brokers: [] },
}: {
  /** The dispatcher's saved people, so step 2 is a pick not a retype (Task 99). */
  contacts?: { drivers: CarrierContact[]; brokers: CarrierContact[] }
} = {}) {
  const [state, action, pending] = useActionState(createCarrierTrip, undefined)
  const [step, setStep] = useState<1 | 2>(1)
  const [rateCon, setRateCon] = useState<File | null>(null)
  const [permitFiles, setPermitFiles] = useState<File[]>([])
  const [permitPath, setPermitPath] = useState<'upload' | 'synchron'>('upload')
  const [extracting, setExtracting] = useState(false)
  const [extracted, setExtracted] = useState(false)
  const [fields, setFields] = useState({
    origin: '',
    destination: '',
    commodity: '',
    unit_number: '',
    pickup_date: '',
    delivery_date: '',
  })
  const [invites, setInvites] = useState<Invite[]>([])
  const [draft, setDraft] = useState<Invite>({ role: 'driver', name: '', email: '', phone: '', phone_ext: '' })
  const [dragOver, setDragOver] = useState(false)
  // Permits get their own drag state so the two drop zones highlight
  // independently (Task 100).
  const [permitsDragOver, setPermitsDragOver] = useState(false)

  /** Append dropped/chosen permits, skipping ones already added. */
  function addPermitFiles(files: FileList | File[] | null) {
    const incoming = [...(files ?? [])]
    if (incoming.length === 0) return
    setPermitFiles((current) => {
      const seen = new Set(current.map((f) => `${f.name}:${f.size}`))
      return [...current, ...incoming.filter((f) => !seen.has(`${f.name}:${f.size}`))]
    })
  }

  const set = (k: keyof typeof fields) => (e: React.ChangeEvent<HTMLInputElement>) =>
    setFields((f) => ({ ...f, [k]: e.target.value }))

  /** Drag & drop, boom — extraction fills the fields; the user corrects gaps. */
  async function onRateCon(file: File) {
    setRateCon(file)
    setExtracting(true)
    try {
      const fd = new FormData()
      fd.set('file', file)
      const res = await fetch('/api/extract/rate-con', { method: 'POST', body: fd })
      const json = await res.json()
      if (json.ok && json.data) {
        setFields((f) => ({
          ...f,
          origin: json.data.origin ?? f.origin,
          destination: json.data.destination ?? f.destination,
          commodity: json.data.commodity ?? f.commodity,
          pickup_date: json.data.pickup_date ?? f.pickup_date,
          delivery_date: json.data.delivery_date ?? f.delivery_date,
        }))
        toast.success('Rate con read — check the fields and fix anything that looks wrong')
      } else if (json.configured === false) {
        toast.info('The extractor connects soon — fill the fields below for now.')
      } else {
        toast.info('Could not read the rate con — fill the fields below.')
      }
      setExtracted(true)
    } finally {
      setExtracting(false)
    }
  }

  function addInvite() {
    if (!draft.name.trim() || !/.+@.+\..+/.test(draft.email)) {
      toast.error('Invitee needs a full name and a valid email.')
      return
    }
    // Nash: the phone number is required (it finds existing users).
    if (draft.phone.trim().length < 5) {
      toast.error('Invitee needs a phone number.')
      return
    }
    setInvites((list) => [...list, { ...draft, email: draft.email.trim().toLowerCase() }])
    setDraft({ role: 'driver', name: '', email: '', phone: '', phone_ext: '' })
  }

  function submit(fd: FormData) {
    if (!rateCon) {
      toast.error('The rate confirmation is required.')
      return
    }
    fd.set('rate_confirmation', rateCon)
    for (const f of permitFiles) fd.append('permits', f)
    fd.set('permit_path', permitPath)
    fd.set('origin', fields.origin)
    fd.set('destination', fields.destination)
    fd.set('commodity', fields.commodity)
    fd.set('unit_number', fields.unit_number)
    fd.set('pickup_date', fields.pickup_date)
    fd.set('delivery_date', fields.delivery_date)
    fd.set('invites', JSON.stringify(invites))
    action(fd)
  }

  const step1Ready = rateCon && fields.origin && fields.destination && fields.commodity

  return (
    <form action={submit} className="mt-6 space-y-5">
      {state?.error && (
        <Alert variant="destructive">
          <AlertDescription>{state.error}</AlertDescription>
        </Alert>
      )}

      {/* Progress */}
      <div className="flex items-center gap-2 text-xs font-bold">
        <span className={`rounded-full px-3 py-1 ${step === 1 ? 'bg-[#0f1b2d] text-white' : 'bg-green-100 text-green-700'}`}>
          1 · Trip info
        </span>
        <span className="text-neutral-300">→</span>
        <span className={`rounded-full px-3 py-1 ${step === 2 ? 'bg-[#0f1b2d] text-white' : 'bg-neutral-100 text-neutral-500'}`}>
          2 · People
        </span>
      </div>

      {step === 1 && (
        <>
          {/* Rate con first — "drag and drop, boom" */}
          <Card>
            <CardContent className="pt-6">
              <Label>
                Rate confirmation <span className="text-red-600">*</span>
              </Label>
              <label
                onDragOver={(e) => {
                  e.preventDefault()
                  setDragOver(true)
                }}
                onDragLeave={() => setDragOver(false)}
                onDrop={(e) => {
                  e.preventDefault()
                  setDragOver(false)
                  const f = e.dataTransfer.files?.[0]
                  if (f) onRateCon(f)
                }}
                className={`mt-2 block cursor-pointer rounded-xl border-2 border-dashed p-8 text-center text-sm transition ${
                  dragOver
                    ? 'border-[#f5a623] bg-amber-50'
                    : rateCon
                      ? 'border-green-300 bg-green-50/50'
                      : 'border-neutral-300 hover:border-neutral-400'
                }`}
              >
                {extracting ? (
                  <span className="font-semibold text-neutral-500">Reading the rate con…</span>
                ) : rateCon ? (
                  <span className="font-semibold text-green-700">✓ {rateCon.name}</span>
                ) : (
                  <>
                    <span className="font-semibold">Drag &amp; drop the rate con here</span>
                    <span className="mt-1 block text-xs text-neutral-500">
                      or click to choose · we read it and fill the trip for you
                    </span>
                  </>
                )}
                <input
                  type="file"
                  className="hidden"
                  accept=".pdf,.jpg,.jpeg,.png,.docx"
                  onChange={(e) => e.target.files?.[0] && onRateCon(e.target.files[0])}
                />
              </label>
            </CardContent>
          </Card>

          {/* Extracted output — editable */}
          {(extracted || rateCon) && (
            <Card>
              <CardContent className="grid gap-4 pt-6 sm:grid-cols-2">
                <p className="text-xs text-neutral-500 sm:col-span-2">
                  Extracted from the rate con — edit anything that looks wrong.
                </p>
                <div className="space-y-2">
                  <Label>
                    Origin <span className="text-red-600">*</span>
                  </Label>
                  <Input value={fields.origin} onChange={set('origin')} placeholder="Tacoma, WA" />
                </div>
                <div className="space-y-2">
                  <Label>
                    Destination <span className="text-red-600">*</span>
                  </Label>
                  <Input value={fields.destination} onChange={set('destination')} placeholder="Macon, GA" />
                </div>
                <div className="space-y-2">
                  <Label>
                    Commodity <span className="text-red-600">*</span>
                  </Label>
                  <Input value={fields.commodity} onChange={set('commodity')} placeholder="Industrial material handler" />
                </div>
                <div className="space-y-2">
                  <Label>Truck / unit number</Label>
                  <Input value={fields.unit_number} onChange={set('unit_number')} placeholder="455" />
                </div>
                <div className="space-y-2">
                  <Label>Pickup date</Label>
                  <Input type="date" value={fields.pickup_date} onChange={set('pickup_date')} />
                </div>
                <div className="space-y-2">
                  <Label>Delivery date</Label>
                  <Input type="date" value={fields.delivery_date} onChange={set('delivery_date')} />
                </div>
              </CardContent>
            </Card>
          )}

          {/* Permits: upload own, or order from the trusted partner */}
          <Card>
            <CardContent className="pt-6">
              <Label>Permits</Label>
              <div className="mt-3 grid gap-3 sm:grid-cols-2">
                <button
                  type="button"
                  onClick={() => setPermitPath('upload')}
                  className={`rounded-xl border-2 p-4 text-left transition ${
                    permitPath === 'upload' ? 'border-[#0f1b2d] bg-[#0f1b2d] text-white' : 'hover:border-neutral-400'
                  }`}
                >
                  <p className="text-sm font-bold">I have my own permits</p>
                  <p className={`mt-1 text-xs ${permitPath === 'upload' ? 'text-neutral-300' : 'text-neutral-500'}`}>
                    Drag and drop permits from any provider
                  </p>
                </button>
                <button
                  type="button"
                  onClick={() => setPermitPath('synchron')}
                  className={`rounded-xl border-2 p-4 text-left transition ${
                    permitPath === 'synchron' ? 'border-[#0f1b2d] bg-[#0f1b2d] text-white' : 'hover:border-neutral-400'
                  }`}
                >
                  <p className="text-sm font-bold">Order from our trusted partner Synchron Permits</p>
                  <p className={`mt-1 text-xs ${permitPath === 'synchron' ? 'text-neutral-300' : 'text-neutral-500'}`}>
                    The order goes straight to the Synchron team
                  </p>
                </button>
              </div>
              {permitPath === 'upload' && (
                <div className="mt-3 space-y-2">
                  {/* Nash, 2026-09-09: "when I choose 'I have my own permits' —
                      I don't have a big drag and drop where I can upload
                      multiple files. We need to add that, for sure." A carrier
                      arrives with a folder of permits, one per state (eleven on
                      the D&D trip), so this is the same size and behaviour as
                      the rate-con zone above. */}
                  <label
                    onDragOver={(e) => {
                      e.preventDefault()
                      setPermitsDragOver(true)
                    }}
                    onDragLeave={() => setPermitsDragOver(false)}
                    onDrop={(e) => {
                      e.preventDefault()
                      setPermitsDragOver(false)
                      addPermitFiles(e.dataTransfer.files)
                    }}
                    className={`block cursor-pointer rounded-xl border-2 border-dashed p-8 text-center text-sm transition ${
                      permitsDragOver
                        ? 'border-[#f5a623] bg-amber-50'
                        : permitFiles.length > 0
                          ? 'border-green-300 bg-green-50/50'
                          : 'border-neutral-300 hover:border-neutral-400'
                    }`}
                  >
                    {permitFiles.length > 0 ? (
                      <span className="font-semibold text-green-700">
                        ✓ {permitFiles.length} permit{permitFiles.length === 1 ? '' : 's'} ready — drop more
                        or click to add
                      </span>
                    ) : (
                      <>
                        <span className="font-semibold">Drag &amp; drop your permits here</span>
                        <span className="mt-1 block text-xs text-neutral-500">
                          or click to choose · several files at once is fine
                        </span>
                      </>
                    )}
                    <input
                      type="file"
                      multiple
                      className="hidden"
                      accept=".pdf,.jpg,.jpeg,.png,.docx"
                      onChange={(e) => {
                        addPermitFiles(e.target.files)
                        e.target.value = ''
                      }}
                    />
                  </label>
                  {/* With eleven permits the dispatcher needs to see that all
                      eleven arrived, and drop the one picked by mistake. */}
                  {permitFiles.length > 0 && (
                    <ul className="space-y-1">
                      {permitFiles.map((f, i) => (
                        <li
                          key={`${f.name}-${f.size}-${i}`}
                          className="flex items-center justify-between gap-2 rounded-lg border bg-white px-3 py-1.5 text-xs"
                        >
                          <span className="min-w-0 truncate">{f.name}</span>
                          <button
                            type="button"
                            onClick={() => setPermitFiles((list) => list.filter((_, j) => j !== i))}
                            className="shrink-0 text-neutral-400 transition hover:text-red-600"
                            title={`Remove ${f.name}`}
                          >
                            ✕
                          </button>
                        </li>
                      ))}
                    </ul>
                  )}
                  <p className="text-[11px] text-neutral-400">One file per state is typical — you can add more later.</p>
                </div>
              )}
            </CardContent>
          </Card>

          <Button
            type="button"
            className="w-full"
            disabled={!step1Ready}
            onClick={() => setStep(2)}
          >
            Next: invite people →
          </Button>
        </>
      )}

      {step === 2 && (
        <>
          <Card>
            <CardContent className="pt-6">
              <Label>Invite drivers and brokers</Label>
              <p className="mt-1 text-xs text-neutral-500">
                Existing users attach automatically by email; new people get an account and a
                welcome email with a password-reset link.
              </p>
              {/* Nash: "I should have a way to choose from the previous
                  contacts." Renders nothing when none are saved. */}
              <ContactPicker
                drivers={contacts.drivers}
                brokers={contacts.brokers}
                alreadyAdded={invites.map((i) => i.email)}
                onPick={(c) => setDraft({ ...c, role: c.role === 'dispatcher' ? 'driver' : c.role })}
                className="mt-3"
              />
              <div className="mt-3 flex flex-wrap items-end gap-2">
                <select
                  value={draft.role}
                  onChange={(e) => setDraft((d) => ({ ...d, role: e.target.value as Invite['role'] }))}
                  className="rounded-lg border px-2 py-2 text-sm"
                >
                  <option value="driver">Driver</option>
                  <option value="broker">Broker</option>
                </select>
                <Input
                  placeholder="Full name"
                  value={draft.name}
                  onChange={(e) => setDraft((d) => ({ ...d, name: e.target.value }))}
                  className="w-40"
                />
                <Input
                  placeholder="Email"
                  type="email"
                  value={draft.email}
                  onChange={(e) => setDraft((d) => ({ ...d, email: e.target.value }))}
                  className="w-52"
                />
                <Input
                  placeholder="Phone *"
                  value={draft.phone}
                  onChange={(e) => setDraft((d) => ({ ...d, phone: e.target.value }))}
                  className="w-36"
                />
                <Input
                  placeholder="Ext."
                  title="Extension (optional)"
                  value={draft.phone_ext}
                  onChange={(e) => setDraft((d) => ({ ...d, phone_ext: e.target.value }))}
                  className="w-20"
                />
                <Button type="button" variant="outline" onClick={addInvite}>
                  + Add
                </Button>
              </div>
              {invites.length > 0 && (
                <ul className="mt-4 space-y-1.5">
                  {invites.map((inv, i) => (
                    <li
                      key={`${inv.email}-${i}`}
                      className="flex items-center justify-between rounded-lg bg-neutral-50 px-3 py-2 text-sm"
                    >
                      <span>
                        <span className="font-semibold">{inv.name}</span>
                        <span className="ml-1.5 text-xs capitalize text-neutral-500">
                          {inv.role} · {inv.email}
                          {inv.phone ? ` · ${inv.phone}${inv.phone_ext ? ` x${inv.phone_ext}` : ''}` : ''}
                        </span>
                      </span>
                      <button
                        type="button"
                        onClick={() => setInvites((list) => list.filter((_, j) => j !== i))}
                        className="text-xs font-bold text-neutral-400 hover:text-red-600"
                      >
                        Remove
                      </button>
                    </li>
                  ))}
                </ul>
              )}
              {invites.length === 0 && (
                <p className="mt-4 rounded-lg border border-dashed p-4 text-center text-xs text-neutral-500">
                  No one added yet — you can also invite people later from the trip&apos;s People tab.
                </p>
              )}
            </CardContent>
          </Card>

          <div className="flex gap-3">
            <Button type="button" variant="outline" onClick={() => setStep(1)} className="flex-1">
              ← Back
            </Button>
            <Button type="submit" className="flex-1" disabled={pending}>
              {pending ? 'Creating trip…' : 'Create trip'}
            </Button>
          </div>
        </>
      )}
    </form>
  )
}
