import { useMemo, useState } from 'react'
import { m, mKey } from '@/i18n/messages'
import { useLocale } from '@/i18n/config'
import { asI18n, type I18nString } from '@pikku/react'
import {
  ActionIcon,
  Badge,
  Box,
  Button,
  Group,
  Paper,
  Select,
  Stack,
  Text,
  TextInput,
  Tooltip,
} from '@pikku/mantine/core'

type SeverityKey = 'mild' | 'moderate' | 'severe' | 'standard'

type Allergy = {
  allergen: string
  severity: string
  note?: string | null
}

type Participant = {
  participantId: string
  name: string
  kind: string
  dietaryTag: string | null
  roomId: string | null
  roomNumber: number | null
  allergies: Allergy[]
}

type DietaryTag =
  | 'omnivore'
  | 'vegetarian'
  | 'vegan'
  | 'gluten_free'
  | 'lactose_free'
  | 'pescatarian'
  | 'unknown'
type Kind = 'overnight' | 'day_guest'

const initials = (name: string) =>
  name
    .split(/\s+/)
    .filter(Boolean)
    .slice(0, 2)
    .map((p) => p[0]?.toUpperCase() ?? '')
    .join('')

const TINTS = [
  '#88557F',
  '#A05C8E',
  '#BC7AA6',
  '#D3A7C4',
  '#FFBC7D',
  '#F37E15',
  '#FFCE00',
  '#806600',
  '#4E3149',
  '#583651',
]
const tintFor = (id: string) => {
  let h = 0
  for (let i = 0; i < id.length; i++) h = (h * 31 + id.charCodeAt(i)) | 0
  return TINTS[Math.abs(h) % TINTS.length]
}

const SEVERITY_STYLE: Record<
  SeverityKey,
  { bg: string; border: string; fg: string }
> = {
  mild: { bg: '#F1EEF0', border: '#D9D2D7', fg: '#5A4F56' },
  moderate: { bg: '#FFE7CF', border: '#FFBC7D', fg: '#7A4A18' },
  severe: { bg: '#4E3149', border: '#4E3149', fg: '#FFFFFF' },
  standard: { bg: '#F5EAF1', border: '#E0CCD9', fg: '#4E3149' },
}

const severityKey = (s: string): SeverityKey =>
  s === 'mild' || s === 'moderate' || s === 'severe' || s === 'standard'
    ? s
    : 'standard'

const DIETARY_VALUES: DietaryTag[] = [
  'omnivore',
  'vegetarian',
  'vegan',
  'gluten_free',
  'lactose_free',
  'pescatarian',
  'unknown',
]

