'use client';

import { useState, useCallback } from 'react';
import { RefreshCw, Copy, Check, Clock } from 'lucide-react';
import { toast } from 'sonner';
import { cn, actionBtn } from '@/lib/utils';
import { SliderRow } from '@/components/ui/slider-row';
import { MobileTabs } from '@/components/ui/mobile-tabs';
import {
  generatePassword, passwordEntropy,
  generateUUID,
  generateApiKey,
  generateHash,
  generateToken,
  type PasswordOpts,
  type ApiKeyOpts,
  type HashOpts,
  type TokenOpts,
} from '@/lib/random/generators';

type GeneratorType = 'password' | 'uuid' | 'apikey' | 'hash' | 'token';
type MobileTab = 'configure' | 'output';

const GENERATOR_TABS: { value: GeneratorType; label: string }[] = [
  { value: 'password', label: 'Password' },
  { value: 'uuid', label: 'UUID' },
  { value: 'apikey', label: 'API Key' },
  { value: 'hash', label: 'Hash' },
  { value: 'token', label: 'Token' },
];

const selectCls =
  'w-full bg-transparent border border-border/40 rounded-lg px-2.5 py-1.5 text-xs font-mono outline-none focus:border-primary/50 transition-colors text-foreground/80 cursor-pointer';

const strengthLabel = (bits: number) => {
  if (bits < 40) return { label: 'Weak', color: 'bg-red-500' };
  if (bits < 60) return { label: 'Fair', color: 'bg-amber-400' };
  if (bits < 80) return { label: 'Good', color: 'bg-yellow-400' };
  if (bits < 100) return { label: 'Strong', color: 'bg-emerald-400' };
  return { label: 'Very Strong', color: 'bg-primary' };
};

