'use client';

/**
 * Dev-only design-system audit page.
 *
 * Its job is to make the monochrome rule falsifiable: every Astryx surface
 * that can carry a colour is rendered here, including the categorical hue
 * variants we deliberately aliased to gray. Anything that still shows a hue
 * other than success-green / warning-amber / error-red is a token we missed
 * in aliasHueToGray(), and gets added there rather than patched locally.
 */

import {useState, useSyncExternalStore} from 'react';
import {Card} from '@astryxdesign/core/Card';
import {Button} from '@astryxdesign/core/Button';
import {Badge} from '@astryxdesign/core/Badge';
import {Banner} from '@astryxdesign/core/Banner';
import {StatusDot} from '@astryxdesign/core/StatusDot';
import {ProgressBar} from '@astryxdesign/core/ProgressBar';
import {Skeleton} from '@astryxdesign/core/Skeleton';
import {EmptyState} from '@astryxdesign/core/EmptyState';
import {TextInput} from '@astryxdesign/core/TextInput';
import {TextArea} from '@astryxdesign/core/TextArea';
import {Switch} from '@astryxdesign/core/Switch';
import {CheckboxInput} from '@astryxdesign/core/CheckboxInput';
import {Divider} from '@astryxdesign/core/Divider';
import {Avatar} from '@astryxdesign/core/Avatar';
import {Icon} from '@astryxdesign/core/Icon';
import {Heading, Text} from '@astryxdesign/core/Text';
import {VStack, HStack} from '@astryxdesign/core/Layout';
import {Grid} from '@astryxdesign/core/Grid';

const HUES = [
  'blue',
  'cyan',
  'green',
  'orange',
  'pink',
  'purple',
  'red',
  'teal',
  'yellow',
] as const;

const DATA_RAMP = [1, 2, 3, 4, 5] as const;

function Section({title, hint, children}: {title: string; hint?: string; children: React.ReactNode}) {
  return (
    <VStack gap={3}>
      <VStack gap={1}>
        <Heading level={3}>{title}</Heading>
        {hint ? <Text size="sm" color="secondary">{hint}</Text> : null}
      </VStack>
      <Card>
        <VStack gap={4}>{children}</VStack>
      </Card>
    </VStack>
  );
}

function Swatch({label, color}: {label: string; color: string}) {
  return (
    <VStack gap={1}>
      <div
        style={{
          height: 48,
          borderRadius: 'var(--radius-element)',
          background: color,
          boxShadow: 'inset 0 0 0 1px var(--color-border)',
        }}
      />
      <Text size="xsm" color="secondary">{label}</Text>
    </VStack>
  );
}