export function ParticipantsTab({
  participants,
  bookingId,
  addParticipant,
  updateParticipant,
  removeParticipant,
  addAllergy,
  removeAllergy,
  isAddingParticipant,
}: {
  participants: Participant[]
  bookingId: string
  addParticipant: (args: {
    bookingId: string
    name: string
    kind: Kind
    email: null
    age: null
    notes: null
  }, opts?: { onSuccess?: () => void }) => void
  updateParticipant: (args: {
    participantId: string
    dietaryTag: DietaryTag | null
  }) => void
  removeParticipant: (args: { participantId: string }) => void
  addAllergy: (
    args: {
      participantId: string
      allergen: string
      severity: 'standard' | 'separate_prep' | 'severe'
    },
    opts?: { onSuccess?: () => void },
  ) => void
  removeAllergy: (args: { participantId: string; allergen: string }) => void
  isAddingParticipant: boolean
}) {
  useLocale()
  const [newName, setNewName] = useState('')
  const [newKind, setNewKind] = useState<Kind>('overnight')
  const [newAllergyByPid, setNewAllergyByPid] = useState<Record<string, string>>({})
  const [allergyOpenByPid, setAllergyOpenByPid] = useState<Record<string, boolean>>({})

  const groups = useMemo(() => {
    const overnight = participants.filter((p) => p.kind === 'overnight')
    const day = participants.filter((p) => p.kind === 'day_guest')
    return [
      { kind: 'overnight' as const, items: overnight },
      { kind: 'day_guest' as const, items: day },
    ].filter((g) => g.items.length > 0)
  }, [participants])

  const dietaryOptions = DIETARY_VALUES.map((v) => ({
    value: v,
    label: mKey(`common.pages.booking.participants.dietary.${v}` as any),
  }))

  const submitAdd = () => {
    const name = newName.trim()
    if (!name) return
    addParticipant(
      { bookingId, name, kind: newKind, email: null, age: null, notes: null },
      {
        onSuccess: () => {
          setNewName('')
          setNewKind('overnight')
        },
      },
    )
  }

  return (
    <Stack gap="md">
      {/* Inline compact add-participant bar -------------------------------- */}
      <Paper
        withBorder
        radius="md"
        p="sm"
        data-testid="add-participant-form"
        style={{ background: '#FBF8FA', borderColor: '#E5DDE3' }}
      >
        <Group gap="sm" wrap="nowrap" align="center">
          <Text
            size="xs"
            tt="uppercase"
            fw={600}
            c="dimmed"
            style={{ letterSpacing: '0.08em', whiteSpace: 'nowrap' }}
          >
            {m.common_pages_booking_participants_add_modal_title()}
          </Text>
          <TextInput
            size="sm"
            data-testid="new-participant-name"
            placeholder={m.common_pages_booking_participants_add_modal_name()}
            value={newName}
            onChange={(e) => setNewName(e.currentTarget.value)}
            onKeyDown={(e) => {
              if (e.key === 'Enter') submitAdd()
            }}
            style={{ flex: 1, minWidth: 160 }}
            aria-label={m.common_pages_booking_participants_add_modal_name()}
          />
          <Select
            size="sm"
            data-testid="new-participant-kind"
            value={newKind}
            onChange={(v) => setNewKind(((v as Kind) ?? 'overnight'))}
            data={[
              {
                value: 'overnight',
                label: m.common_pages_booking_participants_kinds_overnight(),
              },
              {
                value: 'day_guest',
                label: m.common_pages_booking_participants_kinds_day_guest(),
              },
            ]}
            allowDeselect={false}
            style={{ width: 160 }}
            aria-label={m.common_pages_booking_participants_add_modal_kind()}
          />
          <Button
            size="sm"
            data-testid="add-participant-submit"
            disabled={!newName.trim() || isAddingParticipant}
            loading={isAddingParticipant}
            onClick={submitAdd}
            color="plum"
          >
            {m.common_pages_booking_participants_add_modal_add()}
          </Button>
        </Group>
      </Paper>

      {participants.length === 0 ? (
        <Text size="sm" c="dimmed" ta="center">
          {m.common_pages_booking_participants_empty()}
        </Text>
      ) : (
        <Stack gap="lg">
          {groups.map((g) => (
            <Stack key={g.kind} gap="xs">
              <Group justify="space-between" align="baseline">
                <Text
                  size="xs"
                  tt="uppercase"
                  c="dimmed"
                  fw={600}
                  style={{ letterSpacing: '0.08em' }}
                >
                  {mKey(`common.pages.booking.participants.kinds.${g.kind}` as any)}
                </Text>
                <Text size="xs" c="dimmed">
                  {m.common_pages_booking_participants_total_participants({
                    count: g.items.length,
                  })}
                </Text>
              </Group>
              <Stack gap="xs">
                {g.items.map((p) => (
                  <ParticipantRow
                    key={p.participantId}
                    p={p}
                    dietaryOptions={dietaryOptions}
                    onDietChange={(v) =>
                      updateParticipant({
                        participantId: p.participantId,
                        dietaryTag: v,
                      })
                    }
                    onRemove={() => {
                      if (
                        window.confirm(
                          m.common_pages_booking_participants_remove_confirm({
                            name: p.name,
                          }),
                        )
                      ) {
                        removeParticipant({ participantId: p.participantId })
                      }
                    }}
                    allergyDraft={newAllergyByPid[p.participantId] ?? ''}
                    onAllergyDraftChange={(v) =>
                      setNewAllergyByPid((m) => ({
                        ...m,
                        [p.participantId]: v,
                      }))
                    }
                    allergyEditorOpen={allergyOpenByPid[p.participantId] ?? true}
                    onToggleAllergyEditor={() =>
                      setAllergyOpenByPid((m) => ({
                        ...m,
                        [p.participantId]: !m[p.participantId],
                      }))
                    }
                    onAddAllergy={() => {
                      const val = (newAllergyByPid[p.participantId] ?? '').trim()
                      if (!val) return
                      addAllergy(
                        {
                          participantId: p.participantId,
                          allergen: val,
                          severity: 'standard',
                        },
                        {
                          onSuccess: () =>
                            setNewAllergyByPid((m) => ({
                              ...m,
                              [p.participantId]: '',
                            })),
                        },
                      )
                    }}
                    onRemoveAllergy={(allergen) =>
                      removeAllergy({
                        participantId: p.participantId,
                        allergen,
                      })
                    }
                  />
                ))}
              </Stack>
            </Stack>
          ))}
        </Stack>
      )}
    </Stack>
  )
}