export function RandomGenerator() {
  const [type, setType] = useState<GeneratorType>('password');
  const [mobileTab, setMobileTab] = useState<MobileTab>('configure');
  const [output, setOutput] = useState('');
  const [copied, setCopied] = useState(false);
  const [generating, setGenerating] = useState(false);
  const [history, setHistory] = useState<string[]>([]);

  // Options per type
  const [pwOpts, setPwOpts] = useState<PasswordOpts>({
    length: 24, uppercase: true, lowercase: true, numbers: true, symbols: true,
  });
  const [apiOpts, setApiOpts] = useState<ApiKeyOpts>({
    length: 32, format: 'hex', prefix: '',
  });
  const [hashOpts, setHashOpts] = useState<HashOpts>({
    algorithm: 'SHA-256', input: '',
  });
  const [tokenOpts, setTokenOpts] = useState<TokenOpts>({
    bytes: 32, format: 'hex',
  });

  const pushHistory = (val: string) =>
    setHistory((h) => [val, ...h].slice(0, 8));

  const generate = useCallback(async () => {
    setGenerating(true);
    try {
      let result = '';
      switch (type) {
        case 'password': result = generatePassword(pwOpts); break;
        case 'uuid':     result = generateUUID(); break;
        case 'apikey':   result = generateApiKey(apiOpts); break;
        case 'hash':     result = await generateHash(hashOpts); break;
        case 'token':    result = generateToken(tokenOpts); break;
      }
      setOutput(result);
      pushHistory(result);
      setMobileTab('output');
    } catch {
      toast.error('Generation failed');
    } finally {
      setGenerating(false);
    }
  }, [type, pwOpts, apiOpts, hashOpts, tokenOpts]);

  const copy = (val = output) => {
    if (!val) return;
    navigator.clipboard.writeText(val);
    setCopied(true);
    toast.success('Copied to clipboard');
    setTimeout(() => setCopied(false), 2000);
  };

  const entropy = type === 'password' ? passwordEntropy(pwOpts) : null;
  const strength = entropy !== null ? strengthLabel(entropy) : null;

  return (
    <div className="flex flex-col gap-4">

      <MobileTabs
        tabs={[{ value: 'configure', label: 'Configure' }, { value: 'output', label: 'Output' }]}
        active={mobileTab}
        onChange={(v) => setMobileTab(v as MobileTab)}
      />

      <div
        className="grid grid-cols-1 lg:grid-cols-5 gap-4"
        style={{ height: 'calc(100svh - 120px)' }}
      >
        {/* ── Left: type selector + options ───────────────────── */}
        <div className={cn(
          'lg:col-span-2 flex flex-col gap-3 overflow-hidden',
          mobileTab !== 'configure' && 'hidden lg:flex'
        )}>
          {/* Type selector */}
          <div className="glass rounded-xl p-4 shrink-0">
            <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest block mb-3">
              Generator
            </span>
            <div className="flex flex-col gap-1">
              {GENERATOR_TABS.map(({ value, label }) => (
                <button
                  key={value}
                  onClick={() => { setType(value); setOutput(''); }}
                  className={cn(
                    'w-full text-left px-3 py-2 rounded-lg text-xs font-mono transition-all',
                    type === value
                      ? 'bg-primary/15 border border-primary/30 text-primary'
                      : 'text-muted-foreground hover:text-foreground hover:bg-white/[0.03] border border-transparent'
                  )}
                >
                  {label}
                </button>
              ))}
            </div>
          </div>

          {/* Options */}
          <div className="glass rounded-xl p-4 flex flex-col flex-1 min-h-0 overflow-y-auto scrollbar-thin scrollbar-thumb-primary/20 scrollbar-track-transparent">
            <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest block mb-4 shrink-0">
              Options
            </span>

            {/* ── Password ── */}
            {type === 'password' && (
              <div className="space-y-4">
                <SliderRow
                  label="Length"
                  display={`${pwOpts.length} chars`}
                  value={pwOpts.length}
                  min={4} max={128}
                  onChange={(v) => setPwOpts((o) => ({ ...o, length: v }))}
                />
                <div className="space-y-1.5">
                  <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest">
                    Character sets
                  </span>
                  <div className="grid grid-cols-2 gap-2">
                    {([
                      { key: 'uppercase', label: 'A–Z', hint: 'Uppercase' },
                      { key: 'lowercase', label: 'a–z', hint: 'Lowercase' },
                      { key: 'numbers',   label: '0–9', hint: 'Numbers' },
                      { key: 'symbols',   label: '!@#', hint: 'Symbols' },
                    ] as const).map(({ key, label, hint }) => (
                      <label
                        key={key}
                        className={cn(
                          'flex items-center gap-2 px-3 py-2 rounded-lg border cursor-pointer transition-all select-none',
                          pwOpts[key]
                            ? 'bg-primary/10 border-primary/30 text-primary'
                            : 'border-border/30 text-muted-foreground/50 hover:border-border/50 hover:text-muted-foreground'
                        )}
                        title={hint}
                      >
                        <input
                          type="checkbox"
                          checked={pwOpts[key]}
                          onChange={(e) => setPwOpts((o) => ({ ...o, [key]: e.target.checked }))}
                          className="sr-only"
                        />
                        <span className="text-xs font-mono">{label}</span>
                      </label>
                    ))}
                  </div>
                </div>
                {strength && (
                  <div className="space-y-1.5">
                    <div className="flex items-center justify-between">
                      <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest">
                        Strength
                      </span>
                      <span className="text-[10px] font-mono text-muted-foreground/40">
                        {entropy} bits
                      </span>
                    </div>
                    <div className="h-1 rounded-full bg-white/[0.06] overflow-hidden">
                      <div
                        className={cn('h-full rounded-full transition-all duration-500', strength.color)}
                        style={{ width: `${Math.min(100, (entropy! / 128) * 100)}%` }}
                      />
                    </div>
                    <span className={cn('text-[10px] font-mono', strength.color.replace('bg-', 'text-'))}>
                      {strength.label}
                    </span>
                  </div>
                )}
              </div>
            )}

            {/* ── UUID ── */}
            {type === 'uuid' && (
              <div className="space-y-3">
                <div className="px-3 py-2.5 rounded-lg bg-white/[0.02] border border-border/20">
                  <p className="text-xs text-muted-foreground/60 leading-relaxed">
                    Generates a cryptographically random UUID v4 using the browser&apos;s built-in{' '}
                    <code className="text-primary/70 text-[10px]">crypto.randomUUID()</code>.
                  </p>
                </div>
                <p className="text-[10px] font-mono text-muted-foreground/30">
                  Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
                </p>
              </div>
            )}

            {/* ── API Key ── */}
            {type === 'apikey' && (
              <div className="space-y-4">
                <SliderRow
                  label="Length"
                  display={`${apiOpts.length} chars`}
                  value={apiOpts.length}
                  min={8} max={64}
                  onChange={(v) => setApiOpts((o) => ({ ...o, length: v }))}
                />
                <div className="space-y-1.5">
                  <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest">
                    Encoding
                  </span>
                  <select
                    value={apiOpts.format}
                    onChange={(e) => setApiOpts((o) => ({ ...o, format: e.target.value as ApiKeyOpts['format'] }))}
                    className={selectCls}
                  >
                    <option value="hex">Hex (0-9, a-f)</option>
                    <option value="base62">Base62 (alphanumeric)</option>
                    <option value="base64url">Base64url</option>
                  </select>
                </div>
                <div className="space-y-1.5">
                  <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest">
                    Prefix <span className="normal-case font-normal text-muted-foreground/40">(optional)</span>
                  </span>
                  <input
                    type="text"
                    value={apiOpts.prefix}
                    onChange={(e) => setApiOpts((o) => ({ ...o, prefix: e.target.value }))}
                    placeholder="sk, pk, api..."
                    className="w-full bg-transparent border border-border/40 rounded-lg px-2.5 py-1.5 text-xs font-mono outline-none focus:border-primary/50 transition-colors text-foreground/80 placeholder:text-muted-foreground/25"
                  />
                </div>
              </div>
            )}

            {/* ── Hash ── */}
            {type === 'hash' && (
              <div className="space-y-4">
                <div className="space-y-1.5">
                  <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest">
                    Algorithm
                  </span>
                  <select
                    value={hashOpts.algorithm}
                    onChange={(e) => setHashOpts((o) => ({ ...o, algorithm: e.target.value as HashOpts['algorithm'] }))}
                    className={selectCls}
                  >
                    <option value="SHA-1">SHA-1 (160 bit)</option>
                    <option value="SHA-256">SHA-256 (256 bit)</option>
                    <option value="SHA-512">SHA-512 (512 bit)</option>
                  </select>
                </div>
                <div className="space-y-1.5">
                  <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest">
                    Input <span className="normal-case font-normal text-muted-foreground/40">(empty = random)</span>
                  </span>
                  <textarea
                    value={hashOpts.input}
                    onChange={(e) => setHashOpts((o) => ({ ...o, input: e.target.value }))}
                    placeholder="Text to hash, or leave empty for random data..."
                    rows={4}
                    className="w-full bg-transparent border border-border/40 rounded-lg px-2.5 py-2 text-xs font-mono outline-none focus:border-primary/50 transition-colors text-foreground/80 placeholder:text-muted-foreground/25 resize-none"
                  />
                </div>
              </div>
            )}

            {/* ── Token ── */}
            {type === 'token' && (
              <div className="space-y-4">
                <div className="space-y-1.5">
                  <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest">
                    Byte length
                  </span>
                  <div className="grid grid-cols-4 gap-1.5">
                    {[16, 32, 48, 64].map((b) => (
                      <button
                        key={b}
                        onClick={() => setTokenOpts((o) => ({ ...o, bytes: b }))}
                        className={cn(
                          'py-1.5 rounded-lg text-xs font-mono border transition-all',
                          tokenOpts.bytes === b
                            ? 'bg-primary/15 border-primary/30 text-primary'
                            : 'border-border/30 text-muted-foreground/50 hover:border-border/50 hover:text-muted-foreground'
                        )}
                      >
                        {b}
                      </button>
                    ))}
                  </div>
                  <p className="text-[10px] font-mono text-muted-foreground/30">
                    {tokenOpts.bytes * 8} bits of entropy
                  </p>
                </div>
                <div className="space-y-1.5">
                  <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest">
                    Encoding
                  </span>
                  <select
                    value={tokenOpts.format}
                    onChange={(e) => setTokenOpts((o) => ({ ...o, format: e.target.value as TokenOpts['format'] }))}
                    className={selectCls}
                  >
                    <option value="hex">Hex</option>
                    <option value="base64url">Base64url</option>
                  </select>
                </div>
              </div>
            )}
          </div>
        </div>

        {/* ── Right: output + history ──────────────────────────── */}
        <div className={cn(
          'lg:col-span-3 flex flex-col gap-3 overflow-hidden',
          mobileTab !== 'output' && 'hidden lg:flex'
        )}>
          {/* Output display */}
          <div className="glass rounded-xl p-4 flex flex-col flex-1 min-h-0">
            <div className="flex items-center justify-between mb-3 shrink-0">
              <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest">
                Output
              </span>
              {output && (
                <span className="text-[9px] font-mono text-muted-foreground/30 tabular-nums">
                  {output.length} chars
                </span>
              )}
            </div>

            {/* Value box */}
            <div
              className="relative flex-1 min-h-0 rounded-xl overflow-hidden border border-white/[0.06]"
              style={{ background: '#06060e' }}
            >
              {output ? (
                <div className="absolute inset-0 p-5 overflow-auto scrollbar-thin scrollbar-thumb-white/10">
                  <p className="font-mono text-sm text-white/80 break-all leading-relaxed select-all">
                    {output}
                  </p>
                </div>
              ) : (
                <div className="absolute inset-0 flex items-center justify-center">
                  <p className="text-xs font-mono text-white/15 italic">
                    Press Generate to create a value
                  </p>
                </div>
              )}
            </div>

            {/* Actions */}
            <div className="flex gap-2 mt-3 shrink-0">
              <button
                onClick={generate}
                disabled={generating}
                className="flex-1 flex items-center justify-center gap-1.5 px-3 py-2 rounded-lg border border-primary/30 bg-primary/[0.08] hover:border-primary/55 hover:bg-primary/[0.15] text-xs font-medium text-primary transition-all duration-200 disabled:opacity-50"
              >
                <RefreshCw className={cn('w-3.5 h-3.5', generating && 'animate-spin')} />
                Generate
              </button>
              <button
                onClick={() => copy()}
                disabled={!output}
                className={actionBtn}
              >
                {copied ? <Check className="w-3.5 h-3.5" /> : <Copy className="w-3.5 h-3.5" />}
                {copied ? 'Copied' : 'Copy'}
              </button>
            </div>
          </div>

          {/* History */}
          {history.length > 0 && (
            <div className="glass rounded-xl p-4 shrink-0">
              <div className="flex items-center gap-2 mb-3">
                <Clock className="w-3 h-3 text-muted-foreground/40" />
                <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-widest">
                  Recent
                </span>
              </div>
              <div className="space-y-1">
                {history.map((item, i) => (
                  <div
                    key={i}
                    className="group flex items-center gap-2 px-2 py-1.5 rounded-lg hover:bg-white/[0.02] transition-colors"
                  >
                    <span className="text-[10px] font-mono text-white/30 group-hover:text-white/50 transition-colors truncate flex-1">
                      {item}
                    </span>
                    <button
                      onClick={() => copy(item)}
                      className="opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground/40 hover:text-primary"
                    >
                      <Copy className="w-3 h-3" />
                    </button>
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
