'use client'

import { Suspense, use, useEffect, useState } from 'react'
import { trpc } from '@/lib/trpc/client'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Checkbox } from '@/components/ui/checkbox'
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
import { Skeleton } from '@/components/ui/skeleton'
import { Textarea } from '@/components/ui/textarea'
import { Badge } from '@/components/ui/badge'
import { Label } from '@/components/ui/label'
import { AlertCircle, CheckCircle2, Loader2, Salad, UtensilsCrossed } from 'lucide-react'

const ALLERGENS = [
  'GLUTEN', 'CRUSTACEANS', 'EGGS', 'FISH', 'PEANUTS', 'SOYBEANS', 'MILK',
  'TREE_NUTS', 'CELERY', 'MUSTARD', 'SESAME', 'SULPHITES', 'LUPIN', 'MOLLUSCS',
] as const
type Allergen = (typeof ALLERGENS)[number]

interface PageProps {
  params: Promise<{ token: string }>
}

function formatTag(t: string): string {
  return t.replace('_', ' ').toLowerCase()
}

function formatWhen(d: Date): string {
  return new Intl.DateTimeFormat(undefined, {
    dateStyle: 'long',
    timeStyle: 'short',
  }).format(d)
}

function CountdownLabel({ deadline }: { deadline: Date }) {
  const [now, setNow] = useState<number>(Date.now())
  useEffect(() => {
    const id = setInterval(() => setNow(Date.now()), 1000)
    return () => clearInterval(id)
  }, [])
  const ms = deadline.getTime() - now
  if (ms <= 0) return <span className="text-destructive font-medium">closed</span>
  const totalSec = Math.floor(ms / 1000)
  const hours = Math.floor(totalSec / 3600)
  const minutes = Math.floor((totalSec % 3600) / 60)
  const seconds = totalSec % 60
  if (hours >= 24) {
    const days = Math.floor(hours / 24)
    return (
      <span className="font-medium tabular-nums">
        {days}d {hours % 24}h remaining
      </span>
    )
  }
  return (
    <span className="font-medium tabular-nums">
      {hours.toString().padStart(2, '0')}:{minutes.toString().padStart(2, '0')}:
      {seconds.toString().padStart(2, '0')} remaining
    </span>
  )
}

function FriendlyError({ title, message }: { title: string; message: string }) {
  return (
    <Card className="mx-auto max-w-xl">
      <CardHeader>
        <div className="flex items-center gap-2">
          <AlertCircle className="text-muted-foreground h-5 w-5" />
          <CardTitle>{title}</CardTitle>
        </div>
      </CardHeader>
      <CardContent>
        <p className="text-muted-foreground">{message}</p>
      </CardContent>
    </Card>
  )
}

