import { useState, type FormEvent } from 'react'
import { Alert } from '@/components/ui/Alert'
import { Button } from '@/components/ui/Button'
import { Modal } from '@/components/ui/Modal'
import { Select } from '@/components/ui/Select'
import { TextArea } from '@/components/ui/TextArea'
import { TextField } from '@/components/ui/TextField'
import { errorMessage } from '@/lib/api'
import {
  conflictSeedLot,
  LOT_UNITS,
  safeExternalUrl,
  useCreateSeedLot,
  useUpdateSeedLot,
  type LotUnit,
  type SeedLot,
} from '@/lib/seedLots'
import type { Plant } from '@/lib/plants'

/**
 * Record a purchase, or correct one. Everything except quantity and unit is
 * optional — the point is to make writing it down cheap enough to bother with,
 * and a form that demands a SKU and a lot code gets skipped.
 */
export function SeedLotModal({
  plant,
  lot,
  onClose,
}: {
  plant: Plant
  /** Editing an existing lot, or undefined to record a new one. */
  lot?: SeedLot
  onClose: () => void
}) {
  const isEdit = !!lot
  const create = useCreateSeedLot()
  const update = useUpdateSeedLot()
  const pending = create.isPending || update.isPending

  // A new lot inherits the plant's vendor and source link, since the usual case
  // is buying the variety you already recorded from the place you recorded it.
  const [vendor, setVendor] = useState(lot?.vendor ?? plant.vendor ?? '')
  const [sourceUrl, setSourceUrl] = useState(lot?.sourceUrl ?? plant.sourceUrl ?? '')
  const [quantity, setQuantity] = useState(lot ? String(lot.quantity) : '')
  const [unit, setUnit] = useState<LotUnit>(lot?.unit ?? 'seeds')
  const [purchasedAt, setPurchasedAt] = useState(lot?.purchasedAt ?? '')
  const [packedForYear, setPackedForYear] = useState(lot?.packedForYear != null ? String(lot.packedForYear) : '')
  const [cost, setCost] = useState(lot?.costCents != null ? (lot.costCents / 100).toFixed(2) : '')
  const [germination, setGermination] = useState(lot?.germinationPct != null ? String(lot.germinationPct) : '')
  const [sku, setSku] = useState(lot?.sku ?? '')
  const [lotCode, setLotCode] = useState(lot?.lotCode ?? '')
  const [notes, setNotes] = useState(lot?.notes ?? '')
  const [version, setVersion] = useState(lot?.version ?? 0)
  const [conflict, setConflict] = useState<string | null>(null)
  const [error, setError] = useState<string | null>(null)

  async function onSubmit(e: FormEvent) {
    e.preventDefault()
    setError(null)
    setConflict(null)

    const qty = quantity.trim() === '' ? 0 : Number(quantity)
    if (!Number.isFinite(qty) || qty < 0) {
      setError('Quantity must be a number, or left blank.')
      return
    }
    if (sourceUrl.trim() && !safeExternalUrl(sourceUrl.trim())) {
      setError('The source link needs to be a full http:// or https:// address.')
      return
    }
    let year: number | null = null
    if (packedForYear.trim()) {
      const y = Number(packedForYear)
      if (!Number.isInteger(y) || y < 1900 || y > 2200) {
        setError('Packed-for year should be a four-digit year.')
        return
      }
      year = y
    }
    let costCents: number | null = null
    if (cost.trim()) {
      const c = Number(cost)
      if (!Number.isFinite(c) || c < 0) {
        setError('Cost must be an amount, or left blank.')
        return
      }
      costCents = Math.round(c * 100)
    }
    let germinationPct: number | null = null
    if (germination.trim()) {
      const g = Number(germination)
      if (!Number.isFinite(g) || g < 0 || g > 100) {
        setError('Germination is a percentage between 0 and 100.')
        return
      }
      germinationPct = g
    }

    const input = {
      plantId: plant.id,
      vendor: vendor.trim(),
      sourceUrl: sourceUrl.trim(),
      sku: sku.trim(),
      lotCode: lotCode.trim(),
      purchasedAt: purchasedAt.trim() === '' ? null : purchasedAt.trim(),
      packedForYear: year,
      quantity: qty,
      unit,
      costCents,
      germinationPct,
      notes: notes.trim(),
    }

    try {
      if (isEdit) {
        await update.mutateAsync({ id: lot.id, version, ...input })
      } else {
        await create.mutateAsync(input)
      }
      onClose()
    } catch (err) {
      const current = conflictSeedLot(err)
      if (current) {
        // Someone edited this lot elsewhere. Rebase onto the fresh row so a
        // re-save applies, rather than making them retype everything — the same
        // contract every other version-guarded form here honours.
        setVersion(current.version)
        setVendor(current.vendor)
        setSourceUrl(current.sourceUrl)
        setQuantity(String(current.quantity))
        setUnit(current.unit)
        setPurchasedAt(current.purchasedAt ?? '')
        setPackedForYear(current.packedForYear != null ? String(current.packedForYear) : '')
        setCost(current.costCents != null ? (current.costCents / 100).toFixed(2) : '')
        setGermination(current.germinationPct != null ? String(current.germinationPct) : '')
        setSku(current.sku)
        setLotCode(current.lotCode)
        setNotes(current.notes)
        setConflict('This lot changed elsewhere. The latest values are shown — review and save again.')
        return
      }
      setError(errorMessage(err, isEdit ? 'Could not save the lot.' : 'Could not record the lot.'))
    }
  }

  return (
    <Modal title={isEdit ? 'Edit seed lot' : `Seed lot — ${plant.name}`} onClose={onClose} busy={pending}>
      <form onSubmit={onSubmit} className="flex flex-col gap-3">
        {conflict && <Alert tone="info">{conflict}</Alert>}

        <div className="grid grid-cols-2 gap-3">
          <TextField
            label="Quantity"
            name="quantity"
            type="number"
            inputMode="decimal"
            step="any"
            min="0"
            value={quantity}
            onChange={(e) => setQuantity(e.target.value)}
          />
          <Select
            label="Unit"
            name="unit"
            value={unit}
            onChange={(e) => setUnit(e.target.value as LotUnit)}
            options={LOT_UNITS.map((u) => ({ value: u.value, label: u.label }))}
          />
        </div>

        <div className="grid grid-cols-2 gap-3">
          <TextField label="Vendor" name="vendor" value={vendor} onChange={(e) => setVendor(e.target.value)} />
          <TextField
            label="Source link"
            name="sourceUrl"
            type="url"
            inputMode="url"
            placeholder="https://…"
            value={sourceUrl}
            onChange={(e) => setSourceUrl(e.target.value)}
          />
        </div>

        <div className="grid grid-cols-2 gap-3">
          <TextField
            label="Purchased"
            name="purchasedAt"
            type="date"
            value={purchasedAt}
            onChange={(e) => setPurchasedAt(e.target.value)}
          />
          <TextField
            label="Packed for"
            name="packedForYear"
            type="number"
            inputMode="numeric"
            placeholder="2026"
            value={packedForYear}
            onChange={(e) => setPackedForYear(e.target.value)}
          />
        </div>

        <div className="grid grid-cols-2 gap-3">
          <TextField
            label="Cost"
            name="cost"
            type="number"
            inputMode="decimal"
            step="0.01"
            min="0"
            placeholder="4.99"
            value={cost}
            onChange={(e) => setCost(e.target.value)}
          />
          <TextField
            label="Germination %"
            name="germination"
            type="number"
            inputMode="decimal"
            step="any"
            min="0"
            max="100"
            value={germination}
            onChange={(e) => setGermination(e.target.value)}
          />
        </div>

        <div className="grid grid-cols-2 gap-3">
          <TextField label="SKU" name="sku" value={sku} onChange={(e) => setSku(e.target.value)} />
          <TextField label="Lot code" name="lotCode" value={lotCode} onChange={(e) => setLotCode(e.target.value)} />
        </div>

        <TextArea label="Notes" name="lotNotes" rows={2} value={notes} onChange={(e) => setNotes(e.target.value)} />

        {error && <Alert>{error}</Alert>}

        <div className="mt-1 flex justify-end gap-2">
          <Button type="button" variant="ghost" onClick={onClose} disabled={pending}>
            Cancel
          </Button>
          <Button type="submit" disabled={pending}>
            {pending ? 'Saving…' : isEdit ? 'Save' : 'Record lot'}
          </Button>
        </div>
      </form>
    </Modal>
  )
}
