'use client';

import { useEffect, useMemo, useState } from 'react';
import {
  AlertTriangle,
  CheckCircle2,
  Code2,
  GitBranch,
  GitPullRequest,
  MessagesSquare,
  RefreshCw,
} from 'lucide-react';

import { Badge, Button } from '@spoon/ui';

type DemoStep = 'check' | 'thread' | 'workspace' | 'decision' | 'pr';

type DemoStepConfig = {
  id: DemoStep;
  label: string;
  title: string;
  description: string;
};

const defaultStep: DemoStepConfig = {
  id: 'check',
  label: 'Check',
  title: 'Upstream moved',
  description: 'Spoon checks default branches and compares the fork network.',
};

const steps: DemoStepConfig[] = [
  defaultStep,
  {
    id: 'thread',
    label: 'Thread',
    title: 'Custom work needs context',
    description:
      'Fork-only commits turn an upstream update into a durable thread.',
  },
  {
    id: 'workspace',
    label: 'Workspace',
    title: 'OpenCode gets a sandbox',
    description:
      'The worker opens a repo workspace with files, thread context, and checks.',
  },
  {
    id: 'decision',
    label: 'Decision',
    title: 'Review the maintenance call',
    description:
      'Spoon records risk, conflicts, and the recommended next step.',
  },
  {
    id: 'pr',
    label: 'Draft PR',
    title: 'Ship as reviewable work',
    description:
      'Code changes leave the workspace as a branch and draft pull request.',
  },
];

const getReducedMotionPreference = () => {
  if (
    typeof window === 'undefined' ||
    typeof window.matchMedia !== 'function'
  ) {
    return false;
  }

  return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
};

const usePrefersReducedMotion = () => {
  const [reducedMotion, setReducedMotion] = useState(
    getReducedMotionPreference,
  );

  useEffect(() => {
    if (typeof window.matchMedia !== 'function') {
      return;
    }

    const query = window.matchMedia('(prefers-reduced-motion: reduce)');
    const update = () => setReducedMotion(query.matches);
    update();
    query.addEventListener('change', update);
    return () => query.removeEventListener('change', update);
  }, []);

  return reducedMotion;
};

const Metric = ({
  label,
  value,
  tone = 'default',
}: {
  label: string;
  value: string;
  tone?: 'default' | 'warning' | 'good';
}) => (
  <div className='border-border bg-background rounded-md border p-3'>
    <p className='text-muted-foreground text-xs'>{label}</p>
    <p
      className={
        tone === 'warning'
          ? 'mt-1 text-lg font-semibold text-amber-600'
          : tone === 'good'
            ? 'mt-1 text-lg font-semibold text-emerald-600'
            : 'mt-1 text-lg font-semibold'
      }
    >
      {value}
    </p>
  </div>
);

const CheckPreview = () => (
  <div className='space-y-4'>
    <div className='grid gap-3 sm:grid-cols-3'>
      <Metric label='Raw upstream ahead' value='3 commits' tone='warning' />
      <Metric label='Fork-only work' value='5 commits' />
      <Metric label='Status' value='Needs thread' tone='warning' />
    </div>
    <div className='border-border bg-background rounded-md border p-4'>
      <div className='flex items-center justify-between gap-4'>
        <div className='min-w-0'>
          <p className='font-medium'>usesend-authentik</p>
          <p className='text-muted-foreground text-xs'>
            usesend/usesend {'->'} gibbyb/usesend
          </p>
        </div>
        <Badge variant='outline'>daily check</Badge>
      </div>
      <div className='mt-4 grid gap-2 text-sm'>
        <div className='bg-muted/50 flex items-center justify-between rounded-md px-3 py-2'>
          <span className='flex items-center gap-2'>
            <RefreshCw className='text-primary size-4' />
            Compare upstream main
          </span>
          <span className='text-muted-foreground'>complete</span>
        </div>
        <div className='bg-muted/50 flex items-center justify-between rounded-md px-3 py-2'>
          <span className='flex items-center gap-2'>
            <GitBranch className='text-primary size-4' />
            Detect fork-only commits
          </span>
          <span className='text-muted-foreground'>custom auth work</span>
        </div>
      </div>
    </div>
  </div>
);