function ParticipantRow({
  p,
  dietaryOptions,
  onDietChange,
  onRemove,
  allergyDraft,
  onAllergyDraftChange,
  allergyEditorOpen,
  onToggleAllergyEditor,
  onAddAllergy,
  onRemoveAllergy,
}: {
  p: Participant
  dietaryOptions: { value: string; label: string }[]
  onDietChange: (v: DietaryTag | null) => void
  onRemove: () => void
  allergyDraft: string
  onAllergyDraftChange: (v: string) => void
  allergyEditorOpen: boolean
  onToggleAllergyEditor: () => void
  onAddAllergy: () => void
  onRemoveAllergy: (allergen: string) => void
}) {
  useLocale()
  const tint = tintFor(p.participantId)

  return (
    <Paper
      withBorder
      radius="md"
      p="md"
      data-testid={`participant-row-${p.participantId}`}
      style={{ borderColor: '#E5DDE3' }}
    >
      <Stack gap="sm">
        <Box
          style={{
            display: 'grid',
            gridTemplateColumns:
              'auto minmax(160px, 1.4fr) minmax(140px, 1fr) auto auto',
            gap: 'var(--mantine-spacing-md)',
            alignItems: 'center',
          }}
        >
          {/* Avatar */}
          <Box
            style={{
              width: 36,
              height: 36,
              borderRadius: 18,
              background: tint,
              color: '#fff',
              fontSize: 13,
              fontWeight: 700,
              display: 'inline-flex',
              alignItems: 'center',
              justifyContent: 'center',
              flexShrink: 0,
            }}
          >
            {initials(p.name) || '·'}
          </Box>

          {/* Name + room */}
          <Stack gap={2}>
            <Text fw={600} size="sm" style={{ lineHeight: 1.2 }}>
              {asI18n(`${p.name}`)}
            </Text>
            {p.roomNumber != null ? (
              <Text size="xs" c="dimmed">
                {asI18n(`${m.common_pages_booking_participants_cols_room()} #${p.roomNumber}`)}
              </Text>
            ) : (
              <Text size="xs" c="dimmed" fs="italic">
                {asI18n('—')}
              </Text>
            )}
          </Stack>

          {/* Diet pill (select) */}
          <Select
            size="xs"
            data-testid={`participant-diet-${p.participantId}`}
            aria-label={m.common_pages_booking_participants_cols_diet()}
            value={p.dietaryTag}
            onChange={(v) => onDietChange((v as DietaryTag | null) ?? null)}
            data={dietaryOptions}
            clearable
            placeholder={m.common_pages_booking_participants_dietary_unknown()}
          />

          {/* Allergy summary chip */}
          <AllergySummary count={p.allergies.length} />

          {/* Delete */}
          <Tooltip label={m.common_actions_delete()} withArrow>
            <ActionIcon
              variant="subtle"
              color="gray"
              size="md"
              data-testid={`remove-participant-${p.participantId}`}
              onClick={onRemove}
              aria-label={m.common_actions_delete()}
            >
              <span aria-hidden style={{ fontSize: 16, lineHeight: 1 }}>×</span>
            </ActionIcon>
          </Tooltip>
        </Box>

        {/* Allergy chips + editor */}
        <Box style={{ paddingLeft: 52 }}>
          {p.allergies.length === 0 && !allergyEditorOpen ? (
            <Button
              size="compact-xs"
              variant="subtle"
              color="plum"
              onClick={onToggleAllergyEditor}
              styles={{ root: { paddingLeft: 0, paddingRight: 0 } }}
            >
              {m.common_pages_booking_participants_allergy_add()}
            </Button>
          ) : (
            <Group gap="xs" wrap="wrap" align="center">
              {p.allergies.map((a) => (
                <AllergyChip
                  key={a.allergen}
                  allergy={a}
                  onRemove={() => onRemoveAllergy(a.allergen)}
                  testId={`remove-allergy-${p.participantId}-${a.allergen}`}
                  removeLabel={m.common_pages_booking_participants_allergy_remove_aria({
                    allergen: a.allergen,
                  })}
                />
              ))}
              {!allergyEditorOpen ? (
                <Button
                  size="compact-xs"
                  variant="subtle"
                  color="plum"
                  onClick={onToggleAllergyEditor}
                >
                  {m.common_pages_booking_participants_allergy_add()}
                </Button>
              ) : null}
            </Group>
          )}

          {allergyEditorOpen && (
            <Group gap="xs" mt="xs" wrap="nowrap">
              <TextInput
                size="xs"
                placeholder={m.common_pages_admin_booking_allergies_add_placeholder()}
                data-testid={`new-allergy-${p.participantId}`}
                value={allergyDraft}
                onChange={(e) => onAllergyDraftChange(e.currentTarget.value)}
                onKeyDown={(e) => {
                  if (e.key === 'Enter') onAddAllergy()
                }}
                style={{ flex: 1, maxWidth: 280 }}
              />
              <Button
                size="compact-xs"
                color="plum"
                data-testid={`add-allergy-${p.participantId}`}
                disabled={!allergyDraft.trim()}
                onClick={onAddAllergy}
              >
                {m.common_pages_admin_booking_allergies_add()}
              </Button>
              <Button
                size="compact-xs"
                variant="subtle"
                color="gray"
                onClick={onToggleAllergyEditor}
              >
                {m.common_actions_cancel({ defaultValue: 'Cancel' })}
              </Button>
            </Group>
          )}
        </Box>
      </Stack>
    </Paper>
  )
}

