"use client";

import React from "react";
import Markdown from "@/components/Markdown/Markdown";
import TagSelector from "@/components/Submit/TagSelector";
import { baseRoms } from "@/data/baseRoms";
import { getScreenshotTutorial } from "@/data/screenshotTutorials";
import Image from "next/image";
import { createClient } from "@/utils/supabase/client";
import { updateHack, saveHackCovers, presignCoverUpload } from "@/app/hack/actions";
import SortableCovers from "@/components/Hack/SortableCovers";
import Select from "@/components/Primitives/Select";
import type { Database } from "@/types/db";
import { FiExternalLink } from "react-icons/fi";

interface HackEditFormProps {
  slug: string;
  initial: {
    title: string;
    summary: string;
    description: string;
    base_rom: string;
    language: string;
    completion_status: Database["public"]["Enums"]["Completion Status"] | null;
    version: string;
    box_art: string | null;
    social_links: {
      discord?: string;
      twitter?: string;
      pokecommunity?: string;
      github?: string;
    } | null;
    tags: string[];
    coverKeys: string[]; // storage keys for covers in order
    signedCoverUrls?: string[]; // optional signed URLs aligned to keys
  };
}

export default function HackEditForm({ slug, initial }: HackEditFormProps) {
  const supabase = createClient();
  const MAX_COVERS = 10;
  const [title, setTitle] = React.useState(initial.title);
  const [summary, setSummary] = React.useState(initial.summary);
  const [description, setDescription] = React.useState(initial.description);
  const [showMdPreview, setShowMdPreview] = React.useState(false);
  const [baseRom, setBaseRom] = React.useState(initial.base_rom);
  const [language, setLanguage] = React.useState(initial.language);
  const [completionStatus, setCompletionStatus] = React.useState<Database["public"]["Enums"]["Completion Status"] | null>(initial.completion_status);
  const [version, setVersion] = React.useState(initial.version);
  const [boxArt, setBoxArt] = React.useState(initial.box_art || "");
  const [discord, setDiscord] = React.useState(initial.social_links?.discord || "");
  const [twitter, setTwitter] = React.useState(initial.social_links?.twitter || "");
  const [pokecommunity, setPokecommunity] = React.useState(initial.social_links?.pokecommunity || "");
  const [github, setGithub] = React.useState(initial.social_links?.github || "");
  const [tags, setTags] = React.useState<string[]>(initial.tags || []);

  // Baseline state used for change detection and reverting
  const [baseline, setBaseline] = React.useState({
    title: initial.title,
    summary: initial.summary,
    description: initial.description,
    language: initial.language,
    completionStatus: initial.completion_status,
    boxArt: initial.box_art || "",
    tags: initial.tags || [],
    discord: initial.social_links?.discord || "",
    twitter: initial.social_links?.twitter || "",
    pokecommunity: initial.social_links?.pokecommunity || "",
    github: initial.social_links?.github || "",
  });

  type CoverItem =
    | { type: "existing"; key: string; url: string }
    | { type: "new"; file: File; url: string };

  const [coverItems, setCoverItems] = React.useState<CoverItem[]>(() => {
    const keys = initial.coverKeys || [];
    const urls = initial.signedCoverUrls || [];
    return keys.map((k, i) => ({ type: "existing", key: k, url: urls[i] || '' }));
  });
  const [coversBaseline, setCoversBaseline] = React.useState<{ keys: string[]; urls: string[] }>(() => ({
    keys: initial.coverKeys || [],
    urls: (initial.signedCoverUrls || []).slice(),
  }));
  const [saving, setSaving] = React.useState(false);

  const urlLike = (s: string) => !s || /^https?:\/\//i.test(s);

  function getAllowedSizesForPlatform(platform: "GB" | "GBC" | "GBA" | "NDS") {
    if (platform === "GB" || platform === "GBC") return [{ w: 160, h: 144 }];
    if (platform === "GBA") return [{ w: 240, h: 160 }];
    return [{ w: 256, h: 192 }, { w: 256, h: 384 }];
  }

  async function validateImageDimensions(file: File, allowed: { w: number; h: number }[]) {
    return new Promise<boolean>((resolve) => {
      const img = document.createElement("img");
      const url = URL.createObjectURL(file);
      img.onload = () => {
        const ok = allowed.some((s) => img.naturalWidth === s.w && img.naturalHeight === s.h);
        URL.revokeObjectURL(url);
        resolve(ok);
      };
      img.onerror = () => {
        URL.revokeObjectURL(url);
        resolve(false);
      };
      img.src = url;
    });
  }

  const platformEntry = React.useMemo(() => baseRoms.find(r => r.id === baseRom), [baseRom]);
  const allowedSizes = platformEntry ? getAllowedSizesForPlatform(platformEntry.platform) : [];
  const tutorialInfo = React.useMemo(() => getScreenshotTutorial(platformEntry?.platform), [platformEntry]);
  const overLimit = coverItems.length > MAX_COVERS;

  // Change detection helpers
  const arraysEqual = (a: string[], b: string[]) => a.length === b.length && a.every((v, i) => v === b[i]);
  const tagsChanged = !arraysEqual(tags, baseline.tags);
  const titleChanged = title !== baseline.title;
  const summaryChanged = summary !== baseline.summary;
  const descriptionChanged = description !== baseline.description;
  const languageChanged = language !== baseline.language;
  const completionStatusChanged = completionStatus !== baseline.completionStatus;
  const boxArtChanged = boxArt !== baseline.boxArt;
  const discordChanged = discord !== baseline.discord;
  const twitterChanged = twitter !== baseline.twitter;
  const pokeChanged = pokecommunity !== baseline.pokecommunity;
  const githubChanged = github !== baseline.github;
  const contentChanged = titleChanged || summaryChanged || descriptionChanged || languageChanged || completionStatusChanged || boxArtChanged || tagsChanged || discordChanged || twitterChanged || pokeChanged || githubChanged;

  const newItemsCount = coverItems.filter((i) => i.type === "new").length;
  const currentExistingKeys = coverItems.filter((i): i is { type: "existing"; key: string; url: string } => i.type === "existing").map((i) => i.key);
  const coversChanged = newItemsCount > 0 || !arraysEqual(currentExistingKeys, coversBaseline.keys);

  function removeAt(index: number) {
    setCoverItems((prev) => prev.filter((_, i) => i !== index));
  }

  function onReorder(oldIndex: number, newIndex: number) {
    setCoverItems((prev) => {
      const copy = prev.slice();
      const [moved] = copy.splice(oldIndex, 1);
      copy.splice(newIndex, 0, moved);
      return copy;
    });
  }

  function onAddFiles(files: File[]) {
    const platform = platformEntry?.platform;
    const sizes = platform ? getAllowedSizesForPlatform(platform) : [];
    const doValidate = async () => {
      const accepted: CoverItem[] = [];
      for (const f of files) {
        if (sizes.length === 0) {
          accepted.push({ type: "new", file: f, url: URL.createObjectURL(f) });
          continue;
        }
        const ok = await validateImageDimensions(f, sizes);
        if (ok) {
          accepted.push({ type: "new", file: f, url: URL.createObjectURL(f) });
        }
      }
      setCoverItems((prev) => [...prev, ...accepted]);
    };
    void doValidate();
  }

  async function onSaveMeta() {
    setSaving(true);
    try {
      const social = discord || twitter || pokecommunity || github ? { discord: discord || undefined, twitter: twitter || undefined, pokecommunity: pokecommunity || undefined, github: github || undefined } : null;
      const updateArgs: any = { slug };
      if (titleChanged) updateArgs.title = title.trim();
      if (summaryChanged) updateArgs.summary = summary.trim();
      if (descriptionChanged) updateArgs.description = description.trim();
      if (languageChanged) updateArgs.language = language;
      if (completionStatusChanged) updateArgs.completion_status = completionStatus;
      if (boxArtChanged) updateArgs.box_art = boxArt ? boxArt.trim() : null;
      if (tagsChanged) updateArgs.tags = tags.slice();
      if (discordChanged || twitterChanged || pokeChanged || githubChanged) updateArgs.social_links = social; // may be null to clear

      const { ok, error } = await updateHack(updateArgs);
      if (!ok) throw new Error(error || "Save failed");
      // Update baseline on success to clear modified indicators
      setBaseline({
        title,
        summary,
        description,
        language,
        completionStatus,
        boxArt,
        tags: tags.slice(),
        discord,
        twitter,
        pokecommunity,
        github,
      });
    } catch (e: any) {
      alert(e.message || "Save failed");
    } finally {
      setSaving(false);
    }
  }

  async function onSaveCovers() {
    setSaving(true);
    try {
      // Upload any new files and build final key order
      const keys: string[] = [];
      for (let i = 0; i < coverItems.length; i++) {
        const item = coverItems[i];
        if (item.type === "existing") {
          keys.push(item.key);
        } else {
          const ext = item.file.name.split('.').pop();
          const path = `${slug}/${Date.now()}-${i}.${ext}`;
          const presigned = await presignCoverUpload({ slug, objectKey: path });
          if (!presigned.ok) throw new Error(presigned.error || 'Failed to presign cover upload');
          await fetch(presigned.presignedUrl, { method: 'PUT', body: item.file, headers: { 'Content-Type': item.file.type || 'image/jpeg' } });
          keys.push(path);
        }
      }
      // Persist cover ordering/rows first
      const saved = await saveHackCovers({ slug, coverUrls: keys });
      if (!saved.ok) throw new Error(saved.error || 'Failed to save covers');
      // Transform any new items into existing with their new keys
      setCoverItems((prev) => prev.map((item, i) => item.type === "existing" ? item : { type: "existing", key: keys[i], url: item.url }));
      // Update covers baseline to newly saved order/keys and keep current preview URLs
      setCoversBaseline({ keys, urls: coverItems.map((c) => c.url) });
    } catch (e: any) {
      alert(e.message || "Failed to save covers");
    } finally {
      setSaving(false);
    }
  }

  const summaryLimit = 120;
  const summaryTooLong = summary.length > summaryLimit;
  const contentHasErrors = summaryTooLong || (!!boxArt && !urlLike(boxArt)) || !completionStatus;

  return (
    <div className="mt-6 flex flex-col gap-6 lg:grid lg:grid-cols-[minmax(0,1fr)_360px]">
      <div className="space-y-6">
        <div className="card-simple p-5">
            <div className="flex items-center justify-between">
              <h2 className="text-xl font-semibold tracking-tight">Content</h2>
              <div className="flex items-center gap-3">
              {contentChanged && (
                <button
                  type="button"
                  onClick={() => {
                    setTitle(baseline.title);
                    setSummary(baseline.summary);
                    setDescription(baseline.description);
                    setLanguage(baseline.language);
                    setCompletionStatus(baseline.completionStatus);
                    setBoxArt(baseline.boxArt);
                    setTags(baseline.tags.slice());
                    setDiscord(baseline.discord);
                    setTwitter(baseline.twitter);
                    setPokecommunity(baseline.pokecommunity);
                    setGithub(baseline.github);
                  }}
                  className="inline-flex items-center underline underline-offset-2 text-[12px] font-semibold cursor-pointer"
                >
                  Revert all
                </button>
              )}
              <button onClick={onSaveMeta} disabled={saving || !contentChanged || contentHasErrors} className="shine-wrap btn-premium h-8 min-w-[6rem] text-sm font-semibold dark:disabled:opacity-70 disabled:cursor-not-allowed disabled:[box-shadow:0_0_0_1px_var(--border)]">
                <span>{saving ? "Saving…" : "Save Content/Details"}</span>
              </button>
            </div>
          </div>
          {!completionStatus && (
            <div className="mt-4 rounded-md border border-amber-500/50 bg-amber-500/10 p-3 text-sm text-amber-900 dark:text-amber-100">
              <div className="flex items-start gap-2">
                <div className="flex items-center justify-center w-5 h-5 shrink-0 mt-0.5">
                  <div className="inline-block h-2 w-2 rounded-full bg-amber-400" />
                </div>
                <div className="flex flex-col gap-1">
                  <p className="font-semibold">Missing Completion Status</p>
                  <p className="text-xs text-amber-800 dark:text-amber-200">
                    This is a new required field. Please select a completion status in the Details section to save your changes.
                  </p>
                </div>
              </div>
            </div>
          )}
          <div className="mt-4 grid gap-4">
            <div className="grid gap-2">
              <div className="flex items-center justify-between">
                <label className="text-sm text-foreground/80">Title</label>
                {titleChanged && (
                  <div className="flex items-center gap-2 text-[11px] text-foreground/70">
                    <span>Modified</span>
                    <button type="button" onClick={() => setTitle(baseline.title)} className="inline-flex items-center underline underline-offset-2 text-[11px] cursor-pointer">Revert</button>
                  </div>
                )}
              </div>
              <input value={title} onChange={(e) => setTitle(e.target.value)} className={`h-11 rounded-md px-3 text-sm ring-1 ring-inset focus:outline-none focus:ring-2 ${titleChanged ? 'ring-[var(--ring)] bg-[var(--surface-2)]' : 'bg-[var(--surface-2)] ring-[var(--border)]'}`} />
            </div>
            <div className="grid gap-1">
              <div className="flex items-center justify-between">
                <label className="text-sm text-foreground/80">Summary</label>
                <div className="flex items-center gap-2">
                  {summaryChanged && (
                    <>
                      <span className="text-[11px] text-foreground/70 ml-2">Modified</span>
                      <button type="button" onClick={() => setSummary(baseline.summary)} className="inline-flex items-center underline underline-offset-2 text-[11px] cursor-pointer">Revert</button>
                    </>
                  )}
                </div>
              </div>
              <div className="relative w-full">
                <input
                  value={summary}
                  onChange={(e) => setSummary(e.target.value)}
                  className={`w-full h-11 rounded-md px-3 text-sm ring-1 ring-inset focus:outline-none focus:ring-2 pr-16 ${summary.length > summaryLimit ? "ring-red-600/40 bg-red-500/10 dark:ring-red-400/40 dark:bg-red-950/20" : summaryChanged ? 'ring-[var(--ring)] bg-[var(--surface-2)]' : 'bg-[var(--surface-2)] ring-[var(--border)]'}`}
                />
                <span className={`absolute right-3 top-1/2 -translate-y-1/2 text-[11px] ${summary.length > summaryLimit ? "text-red-300" : "text-foreground/60"}`}>
                  {summary.length}/{summaryLimit}
                </span>
              </div>
            </div>
            <div className="grid gap-2">
              <div className="flex items-center justify-between">
                <label className="text-sm text-foreground/80">Description</label>
                <div className="flex items-center gap-1 text-xs">
                  <button type="button" onClick={() => setShowMdPreview(false)} className={`px-2 py-1 rounded ${!showMdPreview ? "bg-[var(--surface-2)] ring-1 ring-[var(--border)]" : "text-foreground/70"}`}>Write</button>
                  <button type="button" onClick={() => setShowMdPreview(true)} className={`px-2 py-1 rounded ${showMdPreview ? "bg-[var(--surface-2)] ring-1 ring-[var(--border)]" : "text-foreground/70"}`}>Preview</button>
                  {descriptionChanged && (
                    <div className="flex items-center gap-2 ml-2">
                      <span className="text-[11px] text-foreground/70">Modified</span>
                      <button type="button" onClick={() => setDescription(baseline.description)} className="inline-flex items-center underline underline-offset-2 text-[11px] cursor-pointer">Revert</button>
                    </div>
                  )}
                </div>
              </div>
              {!showMdPreview ? (
                <textarea
                  rows={14}
                  value={description}
                  onChange={(e) => setDescription(e.target.value)}
                  placeholder="Supports Markdown"
                  className={`rounded-md px-3 py-2 min-h-[14rem] text-sm ring-1 ring-inset focus:outline-none focus:ring-2 ${descriptionChanged ? 'ring-[var(--ring)] bg-[var(--surface-2)]' : 'bg-[var(--surface-2)] ring-[var(--border)]'}`}
                />
              ) : (
                <div className={`prose max-w-none rounded-md min-h-[14rem] px-3 py-2 ring-1 ring-inset ${descriptionChanged ? 'ring-[var(--ring)] bg-[var(--surface-2)]' : 'bg-[var(--surface-2)] ring-[var(--border)]'} ${description ? "" : "text-foreground/60 text-sm"}`}>
                  <Markdown headingLevelOffset={1}>{description || "Nothing to preview yet."}</Markdown>
                </div>
              )}
            </div>

            <div className="grid gap-2">
              <div className="flex items-center justify-between">
                <label className="text-sm text-foreground/80">Tags</label>
                {tagsChanged && (
                  <div className="flex items-center gap-2 text-[11px] text-foreground/70">
                    <span>Modified</span>
                    <button type="button" onClick={() => setTags(baseline.tags.slice())} className="inline-flex items-center underline underline-offset-2 text-[11px] cursor-pointer">Revert</button>
                  </div>
                )}
              </div>
              <div className={`rounded-md ring-1 ring-inset ${tagsChanged ? 'ring-[var(--ring)] bg-[var(--surface-2)]' : 'ring-transparent'} p-1`}>
                <TagSelector value={tags} onChange={setTags} />
              </div>
            </div>
          </div>
        </div>

        <div className="card p-5">
            <div className="flex items-center justify-between">
              <h2 className="text-xl font-semibold tracking-tight">Screenshots</h2>
              <div className="flex items-center gap-2">
                {coversChanged && (
                  <button type="button" onClick={() => setCoverItems(coversBaseline.keys.map((k, i) => ({ type: 'existing' as const, key: k, url: coversBaseline.urls[i] || '' })))} className="inline-flex h-8 items-center justify-center rounded-md border border-[var(--border)] bg-[var(--surface-2)] px-3 text-[12px] cursor-pointer">
                    Revert
                  </button>
                )}
                <button onClick={onSaveCovers} disabled={saving || !coversChanged || overLimit} className="inline-flex shine-wrap btn-premium h-8 min-w-[6rem] text-sm font-semibold dark:disabled:opacity-70 disabled:cursor-not-allowed disabled:[box-shadow:0_0_0_1px_var(--border)]">
                  <span>{saving ? "Saving…" : "Save images"}</span>
                </button>
              </div>
            </div>
          <div className="mt-4 grid gap-4">
            {allowedSizes.length > 0 && (
              <p className="text-xs text-foreground/60">Allowed sizes: {allowedSizes.map((s) => `${s.w}x${s.h}`).join(", ")}</p>
            )}
            {tutorialInfo && (
              <p className="text-xs text-foreground/60">
                Need help taking screenshots? Watch our{" "}
                <a
                  href={tutorialInfo.url}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="inline-flex items-center gap-1 underline underline-offset-2 hover:text-foreground/80 transition-colors"
                >
                  {tutorialInfo.emulatorName} tutorial
                  <FiExternalLink className="h-3 w-3" />
                </a>
              </p>
            )}
            <input
              type="file"
              multiple
              accept="image/*"
              onChange={(e) => onAddFiles(Array.from(e.target.files || []))}
              className="w-full rounded-md bg-[var(--surface-2)] px-3 py-2 text-sm ring-1 ring-inset ring-[var(--border)] focus:outline-none"
            />

            {coverItems.length === 0 ? (
              <p className="text-sm text-foreground/70">No screenshots yet.</p>
            ) : (
              <SortableCovers
                items={coverItems.map((item, i) => ({
                  id: item.type === 'existing' ? `e:${(item as any).key}` : `n:${(item as any).file.name}-${i}`,
                  url: item.url,
                  filename: item.type === 'existing' ? item.key.split('/').pop() || `Cover ${i+1}` : (item as any).file.name,
                  isNew: item.type === 'new'
                }))}
                onReorder={onReorder}
                onRemove={removeAt}
              />
            )}

            <div className="text-xs text-foreground/60 flex justify-between">
              <p>Images: <span className={overLimit ? "text-red-300 font-bold" : "text-foreground/60"}>{coverItems.length}</span>/{MAX_COVERS}</p>
              {overLimit && <p className="text-red-300/80 italic">Remove some to save.</p>}
            </div>
          </div>
        </div>
      </div>

      <aside className="space-y-6 self-start w-full lg:w-auto">
        <div className="card p-5">
          <h3 className="text-[15px] font-semibold tracking-tight">Details</h3>
          <div className="mt-3 grid gap-3 text-sm">
            <div className="grid gap-2">
              <label className="text-sm text-foreground/80">Base ROM</label>
              <p className="flex items-center h-11 rounded-md bg-[var(--surface-2)] px-3 text-sm ring-1 ring-inset ring-[var(--border)] focus:outline-none focus:ring-2 focus:ring-[var(--ring)] text-foreground/60 select-none cursor-not-allowed">
                {baseRoms.find(r => r.id === baseRom)?.name || baseRom}
              </p>
            </div>
            <div className="grid gap-2">
              <div className="flex items-center justify-between">
                <label className="text-sm text-foreground/80">Language</label>
                {languageChanged && (
                  <div className="ml-auto flex items-center gap-2 text-[11px] text-foreground/70">
                    <span>Modified</span>
                    <button type="button" onClick={() => setLanguage(baseline.language)} className="inline-flex items-center underline underline-offset-2 text-[11px] cursor-pointer">Revert</button>
                  </div>
                )}
              </div>
              <Select
                value={language}
                onChange={setLanguage}
                className={languageChanged ? 'ring-[var(--ring)]' : ''}
                options={['English','Spanish','French','German','Italian','Portuguese','Japanese','Chinese','Korean','Other'].map(l => ({
                  value: l,
                  label: l,
                }))}
              />
            </div>
            <div className="grid gap-2">
              <div className="flex items-center justify-between">
                <label className={`text-sm ${!completionStatus ? 'text-red-500 font-semibold' : 'text-foreground/80'}`}>
                  Completion Status <span className="text-red-500">*</span>
                  {!completionStatus && <span className="ml-2 text-xs font-normal text-red-500/80">(Required)</span>}
                </label>
                {completionStatusChanged && (
                  <div className="ml-auto flex items-center gap-2 text-[11px] text-foreground/70">
                    <span>Modified</span>
                    <button type="button" onClick={() => setCompletionStatus(baseline.completionStatus)} className="inline-flex items-center underline underline-offset-2 text-[11px] cursor-pointer">Revert</button>
                  </div>
                )}
              </div>
              <Select
                value={completionStatus || ""}
                onChange={(value) => setCompletionStatus(value as Database["public"]["Enums"]["Completion Status"] | null)}
                placeholder="Select completion status"
                className={!completionStatus ? 'ring-2 ring-red-500/60 bg-red-500/10 dark:ring-red-400/60 dark:bg-red-950/20' : completionStatusChanged ? 'ring-[var(--ring)]' : ''}
                options={['Complete','Demo','Alpha','Beta'].map(s => ({
                  value: s,
                  label: s,
                }))}
              />
              {!completionStatus && (
                <p className="text-xs text-red-500/80 dark:text-red-400/80">
                  This is a new required field. Please select a completion status to save your changes.
                </p>
              )}
            </div>
            <div className="grid gap-2">
              <label className="text-sm text-foreground/80">Current version</label>
              <p className="flex items-center h-11 rounded-md bg-[var(--surface-2)] px-3 text-sm ring-1 ring-inset ring-[var(--border)] focus:outline-none focus:ring-2 focus:ring-[var(--ring)] text-foreground/60 select-none cursor-not-allowed">
                {version}
              </p>
            </div>
            <div className="grid gap-2">
              <label className="text-sm text-foreground/80">Box art URL</label>
              <div className="flex items-center justify-between">
                <input value={boxArt} onChange={(e) => setBoxArt(e.target.value)} placeholder="https://..." className={`flex-1 h-11 rounded-md px-3 text-sm ring-1 ring-inset focus:outline-none focus:ring-2 ${boxArt && !urlLike(boxArt) ? "ring-red-600/40 bg-red-500/10 dark:ring-red-400/40 dark:bg-red-950/20" : boxArtChanged ? 'ring-[var(--ring)] bg-[var(--surface-2)]' : 'bg-[var(--surface-2)] ring-[var(--border)]'}`} />
                {boxArtChanged && (
                  <button type="button" onClick={() => setBoxArt(baseline.boxArt)} className="ml-3 text-[11px] underline underline-offset-2 cursor-pointer">Revert</button>
                )}
              </div>
              {boxArt && urlLike(boxArt) && (
                <div className="relative aspect-square w-full max-h-[300px] overflow-hidden rounded ring-1 ring-[var(--border)]">
                  <Image src={boxArt} alt="Box art preview" fill className="object-contain" unoptimized />
                </div>
              )}
            </div>
            <div className="grid gap-2">
              <label className="text-sm text-foreground/80">Social links</label>
              <div className="grid gap-2">
                <div className="flex items-center gap-2">
                  <input value={discord} onChange={(e) => setDiscord(e.target.value)} placeholder="Discord invite URL" className={`flex-1 h-11 rounded-md px-3 text-sm ring-1 ring-inset focus:outline-none focus:ring-2 ${discord && !urlLike(discord) ? "ring-red-600/40 bg-red-500/10 dark:ring-red-400/40 dark:bg-red-950/20" : discordChanged ? 'ring-[var(--ring)] bg-[var(--surface-2)]' : 'bg-[var(--surface-2)] ring-[var(--border)]'}`} />
                  {discordChanged && <button type="button" onClick={() => setDiscord(baseline.discord)} className="text-[11px] underline underline-offset-2 cursor-pointer">Revert</button>}
                </div>
                <div className="flex items-center gap-2">
                  <input value={twitter} onChange={(e) => setTwitter(e.target.value)} placeholder="Twitter/X profile URL" className={`flex-1 h-11 rounded-md px-3 text-sm ring-1 ring-inset focus:outline-none focus:ring-2 ${twitter && !urlLike(twitter) ? "ring-red-600/40 bg-red-500/10 dark:ring-red-400/40 dark:bg-red-950/20" : twitterChanged ? 'ring-[var(--ring)] bg-[var(--surface-2)]' : 'bg-[var(--surface-2)] ring-[var(--border)]'}`} />
                  {twitterChanged && <button type="button" onClick={() => setTwitter(baseline.twitter)} className="text-[11px] underline underline-offset-2 cursor-pointer">Revert</button>}
                </div>
                <div className="flex items-center gap-2">
                  <input value={pokecommunity} onChange={(e) => setPokecommunity(e.target.value)} placeholder="PokeCommunity thread URL" className={`flex-1 h-11 rounded-md px-3 text-sm ring-1 ring-inset focus:outline-none focus:ring-2 ${pokecommunity && !urlLike(pokecommunity) ? "ring-red-600/40 bg-red-500/10 dark:ring-red-400/40 dark:bg-red-950/20" : pokeChanged ? 'ring-[var(--ring)] bg-[var(--surface-2)]' : 'bg-[var(--surface-2)] ring-[var(--border)]'}`} />
                  {pokeChanged && <button type="button" onClick={() => setPokecommunity(baseline.pokecommunity)} className="text-[11px] underline underline-offset-2 cursor-pointer">Revert</button>}
                </div>
                <div className="flex items-center gap-2">
                  <input value={github} onChange={(e) => setGithub(e.target.value)} placeholder="GitHub repository URL" className={`flex-1 h-11 rounded-md px-3 text-sm ring-1 ring-inset focus:outline-none focus:ring-2 ${github && !urlLike(github) ? "ring-red-600/40 bg-red-500/10 dark:ring-red-400/40 dark:bg-red-950/20" : githubChanged ? 'ring-[var(--ring)] bg-[var(--surface-2)]' : 'bg-[var(--surface-2)] ring-[var(--border)]'}`} />
                  {githubChanged && <button type="button" onClick={() => setGithub(baseline.github)} className="text-[11px] underline underline-offset-2 cursor-pointer">Revert</button>}
                </div>
              </div>
            </div>
          </div>
        </div>
      </aside>
    </div>
  );
}