const ThreadPreview = () => (
  <div className='space-y-4'>
    <div className='border-border bg-background rounded-md border p-4'>
      <div className='flex flex-wrap items-center gap-2'>
        <MessagesSquare className='text-primary size-4' />
        <p className='font-medium'>
          Upstream changed: auth and webhook updates
        </p>
        <Badge className='bg-amber-500/10 text-amber-700 hover:bg-amber-500/10'>
          Review required
        </Badge>
      </div>
      <div className='mt-4 space-y-3 text-sm'>
        <div className='bg-muted/60 rounded-md p-3'>
          <p className='text-muted-foreground text-xs'>system</p>
          <p className='mt-1'>
            Spoon found upstream commits that touch auth-adjacent files. Fork
            has custom Authentik work.
          </p>
        </div>
        <div className='rounded-md border p-3'>
          <p className='text-muted-foreground text-xs'>assistant</p>
          <p className='mt-1'>
            These updates are probably valuable, but they overlap with fork-only
            provider changes.
          </p>
        </div>
      </div>
    </div>
  </div>
);

const WorkspacePreview = () => (
  <div className='grid min-h-[19rem] gap-3 lg:grid-cols-[0.8fr_1.4fr_0.9fr]'>
    <div className='border-border bg-background rounded-md border p-3 text-xs'>
      <p className='mb-3 font-medium'>Files</p>
      {['packages/auth/providers.ts', '.env.example', 'apps/web/auth.ts'].map(
        (file) => (
          <div
            key={file}
            className='text-muted-foreground hover:text-foreground rounded px-2 py-1.5'
          >
            {file}
          </div>
        ),
      )}
    </div>
    <div className='border-border rounded-md border bg-zinc-950 p-3 font-mono text-xs text-zinc-100'>
      <div className='mb-3 flex items-center justify-between text-zinc-400'>
        <span>providers.ts</span>
        <span>vim mode</span>
      </div>
      <pre className='overflow-hidden leading-6'>
        <code>{`export const providers = [
  Authentik({
    issuer: env.AUTHENTIK_ISSUER,
    clientId: env.AUTHENTIK_CLIENT_ID,
  }),
];

// GitHub provider removed in fork`}</code>
      </pre>
    </div>
    <div className='border-border bg-background rounded-md border p-3 text-xs'>
      <p className='mb-3 font-medium'>Thread</p>
      <div className='space-y-2'>
        <p className='bg-muted/60 rounded-md p-2'>
          Preserve Authentik-only auth.
        </p>
        <p className='rounded-md border p-2'>
          Running typecheck after provider update.
        </p>
        <p className='text-muted-foreground bg-muted/40 rounded-md p-2'>
          Secrets available as process env.
        </p>
      </div>
    </div>
  </div>
);

const DecisionPreview = () => (
  <div className='space-y-3'>
    {[
      ['Risk', 'Medium', 'Auth provider wiring overlaps custom fork changes.'],
      [
        'Recommended action',
        'Open review PR',
        'Keep the fork branch reviewable.',
      ],
      [
        'Conflict signals',
        '2 files',
        'OAuth callback copy and package scripts.',
      ],
    ].map(([label, value, detail]) => (
      <div
        key={label}
        className='border-border bg-background rounded-md border p-4'
      >
        <div className='flex items-center justify-between gap-3'>
          <p className='text-muted-foreground text-sm'>{label}</p>
          <Badge variant='outline'>{value}</Badge>
        </div>
        <p className='mt-2 text-sm'>{detail}</p>
      </div>
    ))}
  </div>
);