export default function TokensPage() {
  const [name, setName] = useState('');
  const [query, setQuery] = useState('Free coffee');
  const [notes, setNotes] = useState('');
  const [auto, setAuto] = useState(true);
  const [closed, setClosed] = useState(false);
  // "Has this hydrated yet?" via useSyncExternalStore — false on the server,
  // true on the client, with no setState in an effect body.
  const showError = useSyncExternalStore(
    () => () => {},
    () => true,
    () => false,
  );

  return (
    <VStack gap={6} padding={6}>
      <VStack gap={1}>
        <Heading level={1}>Design tokens</Heading>
        <Text color="secondary">
          Monochrome audit. The only colour permitted below is semantic:
          success, warning, error. Everything else must read as gray.
        </Text>
      </VStack>

      <Section title="Surfaces" hint="body → surface → card → muted, the four elevation steps of the shell.">
        <Grid columns={{minWidth: 140, repeat: 'fit'}} gap={3}>
          <Swatch label="body #000000" color="var(--color-background-body)" />
          <Swatch label="surface #0F0F10" color="var(--color-background-surface)" />
          <Swatch label="card #171717" color="var(--color-background-card)" />
          <Swatch label="muted #202124" color="var(--color-background-muted)" />
          <Swatch label="border #2F2F2F" color="var(--color-border)" />
          <Swatch label="border-emph" color="var(--color-border-emphasized)" />
        </Grid>
      </Section>

      <Section title="Text & icon" hint="White / #A1A1AA / #71717A.">
        <VStack gap={2}>
          <Text>Primary text — white on black.</Text>
          <Text color="secondary">Secondary text — #A1A1AA.</Text>
          <Text color="disabled">Disabled text — #71717A.</Text>
          <HStack gap={3}>
            <Icon icon="search" />
            <Icon icon="check" color="secondary" />
            <Icon icon="warning" color="warning" />
            <Icon icon="error" color="error" />
            <Icon icon="success" color="success" />
          </HStack>
        </VStack>
      </Section>

      <Section
        title="Buttons"
        hint="Primary = gray fill. Secondary = transparent + border. Ghost = transparent, gray hover. Tab through these to check focus rings."
      >
        <VStack gap={3}>
          <HStack gap={2} wrap="wrap">
            <Button variant="primary" label="Primary" />
            <Button variant="secondary" label="Secondary" />
            <Button variant="ghost" label="Ghost" />
            <Button variant="destructive" label="Destructive" />
          </HStack>
          <HStack gap={2} wrap="wrap">
            <Button variant="primary" label="Disabled" isDisabled />
            <Button variant="secondary" label="Disabled" isDisabled />
            <Button variant="primary" label="Loading" isLoading />
            <Button variant="primary" label="With icon" icon={<Icon icon="search" />} />
          </HStack>
          <HStack gap={2} wrap="wrap" vAlign="center">
            <Button size="sm" variant="primary" label="Small" />
            <Button size="md" variant="primary" label="Medium" />
            <Button size="lg" variant="primary" label="Large" />
          </HStack>
        </VStack>
      </Section>

      <Section
        title="Badges — semantic"
        hint="These four are allowed to carry colour. They are the semantic language."
      >
        <HStack gap={2} wrap="wrap">
          <Badge variant="neutral" label="Neutral" />
          <Badge variant="info" label="Info" />
          <Badge variant="success" label="Success" />
          <Badge variant="warning" label="Warning" />
          <Badge variant="error" label="Error" />
        </HStack>
      </Section>

      <Section
        title="Badges — categorical hues"
        hint="AUDIT: blue/cyan/orange/pink/purple/teal must render gray. green/red/yellow stay tinted by design — Banner's semantic statuses resolve through those same hue tokens."
      >
        <HStack gap={2} wrap="wrap">
          {HUES.map((hue) => (
            <Badge key={hue} variant={hue} label={hue} />
          ))}
        </HStack>
      </Section>

      <Section
        title="Cards — categorical variants"
        hint="AUDIT: same rule. default / transparent / muted / gray plus the nine hues."
      >
        <Grid columns={{minWidth: 150, repeat: 'fit'}} gap={3}>
          {(['default', 'transparent', 'muted', 'gray', ...HUES] as const).map((v) => (
            <Card key={v} variant={v}>
              <Text size="sm">{v}</Text>
            </Card>
          ))}
        </Grid>
      </Section>

      <Section title="Status dots" hint="accent must be gray; the rest semantic.">
        <HStack gap={4} wrap="wrap" vAlign="center">
          {(['neutral', 'accent', 'success', 'warning', 'error'] as const).map((v) => (
            <HStack key={v} gap={2} vAlign="center">
              <StatusDot variant={v} label={v} />
              <Text size="sm" color="secondary">{v}</Text>
            </HStack>
          ))}
        </HStack>
      </Section>

      <Section title="Banners" hint="Full-width status surfaces used for alerts and expiry warnings.">
        <VStack gap={2}>
          <Banner status="info" title="Peak hours start in 20 minutes" description="Staff coverage is below the weekday average." />
          <Banner status="success" title="Weekend campaign hit its target" description="1,284 LYTs redeemed against a 1,000 goal." />
          <Banner status="warning" title="3 rewards expire this week" description="Free Coffee, Combo 20% and Weekend Bonus." />
          <Banner status="error" title="Koramangala store is offline" description="No footfall events received in 4 hours." />
        </VStack>
      </Section>

      <Section title="Inputs" hint="Black background, gray border, white text, gray placeholder.">
        <Grid columns={{minWidth: 240, repeat: 'fit'}} gap={4}>
          <TextInput
            label="Store name"
            placeholder="e.g. Indiranagar Flagship"
            value={name}
            onChange={setName}
          />
          <TextInput
            label="Disabled"
            placeholder="Not editable"
            value=""
            isDisabled
          />
          {/*
            Status is applied AFTER mount on purpose. Astryx's useEntryAnimation
            assumes 'use client' modules never execute on the server, which is
            false in the App Router: SSR renders without the slide-down class,
            then hydration (which lands after the first rAF) renders with it,
            and React reports a class mismatch it will not patch up.
            Real forms set status on blur/submit, so they never hit this; only
            a status present at initial paint does. See AGENTS.md.
          */}
          <TextInput
            label="With error"
            placeholder="Required"
            value=""
            status={
              showError
                ? {type: 'error', message: 'This field is required'}
                : undefined
            }
          />
          <TextInput
            label="Search"
            placeholder="Find a reward…"
            value={query}
            onChange={setQuery}
            startIcon="search"
            hasClear
          />
        </Grid>
        <TextArea
          label="Notes"
          placeholder="Internal notes about this store…"
          rows={3}
          value={notes}
          onChange={setNotes}
        />
        <HStack gap={5} wrap="wrap" vAlign="center">
          <Switch label="Auto-issue rewards" value={auto} onChange={setAuto} />
          <Switch label="Disabled" value={false} isDisabled />
          <CheckboxInput
            label="Include closed stores"
            value={closed}
            onChange={setClosed}
          />
          <CheckboxInput label="Indeterminate" value="indeterminate" />
        </HStack>
      </Section>

      <Section title="Feedback" hint="Progress, skeleton and empty state.">
        <VStack gap={4}>
          <ProgressBar value={64} label="Monthly target" />
          <VStack gap={2}>
            <Skeleton height={16} width="40%" />
            <Skeleton height={16} width="70%" />
            <Skeleton height={16} width="55%" />
          </VStack>
          <Divider />
          <EmptyState
            icon={<Icon icon="search" size="lg" />}
            title="No rewards match this filter"
            description="Try widening the date range or clearing the store filter."
            actions={<Button variant="secondary" label="Clear filters" />}
          />
        </VStack>
      </Section>

      <Section
        title="Avatars"
        hint="AUDIT: Astryx auto-assigns a categorical hue per name. These must all read gray."
      >
        <HStack gap={2} wrap="wrap">
          {['Anita R', 'Vikram S', 'Priya M', 'Rahul K', 'Deepa N', 'Suresh T'].map((n) => (
            <Avatar key={n} name={n} />
          ))}
        </HStack>
      </Section>

      <Section
        title="Chart ramp"
        hint="--color-data-gray-1..5, the ordered series palette. Lightest = most important series."
      >
        <Grid columns={{minWidth: 110, repeat: 'fit'}} gap={3}>
          {DATA_RAMP.map((i) => (
            <Swatch key={i} label={`data-gray-${i}`} color={`var(--color-data-gray-${i})`} />
          ))}
          <Swatch label="data-neutral" color="var(--color-data-neutral)" />
        </Grid>
      </Section>

      <Section
        title="Chart categorical slots"
        hint="AUDIT: Astryx's 10 categorical data tokens, all remapped onto the gray ramp."
      >
        <Grid columns={{minWidth: 110, repeat: 'fit'}} gap={3}>
          {(['blue', 'orange', 'green', 'purple', 'cyan', 'red', 'teal', 'pink', 'brown', 'indigo'] as const).map(
            (hue) => (
              <Swatch
                key={hue}
                label={hue}
                color={`var(--color-data-categorical-${hue})`}
              />
            ),
          )}
        </Grid>
      </Section>

      <Section title="Elevation" hint="On pure black, separation comes from the 1px inset rim, not the drop shadow.">
        <Grid columns={{minWidth: 160, repeat: 'fit'}} gap={4}>
          {(['none', 'low', 'med', 'high'] as const).map((e) => (
            <Card key={e} elevation={e}>
              <Text size="sm">elevation {e}</Text>
            </Card>
          ))}
        </Grid>
      </Section>
    </VStack>
  );
}