function DishPickContent({ token }: { token: string }) {
  const { data, isLoading, error } = trpc.lunch.getExternalByToken.useQuery(
    { token },
    { retry: false },
  )
  const setPick = trpc.lunch.setExternalPick.useMutation()

  const [dishId, setDishId] = useState<string>('')
  const [allergens, setAllergens] = useState<Allergen[]>([])
  const [allergenOther, setAllergenOther] = useState<string>('')
  const [hydrated, setHydrated] = useState(false)
  const [saved, setSaved] = useState(false)
  const [submitError, setSubmitError] = useState<string | null>(null)

  useEffect(() => {
    if (!hydrated && data) {
      setDishId(data.external.dishId ?? '')
      setAllergens((data.external.allergens as Allergen[]) ?? [])
      setAllergenOther(data.external.allergenOther ?? '')
      setHydrated(true)
    }
  }, [data, hydrated])

  if (isLoading) {
    return (
      <div className="mx-auto max-w-xl space-y-4">
        <Skeleton className="h-8 w-2/3" />
        <Skeleton className="h-32 w-full" />
        <Skeleton className="h-48 w-full" />
      </div>
    )
  }

  if (error) {
    const msg = error.message ?? ''
    if (/expired/i.test(msg)) {
      return (
        <FriendlyError
          title="This link has expired"
          message="Please contact us at info@monaco-opc.com and we'll sort out your lunch."
        />
      )
    }
    if (/signature|malformed|parseable/i.test(msg)) {
      return (
        <FriendlyError
          title="This link is not valid"
          message="Please check your email or contact us at info@monaco-opc.com."
        />
      )
    }
    return (
      <FriendlyError
        title="Something went wrong"
        message={msg || 'Please try again or contact us at info@monaco-opc.com.'}
      />
    )
  }
  if (!data) {
    return (
      <FriendlyError
        title="Not found"
        message="Please check your email link or contact us at info@monaco-opc.com."
      />
    )
  }

  const deadline = data.changeDeadline ? new Date(data.changeDeadline) : null
  const deadlinePassed = deadline ? new Date() > deadline : false
  const eventAt = data.event.eventAt ? new Date(data.event.eventAt) : null

  const handleSave = async () => {
    setSubmitError(null)
    try {
      await setPick.mutateAsync({
        token,
        dishId: dishId || null,
        allergens,
        allergenOther: allergenOther.trim() || null,
      })
      setSaved(true)
    } catch (err) {
      setSubmitError(err instanceof Error ? err.message : 'Failed to save')
    }
  }

  const eventCard = (
    <Card className="border-primary/40 bg-primary/5">
      <CardHeader>
        <div className="flex items-center gap-2">
          <UtensilsCrossed className="text-primary h-5 w-5" />
          <CardTitle>
            {data.event.venue ? `Lunch at ${data.event.venue}` : 'Lunch'}
          </CardTitle>
        </div>
      </CardHeader>
      <CardContent className="space-y-1 text-sm">
        <p>
          Hi <strong>{data.external.name}</strong>, please choose your dish below.
        </p>
        {eventAt && (
          <p className="text-muted-foreground">
            <strong>When:</strong> {formatWhen(eventAt)}
          </p>
        )}
        {data.event.notes && (
          <p className="text-muted-foreground">{data.event.notes}</p>
        )}
        {deadline && !deadlinePassed && (
          <p className="text-muted-foreground pt-1">
            Choose by {formatWhen(deadline)} · <CountdownLabel deadline={deadline} />
          </p>
        )}
      </CardContent>
    </Card>
  )

  // Past the change deadline → read-only.
  if (deadlinePassed) {
    const chosen = data.dishes.find((d) => d.id === data.external.dishId)
    return (
      <div className="mx-auto max-w-xl space-y-6">
        {eventCard}
        <FriendlyError
          title="Dish selection is now closed"
          message={
            chosen
              ? `Your choice is "${chosen.name}". To change it, please contact us at info@monaco-opc.com.`
              : 'The deadline to choose a dish has passed. Please contact us at info@monaco-opc.com.'
          }
        />
      </div>
    )
  }

  return (
    <div className="mx-auto max-w-xl space-y-6">
      {eventCard}

      <Card>
        <CardHeader>
          <CardTitle className="flex items-center gap-2 text-base">
            <Salad className="h-4 w-4 text-emerald-600" /> Your dish
          </CardTitle>
        </CardHeader>
        <CardContent className="space-y-6">
          <RadioGroup value={dishId} onValueChange={setDishId} className="gap-2">
            {data.dishes.map((d) => (
              <label
                key={d.id}
                htmlFor={`dish-${d.id}`}
                className="hover:bg-muted/50 flex cursor-pointer items-start gap-3 rounded-md border p-3"
              >
                <RadioGroupItem id={`dish-${d.id}`} value={d.id} className="mt-0.5" />
                <div>
                  <div className="font-medium">{d.name}</div>
                  {d.dietaryTags.length > 0 && (
                    <div className="mt-1 flex flex-wrap gap-1">
                      {d.dietaryTags.map((t) => (
                        <Badge key={t} variant="secondary" className="text-xs">
                          {formatTag(t)}
                        </Badge>
                      ))}
                    </div>
                  )}
                </div>
              </label>
            ))}
            {data.dishes.length === 0 && (
              <p className="text-muted-foreground text-sm">
                No dishes have been published yet. Please check back later.
              </p>
            )}
          </RadioGroup>

          <div>
            <Label className="text-sm">Allergens</Label>
            <div className="mt-2 grid grid-cols-2 gap-2 sm:grid-cols-3">
              {ALLERGENS.map((a) => (
                <label key={a} className="flex items-center gap-2 text-sm">
                  <Checkbox
                    checked={allergens.includes(a)}
                    onCheckedChange={(v) =>
                      setAllergens(
                        v ? [...allergens, a] : allergens.filter((x) => x !== a),
                      )
                    }
                  />
                  {formatTag(a)}
                </label>
              ))}
            </div>
          </div>

          <div>
            <Label className="text-sm">Other allergens / dietary notes</Label>
            <Textarea
              value={allergenOther}
              onChange={(e) => {
                setAllergenOther(e.target.value)
                setSaved(false)
              }}
              rows={2}
              className="mt-1"
              placeholder="e.g. severe nut allergy, no shellfish"
            />
          </div>
        </CardContent>
      </Card>

      {submitError && (
        <div className="border-destructive bg-destructive/10 text-destructive rounded-md border p-3 text-sm">
          {submitError}
        </div>
      )}

      <div className="flex items-center justify-between gap-4">
        {saved && !setPick.isPending ? (
          <span className="flex items-center gap-2 text-sm text-emerald-600">
            <CheckCircle2 className="h-4 w-4" /> Saved — you can change it until the deadline.
          </span>
        ) : (
          <span />
        )}
        <Button size="lg" onClick={handleSave} disabled={setPick.isPending}>
          {setPick.isPending ? (
            <>
              <Loader2 className="mr-2 h-4 w-4 animate-spin" /> Saving…
            </>
          ) : (
            <>
              <CheckCircle2 className="mr-2 h-4 w-4" /> Save my choice
            </>
          )}
        </Button>
      </div>
    </div>
  )
}

export default function LunchPickPage({ params }: PageProps) {
  const { token } = use(params)
  return (
    <Suspense fallback={<Skeleton className="h-64 w-full" />}>
      <DishPickContent token={token} />
    </Suspense>
  )
}