const DraftPrPreview = () => (
  <div className='border-border bg-background rounded-md border p-5'>
    <div className='flex flex-wrap items-center justify-between gap-3'>
      <div>
        <p className='font-medium'>Draft PR opened</p>
        <p className='text-muted-foreground text-xs'>
          spoon/thread/authentik-upstream
        </p>
      </div>
      <Badge className='bg-emerald-500/10 text-emerald-700 hover:bg-emerald-500/10'>
        ready for review
      </Badge>
    </div>
    <div className='mt-5 grid gap-2 text-sm'>
      <div className='bg-muted/50 flex items-center justify-between rounded-md px-3 py-2'>
        <span className='flex items-center gap-2'>
          <CheckCircle2 className='size-4 text-emerald-600' />
          lint
        </span>
        <span>passed</span>
      </div>
      <div className='bg-muted/50 flex items-center justify-between rounded-md px-3 py-2'>
        <span className='flex items-center gap-2'>
          <AlertTriangle className='size-4 text-amber-600' />
          typecheck
        </span>
        <span>queued</span>
      </div>
    </div>
    <Button className='mt-5 w-full' variant='outline'>
      Review PR
      <GitPullRequest className='size-4' />
    </Button>
  </div>
);

const renderPreview = (step: DemoStep) => {
  if (step === 'check') return <CheckPreview />;
  if (step === 'thread') return <ThreadPreview />;
  if (step === 'workspace') return <WorkspacePreview />;
  if (step === 'decision') return <DecisionPreview />;
  return <DraftPrPreview />;
};

export const ProductStoryDemo = () => {
  const [activeStep, setActiveStep] = useState<DemoStep>('check');
  const [paused, setPaused] = useState(false);
  const reducedMotion = usePrefersReducedMotion();
  const active = useMemo(
    () => steps.find((step) => step.id === activeStep) ?? defaultStep,
    [activeStep],
  );

  useEffect(() => {
    if (paused || reducedMotion) return;
    const interval = window.setInterval(() => {
      setActiveStep((current) => {
        const index = steps.findIndex((step) => step.id === current);
        return steps[(index + 1) % steps.length]?.id ?? 'check';
      });
    }, 3500);
    return () => window.clearInterval(interval);
  }, [paused, reducedMotion]);

  return (
    <div
      id='demo'
      aria-label='Animated Spoon maintenance flow demo'
      className='border-border bg-card overflow-hidden rounded-lg border shadow-sm'
      onMouseEnter={() => setPaused(true)}
      onMouseLeave={() => setPaused(false)}
      onFocus={() => setPaused(true)}
      onBlur={() => setPaused(false)}
    >
      <div className='border-border flex items-start justify-between gap-4 border-b px-5 py-4'>
        <div>
          <p className='text-sm font-medium'>{active.title}</p>
          <p className='text-muted-foreground mt-1 text-xs'>
            {active.description}
          </p>
        </div>
        <Badge className='bg-primary/10 text-primary hover:bg-primary/10'>
          Live flow
        </Badge>
      </div>
      <div className='border-border flex gap-2 overflow-x-auto border-b p-2'>
        {steps.map((step) => (
          <button
            key={step.id}
            type='button'
            aria-current={step.id === activeStep ? 'step' : undefined}
            onClick={() => setActiveStep(step.id)}
            className={
              step.id === activeStep
                ? 'bg-primary text-primary-foreground flex-none rounded-md px-3 py-2 text-xs font-medium'
                : 'text-muted-foreground hover:bg-muted hover:text-foreground flex-none rounded-md px-3 py-2 text-xs font-medium'
            }
          >
            {step.label}
          </button>
        ))}
      </div>
      <div className='min-h-[24rem] p-4 sm:p-5'>
        {renderPreview(activeStep)}
      </div>
      <div className='border-border bg-muted/30 grid gap-3 border-t p-4 text-sm sm:grid-cols-3'>
        <span className='flex items-center gap-2'>
          <GitBranch className='text-primary size-4' />
          fork stays source of truth
        </span>
        <span className='flex items-center gap-2'>
          <MessagesSquare className='text-primary size-4' />
          decisions stay threaded
        </span>
        <span className='flex items-center gap-2'>
          <Code2 className='text-primary size-4' />
          workspace opens when needed
        </span>
      </div>
    </div>
  );
};