function AllergySummary({ count }: { count: number }) {
  useLocale()
  if (count === 0) {
    return (
      <Text size="xs" c="dimmed">
        {m.common_pages_booking_participants_allergy_none()}
      </Text>
    )
  }
  return (
    <Badge
      variant="light"
      color="peach"
      size="sm"
      styles={{
        root: {
          background: '#FFE7CF',
          color: '#7A4A18',
          textTransform: 'none',
          fontWeight: 600,
        },
      }}
    >
      {m.common_pages_booking_participants_allergy_count({ count })}
    </Badge>
  )
}

function AllergyChip({
  allergy,
  onRemove,
  testId,
  removeLabel,
}: {
  allergy: Allergy
  onRemove: () => void
  testId: string
  removeLabel: I18nString
}) {
  useLocale()
  const sev = severityKey(allergy.severity)
  const style = SEVERITY_STYLE[sev]
  const sevLabel =
    sev === 'standard'
      ? null
      : mKey(`common.pages.booking.participants.severity.${sev}` as const)

  return (
    <Box
      style={{
        display: 'inline-flex',
        alignItems: 'center',
        gap: 6,
        background: style.bg,
        border: `1px solid ${style.border}`,
        color: style.fg,
        borderRadius: 999,
        padding: '2px 4px 2px 10px',
        fontSize: 12,
        fontWeight: 500,
        lineHeight: 1.4,
      }}
    >
      <span>{mKey(`common.pages.allergens.${allergy.allergen}` as any)}</span>
      {sevLabel ? (
        <span
          style={{
            fontSize: 10,
            textTransform: 'uppercase',
            letterSpacing: '0.06em',
            opacity: 0.8,
          }}
        >
          · {sevLabel}
        </span>
      ) : null}
      <ActionIcon
        size="xs"
        variant="transparent"
        data-testid={testId}
        onClick={onRemove}
        aria-label={removeLabel}
        style={{ color: style.fg }}
      >
        <span aria-hidden style={{ fontSize: 12, lineHeight: 1 }}>×</span>
      </ActionIcon>
    </Box>
  )
}
