import { useCallback, useEffect, useState } from "react";
import {
  Loader2,
  AlertTriangle,
  Save,
  Check,
  TrendingUp,
  Coins,
  Package,
  Gift,
  Brain,
  Shield,
  Terminal,
  RotateCcw,
  Server,
  X,
} from "lucide-react";
import { cn } from "../lib/utils";
import {
  useSettings,
  type GameSettings,
  type GuildSettings,
  type SettingsMeta,
} from "../lib/useSettings";

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

type SettingsSection =
  | "guild"
  | "leveling"
  | "economy"
  | "inventory"
  | "lootdrop"
  | "trivia"
  | "moderation"
  | "commands";

const sections: {
  key: SettingsSection;
  label: string;
  icon: React.ComponentType<{ className?: string }>;
}[] = [
  { key: "guild", label: "Guild", icon: Server },
  { key: "leveling", label: "Leveling", icon: TrendingUp },
  { key: "economy", label: "Economy", icon: Coins },
  { key: "inventory", label: "Inventory", icon: Package },
  { key: "lootdrop", label: "Lootdrops", icon: Gift },
  { key: "trivia", label: "Trivia", icon: Brain },
  { key: "moderation", label: "Moderation", icon: Shield },
  { key: "commands", label: "Commands", icon: Terminal },
];

function formatMs(ms: number): string {
  if (ms >= 86_400_000) return `${ms / 86_400_000}h`;
  if (ms >= 60_000) return `${ms / 60_000} min`;
  return `${ms / 1_000}s`;
}

// ---------------------------------------------------------------------------
// Reusable field components
// ---------------------------------------------------------------------------

function Field({
  label,
  hint,
  children,
}: {
  label: string;
  hint?: string;
  children: React.ReactNode;
}) {
  return (
    <div className="space-y-1.5">
      <label className="block text-xs font-semibold text-text-secondary">
        {label}
      </label>
      {children}
      {hint && <p className="text-[11px] text-text-tertiary">{hint}</p>}
    </div>
  );
}

function NumberInput({
  value,
  onChange,
  min,
  max,
  step,
  className,
}: {
  value: number;
  onChange: (v: number) => void;
  min?: number;
  max?: number;
  step?: number;
  className?: string;
}) {
  return (
    <input
      type="number"
      value={value}
      onChange={(e) => onChange(Number(e.target.value))}
      min={min}
      max={max}
      step={step}
      className={cn(
        "w-full bg-input border border-border rounded-md px-3 py-2 text-sm font-mono text-foreground",
        "focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
        "transition-colors",
        className
      )}
    />
  );
}

function StringInput({
  value,
  onChange,
  placeholder,
  className,
}: {
  value: string;
  onChange: (v: string) => void;
  placeholder?: string;
  className?: string;
}) {
  return (
    <input
      type="text"
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder}
      className={cn(
        "w-full bg-input border border-border rounded-md px-3 py-2 text-sm font-mono text-foreground",
        "focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
        "transition-colors",
        className
      )}
    />
  );
}

function TextArea({
  value,
  onChange,
  placeholder,
  rows = 3,
}: {
  value: string;
  onChange: (v: string) => void;
  placeholder?: string;
  rows?: number;
}) {
  return (
    <textarea
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder}
      rows={rows}
      className={cn(
        "w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground resize-y",
        "focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
        "transition-colors"
      )}
    />
  );
}

function Toggle({
  checked,
  onChange,
}: {
  checked: boolean;
  onChange: (v: boolean) => void;
}) {
  return (
    <button
      type="button"
      role="switch"
      aria-checked={checked}
      onClick={() => onChange(!checked)}
      className={cn(
        "relative inline-flex h-6 w-11 items-center rounded-full transition-colors",
        checked ? "bg-primary" : "bg-raised"
      )}
    >
      <span
        className={cn(
          "inline-block h-4 w-4 rounded-full bg-white transition-transform",
          checked ? "translate-x-6" : "translate-x-1"
        )}
      />
    </button>
  );
}

function SelectInput({
  value,
  onChange,
  options,
}: {
  value: string;
  onChange: (v: string) => void;
  options: { value: string; label: string }[];
}) {
  return (
    <select
      value={value}
      onChange={(e) => onChange(e.target.value)}
      className={cn(
        "w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
        "focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
        "transition-colors"
      )}
    >
      {options.map((o) => (
        <option key={o.value} value={o.value}>
          {o.label}
        </option>
      ))}
    </select>
  );
}

/** Role picker dropdown — selects a single role ID */
function RolePicker({
  value,
  onChange,
  roles,
  placeholder = "Select a role…",
}: {
  value: string | undefined;
  onChange: (v: string | undefined) => void;
  roles: SettingsMeta["roles"];
  placeholder?: string;
}) {
  return (
    <select
      value={value ?? ""}
      onChange={(e) => onChange(e.target.value || undefined)}
      className={cn(
        "w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
        "focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
        "transition-colors"
      )}
    >
      <option value="">{placeholder}</option>
      {roles.map((r) => (
        <option key={r.id} value={r.id}>
          {r.name}
        </option>
      ))}
    </select>
  );
}

/** Channel picker dropdown — selects a single channel ID (text channels only) */
function ChannelPicker({
  value,
  onChange,
  channels,
  placeholder = "Select a channel…",
}: {
  value: string | undefined;
  onChange: (v: string | undefined) => void;
  channels: SettingsMeta["channels"];
  placeholder?: string;
}) {
  // type 0 = text channel
  const textChannels = channels.filter((c) => c.type === 0);
  return (
    <select
      value={value ?? ""}
      onChange={(e) => onChange(e.target.value || undefined)}
      className={cn(
        "w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
        "focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
        "transition-colors"
      )}
    >
      <option value="">{placeholder}</option>
      {textChannels.map((c) => (
        <option key={c.id} value={c.id}>
          #{c.name}
        </option>
      ))}
    </select>
  );
}

/** Multi-select role picker for color roles */
function MultiRolePicker({
  selected,
  onChange,
  roles,
}: {
  selected: string[];
  onChange: (v: string[]) => void;
  roles: SettingsMeta["roles"];
}) {
  const available = roles.filter((r) => !selected.includes(r.id));
  const selectedRoles = selected
    .map((id) => roles.find((r) => r.id === id))
    .filter(Boolean) as SettingsMeta["roles"];

  return (
    <div className="space-y-2">
      {selectedRoles.length > 0 && (
        <div className="flex flex-wrap gap-2">
          {selectedRoles.map((r) => (
            <span
              key={r.id}
              className="inline-flex items-center gap-1.5 bg-primary/15 border border-primary/30 rounded-full px-3 py-1 text-xs font-medium"
            >
              <span
                className="w-2.5 h-2.5 rounded-full"
                style={{ backgroundColor: r.color !== "#000000" ? r.color : "#6B7280" }}
              />
              {r.name}
              <button
                type="button"
                onClick={() => onChange(selected.filter((id) => id !== r.id))}
                className="ml-0.5 text-text-tertiary hover:text-destructive transition-colors"
              >
                <X className="w-3 h-3" />
              </button>
            </span>
          ))}
        </div>
      )}
      {available.length > 0 && (
        <select
          value=""
          onChange={(e) => {
            if (e.target.value) onChange([...selected, e.target.value]);
          }}
          className={cn(
            "w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
            "focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
            "transition-colors"
          )}
        >
          <option value="">Add a color role…</option>
          {available.map((r) => (
            <option key={r.id} value={r.id}>
              {r.name}
            </option>
          ))}
        </select>
      )}
    </div>
  );
}

/** OpenTDB category IDs */
const TRIVIA_CATEGORIES: { id: number; name: string }[] = [
  { id: 9, name: "General Knowledge" },
  { id: 10, name: "Books" },
  { id: 11, name: "Film" },
  { id: 12, name: "Music" },
  { id: 13, name: "Musicals & Theatre" },
  { id: 14, name: "Television" },
  { id: 15, name: "Video Games" },
  { id: 16, name: "Board Games" },
  { id: 17, name: "Science & Nature" },
  { id: 18, name: "Computers" },
  { id: 19, name: "Mathematics" },
  { id: 20, name: "Mythology" },
  { id: 21, name: "Sports" },
  { id: 22, name: "Geography" },
  { id: 23, name: "History" },
  { id: 24, name: "Politics" },
  { id: 25, name: "Art" },
  { id: 26, name: "Celebrities" },
  { id: 27, name: "Animals" },
  { id: 28, name: "Vehicles" },
  { id: 29, name: "Comics" },
  { id: 30, name: "Gadgets" },
  { id: 31, name: "Anime & Manga" },
  { id: 32, name: "Cartoons & Animations" },
];

function CategoryPicker({
  selected,
  onChange,
}: {
  selected: number[];
  onChange: (v: number[]) => void;
}) {
  const available = TRIVIA_CATEGORIES.filter((c) => !selected.includes(c.id));
  const selectedCats = selected
    .map((id) => TRIVIA_CATEGORIES.find((c) => c.id === id))
    .filter(Boolean) as typeof TRIVIA_CATEGORIES;

  return (
    <div className="space-y-2">
      {selectedCats.length > 0 && (
        <div className="flex flex-wrap gap-2">
          {selectedCats.map((c) => (
            <span
              key={c.id}
              className="inline-flex items-center gap-1.5 bg-info/15 border border-info/30 rounded-full px-3 py-1 text-xs font-medium"
            >
              {c.name}
              <button
                type="button"
                onClick={() => onChange(selected.filter((id) => id !== c.id))}
                className="ml-0.5 text-text-tertiary hover:text-destructive transition-colors"
              >
                <X className="w-3 h-3" />
              </button>
            </span>
          ))}
        </div>
      )}
      {available.length > 0 && (
        <select
          value=""
          onChange={(e) => {
            const id = Number(e.target.value);
            if (id) onChange([...selected, id]);
          }}
          className={cn(
            "w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
            "focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
            "transition-colors"
          )}
        >
          <option value="">Add a category…</option>
          {available.map((c) => (
            <option key={c.id} value={c.id}>
              {c.name}
            </option>
          ))}
        </select>
      )}
    </div>
  );
}

/** Key-value editor for feature override flags */
function FeatureOverridesEditor({
  value,
  onChange,
}: {
  value: Record<string, boolean>;
  onChange: (v: Record<string, boolean>) => void;
}) {
  const [newKey, setNewKey] = useState("");
  const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));

  const addFlag = () => {
    const key = newKey.trim().toLowerCase().replace(/\s+/g, "_");
    if (!key || key in value) return;
    onChange({ ...value, [key]: true });
    setNewKey("");
  };

  return (
    <div className="space-y-3">
      {entries.length > 0 && (
        <div className="space-y-2">
          {entries.map(([key, enabled]) => (
            <div
              key={key}
              className="flex items-center justify-between py-1.5"
            >
              <span
                className={cn(
                  "text-sm font-mono",
                  enabled ? "text-foreground" : "text-text-disabled"
                )}
              >
                {key}
              </span>
              <div className="flex items-center gap-3">
                <Toggle
                  checked={enabled}
                  onChange={(v) => onChange({ ...value, [key]: v })}
                />
                <button
                  type="button"
                  onClick={() => {
                    const { [key]: _, ...rest } = value;
                    onChange(rest);
                  }}
                  className="text-text-tertiary hover:text-destructive transition-colors"
                >
                  <X className="w-3.5 h-3.5" />
                </button>
              </div>
            </div>
          ))}
        </div>
      )}
      <div className="flex gap-2">
        <StringInput
          value={newKey}
          onChange={setNewKey}
          placeholder="feature_name"
          className="flex-1"
        />
        <button
          type="button"
          onClick={addFlag}
          disabled={!newKey.trim()}
          className={cn(
            "rounded-md px-4 py-2 text-sm font-medium transition-colors",
            newKey.trim()
              ? "bg-primary/15 text-primary hover:bg-primary/25 border border-primary/30"
              : "bg-raised text-text-disabled cursor-not-allowed"
          )}
        >
          Add
        </button>
      </div>
    </div>
  );
}

function SectionCard({
  title,
  icon: Icon,
  children,
}: {
  title: string;
  icon: React.ComponentType<{ className?: string }>;
  children: React.ReactNode;
}) {
  return (
    <div className="bg-card rounded-lg border border-border">
      <div className="flex items-center gap-2.5 px-6 py-4 border-b border-border">
        <Icon className="w-4 h-4 text-primary" />
        <h3 className="text-sm font-semibold">{title}</h3>
      </div>
      <div className="px-6 py-5 space-y-5">{children}</div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Section editors
// ---------------------------------------------------------------------------

function GuildSection({
  data,
  onChange,
  meta,
}: {
  data: GuildSettings;
  onChange: (d: GuildSettings) => void;
  meta: SettingsMeta | null;
}) {
  const roles = meta?.roles ?? [];
  const channels = meta?.channels ?? [];

  return (
    <div className="space-y-6">
      <SectionCard title="Roles" icon={Server}>
        <div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
          <Field label="Student Role" hint="Assigned to verified students">
            <RolePicker
              value={data.studentRoleId}
              onChange={(v) => onChange({ ...data, studentRoleId: v })}
              roles={roles}
            />
          </Field>
          <Field label="Visitor Role" hint="Assigned to unverified members">
            <RolePicker
              value={data.visitorRoleId}
              onChange={(v) => onChange({ ...data, visitorRoleId: v })}
              roles={roles}
            />
          </Field>
        </div>
        <Field label="Color Roles" hint="Roles users can self-assign for name color">
          <MultiRolePicker
            selected={data.colorRoleIds ?? []}
            onChange={(v) => onChange({ ...data, colorRoleIds: v })}
            roles={roles}
          />
        </Field>
      </SectionCard>

      <SectionCard title="Channels" icon={Server}>
        <div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
          <Field label="Welcome Channel">
            <ChannelPicker
              value={data.welcomeChannelId}
              onChange={(v) => onChange({ ...data, welcomeChannelId: v })}
              channels={channels}
            />
          </Field>
          <Field label="Feedback Channel">
            <ChannelPicker
              value={data.feedbackChannelId}
              onChange={(v) => onChange({ ...data, feedbackChannelId: v })}
              channels={channels}
            />
          </Field>
          <Field label="Terminal Channel">
            <ChannelPicker
              value={data.terminalChannelId}
              onChange={(v) => onChange({ ...data, terminalChannelId: v })}
              channels={channels}
            />
          </Field>
          <Field label="Moderation Log Channel">
            <ChannelPicker
              value={data.moderationLogChannelId}
              onChange={(v) => onChange({ ...data, moderationLogChannelId: v })}
              channels={channels}
            />
          </Field>
        </div>
      </SectionCard>

      <SectionCard title="Welcome Message" icon={Server}>
        <Field label="Message" hint="Sent when a new member joins. Leave empty to disable.">
          <TextArea
            value={data.welcomeMessage ?? ""}
            onChange={(v) => onChange({ ...data, welcomeMessage: v || undefined })}
            placeholder="Welcome to the academy, {user}!"
            rows={3}
          />
        </Field>
      </SectionCard>

      <SectionCard title="Moderation" icon={Shield}>
        <div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
          <Field label="DM on Warn" hint="Send a DM to users when they receive a warning">
            <Toggle
              checked={data.moderationDmOnWarn ?? true}
              onChange={(v) => onChange({ ...data, moderationDmOnWarn: v })}
            />
          </Field>
          <Field label="Auto-Timeout Threshold" hint="Warnings before auto-timeout (empty = disabled)">
            <NumberInput
              value={data.moderationAutoTimeoutThreshold ?? 0}
              onChange={(v) =>
                onChange({
                  ...data,
                  moderationAutoTimeoutThreshold: v || undefined,
                })
              }
              min={0}
            />
          </Field>
        </div>
      </SectionCard>

      <SectionCard title="Feature Overrides" icon={Server}>
        <p className="text-xs text-text-tertiary">
          Toggle feature flags for this guild. Add new flags by name.
        </p>
        <FeatureOverridesEditor
          value={data.featureOverrides ?? {}}
          onChange={(v) => onChange({ ...data, featureOverrides: v })}
        />
      </SectionCard>
    </div>
  );
}

function LevelingSection({
  data,
  onChange,
}: {
  data: GameSettings["leveling"];
  onChange: (d: GameSettings["leveling"]) => void;
}) {
  return (
    <SectionCard title="Leveling" icon={TrendingUp}>
      <div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
        <Field label="Base XP" hint="Base XP required for level 2">
          <NumberInput
            value={data.base}
            onChange={(v) => onChange({ ...data, base: v })}
            min={1}
          />
        </Field>
        <Field label="Exponent" hint="XP growth curve exponent">
          <NumberInput
            value={data.exponent}
            onChange={(v) => onChange({ ...data, exponent: v })}
            min={1}
            max={5}
            step={0.1}
          />
        </Field>
      </div>
      <h4 className="text-xs font-semibold text-text-tertiary uppercase tracking-wider pt-2">
        Chat XP
      </h4>
      <div className="grid grid-cols-1 sm:grid-cols-3 gap-5">
        <Field label="Cooldown (ms)" hint={formatMs(data.chat.cooldownMs)}>
          <NumberInput
            value={data.chat.cooldownMs}
            onChange={(v) =>
              onChange({ ...data, chat: { ...data.chat, cooldownMs: v } })
            }
            min={0}
            step={1000}
          />
        </Field>
        <Field label="Min XP">
          <NumberInput
            value={data.chat.minXp}
            onChange={(v) =>
              onChange({ ...data, chat: { ...data.chat, minXp: v } })
            }
            min={0}
          />
        </Field>
        <Field label="Max XP">
          <NumberInput
            value={data.chat.maxXp}
            onChange={(v) =>
              onChange({ ...data, chat: { ...data.chat, maxXp: v } })
            }
            min={0}
          />
        </Field>
      </div>
    </SectionCard>
  );
}

function EconomySection({
  data,
  onChange,
}: {
  data: GameSettings["economy"];
  onChange: (d: GameSettings["economy"]) => void;
}) {
  const setDaily = (patch: Partial<GameSettings["economy"]["daily"]>) =>
    onChange({ ...data, daily: { ...data.daily, ...patch } });
  const setTransfers = (
    patch: Partial<GameSettings["economy"]["transfers"]>
  ) => onChange({ ...data, transfers: { ...data.transfers, ...patch } });
  const setExam = (patch: Partial<GameSettings["economy"]["exam"]>) =>
    onChange({ ...data, exam: { ...data.exam, ...patch } });

  return (
    <SectionCard title="Economy" icon={Coins}>
      <h4 className="text-xs font-semibold text-text-tertiary uppercase tracking-wider">
        Daily Rewards
      </h4>
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5">
        <Field label="Amount (AU)">
          <StringInput
            value={data.daily.amount}
            onChange={(v) => setDaily({ amount: v })}
          />
        </Field>
        <Field label="Streak Bonus">
          <StringInput
            value={data.daily.streakBonus}
            onChange={(v) => setDaily({ streakBonus: v })}
          />
        </Field>
        <Field label="Weekly Bonus">
          <StringInput
            value={data.daily.weeklyBonus}
            onChange={(v) => setDaily({ weeklyBonus: v })}
          />
        </Field>
        <Field label="Cooldown (ms)" hint={formatMs(data.daily.cooldownMs)}>
          <NumberInput
            value={data.daily.cooldownMs}
            onChange={(v) => setDaily({ cooldownMs: v })}
            min={0}
            step={1000}
          />
        </Field>
      </div>

      <h4 className="text-xs font-semibold text-text-tertiary uppercase tracking-wider pt-2">
        Transfers
      </h4>
      <div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
        <Field label="Min Amount">
          <StringInput
            value={data.transfers.minAmount}
            onChange={(v) => setTransfers({ minAmount: v })}
          />
        </Field>
        <Field label="Allow Self-Transfer">
          <Toggle
            checked={data.transfers.allowSelfTransfer}
            onChange={(v) => setTransfers({ allowSelfTransfer: v })}
          />
        </Field>
      </div>

      <h4 className="text-xs font-semibold text-text-tertiary uppercase tracking-wider pt-2">
        Exam
      </h4>
      <div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
        <Field label="Min Multiplier">
          <NumberInput
            value={data.exam.multMin}
            onChange={(v) => setExam({ multMin: v })}
            min={0}
            step={0.1}
          />
        </Field>
        <Field label="Max Multiplier">
          <NumberInput
            value={data.exam.multMax}
            onChange={(v) => setExam({ multMax: v })}
            min={0}
            step={0.1}
          />
        </Field>
      </div>
    </SectionCard>
  );
}

function InventorySection({
  data,
  onChange,
}: {
  data: GameSettings["inventory"];
  onChange: (d: GameSettings["inventory"]) => void;
}) {
  return (
    <SectionCard title="Inventory" icon={Package}>
      <div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
        <Field label="Max Stack Size">
          <StringInput
            value={data.maxStackSize}
            onChange={(v) => onChange({ ...data, maxStackSize: v })}
          />
        </Field>
        <Field label="Max Slots">
          <NumberInput
            value={data.maxSlots}
            onChange={(v) => onChange({ ...data, maxSlots: v })}
            min={1}
          />
        </Field>
      </div>
    </SectionCard>
  );
}

function LootdropSection({
  data,
  onChange,
}: {
  data: GameSettings["lootdrop"];
  onChange: (d: GameSettings["lootdrop"]) => void;
}) {
  const setReward = (patch: Partial<GameSettings["lootdrop"]["reward"]>) =>
    onChange({ ...data, reward: { ...data.reward, ...patch } });

  return (
    <SectionCard title="Lootdrops" icon={Gift}>
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5">
        <Field
          label="Activity Window (ms)"
          hint={formatMs(data.activityWindowMs)}
        >
          <NumberInput
            value={data.activityWindowMs}
            onChange={(v) => onChange({ ...data, activityWindowMs: v })}
            min={0}
            step={1000}
          />
        </Field>
        <Field label="Min Messages">
          <NumberInput
            value={data.minMessages}
            onChange={(v) => onChange({ ...data, minMessages: v })}
            min={1}
          />
        </Field>
        <Field label="Spawn Chance" hint="0.0 – 1.0">
          <NumberInput
            value={data.spawnChance}
            onChange={(v) => onChange({ ...data, spawnChance: v })}
            min={0}
            max={1}
            step={0.01}
          />
        </Field>
        <Field label="Cooldown (ms)" hint={formatMs(data.cooldownMs)}>
          <NumberInput
            value={data.cooldownMs}
            onChange={(v) => onChange({ ...data, cooldownMs: v })}
            min={0}
            step={1000}
          />
        </Field>
      </div>

      <h4 className="text-xs font-semibold text-text-tertiary uppercase tracking-wider pt-2">
        Reward
      </h4>
      <div className="grid grid-cols-1 sm:grid-cols-3 gap-5">
        <Field label="Min Reward">
          <NumberInput
            value={data.reward.min}
            onChange={(v) => setReward({ min: v })}
            min={0}
          />
        </Field>
        <Field label="Max Reward">
          <NumberInput
            value={data.reward.max}
            onChange={(v) => setReward({ max: v })}
            min={0}
          />
        </Field>
        <Field label="Currency">
          <SelectInput
            value={data.reward.currency}
            onChange={(v) => setReward({ currency: v })}
            options={[
              { value: "AU", label: "AU (Astral Units)" },
              { value: "CU", label: "CU (Constellation Units)" },
            ]}
          />
        </Field>
      </div>
    </SectionCard>
  );
}

function TriviaSection({
  data,
  onChange,
}: {
  data: GameSettings["trivia"];
  onChange: (d: GameSettings["trivia"]) => void;
}) {
  return (
    <SectionCard title="Trivia" icon={Brain}>
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5">
        <Field label="Entry Fee (AU)">
          <StringInput
            value={data.entryFee}
            onChange={(v) => onChange({ ...data, entryFee: v })}
          />
        </Field>
        <Field label="Reward Multiplier">
          <NumberInput
            value={data.rewardMultiplier}
            onChange={(v) => onChange({ ...data, rewardMultiplier: v })}
            min={0}
            step={0.1}
          />
        </Field>
        <Field label="Timeout (seconds)">
          <NumberInput
            value={data.timeoutSeconds}
            onChange={(v) => onChange({ ...data, timeoutSeconds: v })}
            min={5}
          />
        </Field>
        <Field label="Cooldown (ms)" hint={formatMs(data.cooldownMs)}>
          <NumberInput
            value={data.cooldownMs}
            onChange={(v) => onChange({ ...data, cooldownMs: v })}
            min={0}
            step={1000}
          />
        </Field>
      </div>
      <div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
        <Field label="Difficulty">
          <SelectInput
            value={data.difficulty}
            onChange={(v) => onChange({ ...data, difficulty: v })}
            options={[
              { value: "random", label: "Random" },
              { value: "easy", label: "Easy" },
              { value: "medium", label: "Medium" },
              { value: "hard", label: "Hard" },
            ]}
          />
        </Field>
      </div>

      <Field
        label="Categories"
        hint="Select which OpenTDB categories to pull from. Leave empty for all categories."
      >
        <CategoryPicker
          selected={data.categories ?? []}
          onChange={(v) => onChange({ ...data, categories: v })}
        />
      </Field>
    </SectionCard>
  );
}

function ModerationSection({
  data,
  onChange,
}: {
  data: GameSettings["moderation"];
  onChange: (d: GameSettings["moderation"]) => void;
}) {
  const setPrune = (patch: Partial<GameSettings["moderation"]["prune"]>) =>
    onChange({ ...data, prune: { ...data.prune, ...patch } });

  return (
    <SectionCard title="Moderation" icon={Shield}>
      <h4 className="text-xs font-semibold text-text-tertiary uppercase tracking-wider">
        Prune
      </h4>
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5">
        <Field label="Max Amount">
          <NumberInput
            value={data.prune.maxAmount}
            onChange={(v) => setPrune({ maxAmount: v })}
            min={1}
          />
        </Field>
        <Field
          label="Confirm Threshold"
          hint="Require confirmation above this"
        >
          <NumberInput
            value={data.prune.confirmThreshold}
            onChange={(v) => setPrune({ confirmThreshold: v })}
            min={1}
          />
        </Field>
        <Field label="Batch Size">
          <NumberInput
            value={data.prune.batchSize}
            onChange={(v) => setPrune({ batchSize: v })}
            min={1}
          />
        </Field>
        <Field
          label="Batch Delay (ms)"
          hint={formatMs(data.prune.batchDelayMs)}
        >
          <NumberInput
            value={data.prune.batchDelayMs}
            onChange={(v) => setPrune({ batchDelayMs: v })}
            min={0}
            step={100}
          />
        </Field>
      </div>
    </SectionCard>
  );
}

function CommandsSection({
  commands,
  onChange,
  meta,
}: {
  commands: GameSettings["commands"];
  meta: SettingsMeta | null;
  onChange: (d: GameSettings["commands"]) => void;
}) {
  const grouped = (meta?.commands ?? []).reduce<
    Record<string, Array<{ name: string; category: string }>>
  >((acc, cmd) => {
    (acc[cmd.category] ??= []).push(cmd);
    return acc;
  }, {});

  const categories = Object.keys(grouped).sort();

  if (categories.length === 0) {
    return (
      <SectionCard title="Commands" icon={Terminal}>
        <p className="text-sm text-text-tertiary">
          No registered commands found. Make sure the bot is online.
        </p>
      </SectionCard>
    );
  }

  return (
    <SectionCard title="Commands" icon={Terminal}>
      <p className="text-xs text-text-tertiary">
        Toggle commands on or off. Disabled commands cannot be used by anyone.
      </p>
      <div className="space-y-6">
        {categories.map((cat) => (
          <div key={cat}>
            <h4 className="text-xs font-semibold text-text-tertiary uppercase tracking-wider mb-3">
              {cat}
            </h4>
            <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-x-6 gap-y-3">
              {grouped[cat]!.map((cmd) => {
                const enabled = commands[cmd.name] !== false;
                return (
                  <div
                    key={cmd.name}
                    className="flex items-center justify-between py-1.5"
                  >
                    <span
                      className={cn(
                        "text-sm font-mono",
                        enabled ? "text-foreground" : "text-text-disabled"
                      )}
                    >
                      /{cmd.name}
                    </span>
                    <Toggle
                      checked={enabled}
                      onChange={(v) =>
                        onChange({ ...commands, [cmd.name]: v })
                      }
                    />
                  </div>
                );
              })}
            </div>
          </div>
        ))}
      </div>
    </SectionCard>
  );
}

// ---------------------------------------------------------------------------
// Default guild settings (used when guild has no config yet)
// ---------------------------------------------------------------------------

const defaultGuildSettings: GuildSettings = {
  guildId: "",
  configured: false,
  colorRoleIds: [],
  moderationDmOnWarn: true,
  featureOverrides: {},
};

// ---------------------------------------------------------------------------
// Main Settings page
// ---------------------------------------------------------------------------

export default function Settings() {
  const {
    settings,
    guildSettings,
    meta,
    loading,
    saving,
    error,
    saveSettings,
    saveGuildSettings,
  } = useSettings();

  const [gameDraft, setGameDraft] = useState<GameSettings | null>(null);
  const [guildDraft, setGuildDraft] = useState<GuildSettings | null>(null);
  const [activeSection, setActiveSection] =
    useState<SettingsSection>("guild");
  const [saveSuccess, setSaveSuccess] = useState(false);

  // Sync drafts when data loads
  useEffect(() => {
    if (settings && !gameDraft) {
      setGameDraft(structuredClone(settings));
    }
  }, [settings, gameDraft]);

  useEffect(() => {
    if (!guildDraft) {
      setGuildDraft(
        guildSettings
          ? structuredClone(guildSettings)
          : { ...defaultGuildSettings, guildId: meta?.guildId ?? "" }
      );
    }
  }, [guildSettings, guildDraft, meta?.guildId]);

  const isGuildTab = activeSection === "guild";

  const gameDirty =
    gameDraft && settings
      ? JSON.stringify(gameDraft) !== JSON.stringify(settings)
      : false;

  const guildDirty =
    guildDraft && guildSettings
      ? JSON.stringify(guildDraft) !== JSON.stringify(guildSettings)
      : guildDraft
      ? JSON.stringify(guildDraft) !==
        JSON.stringify({ ...defaultGuildSettings, guildId: meta?.guildId ?? "" })
      : false;

  const dirty = isGuildTab ? guildDirty : gameDirty;

  const handleSave = useCallback(async () => {
    let ok: boolean;
    if (isGuildTab && guildDraft) {
      ok = await saveGuildSettings(guildDraft);
    } else if (gameDraft) {
      ok = await saveSettings(
        gameDraft as unknown as Record<string, unknown>
      );
    } else {
      return;
    }
    if (ok) {
      setSaveSuccess(true);
      setTimeout(() => setSaveSuccess(false), 2000);
      // Reset drafts so they re-sync from server
      if (isGuildTab) setGuildDraft(null);
      else setGameDraft(null);
    }
  }, [isGuildTab, gameDraft, guildDraft, saveSettings, saveGuildSettings]);

  const handleReset = useCallback(() => {
    if (isGuildTab) {
      setGuildDraft(
        guildSettings
          ? structuredClone(guildSettings)
          : { ...defaultGuildSettings, guildId: meta?.guildId ?? "" }
      );
    } else if (settings) {
      setGameDraft(structuredClone(settings));
    }
  }, [isGuildTab, settings, guildSettings, meta?.guildId]);

  if (loading) {
    return (
      <div className="flex items-center justify-center py-32">
        <Loader2 className="w-6 h-6 animate-spin text-primary" />
      </div>
    );
  }

  if (error && !settings) {
    return (
      <div className="flex items-center justify-center py-32">
        <div className="text-center">
          <AlertTriangle className="w-8 h-8 text-warning mx-auto mb-3" />
          <p className="text-sm text-text-tertiary">{error}</p>
        </div>
      </div>
    );
  }

  if (!gameDraft || !guildDraft) return null;

  const updateGameSection = <K extends keyof GameSettings>(
    key: K,
    value: GameSettings[K]
  ) => setGameDraft((prev) => (prev ? { ...prev, [key]: value } : prev));

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h1 className="font-display text-2xl font-bold tracking-tight">
            Settings
          </h1>
          <p className="text-sm text-text-tertiary mt-1">
            Configure guild, bot systems, economy, and command access
          </p>
        </div>
        <div className="flex items-center gap-3">
          {dirty && (
            <button
              onClick={handleReset}
              className="inline-flex items-center gap-2 rounded-md border border-border px-4 py-2 text-sm font-medium text-text-secondary hover:bg-primary/10 transition-colors"
            >
              <RotateCcw className="w-4 h-4" />
              Discard
            </button>
          )}
          <button
            onClick={handleSave}
            disabled={!dirty || saving}
            className={cn(
              "inline-flex items-center gap-2 rounded-md px-5 py-2 text-sm font-medium transition-colors",
              dirty
                ? "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm shadow-primary/30"
                : "bg-primary/30 text-primary-foreground/50 cursor-not-allowed"
            )}
          >
            {saving ? (
              <Loader2 className="w-4 h-4 animate-spin" />
            ) : saveSuccess ? (
              <Check className="w-4 h-4" />
            ) : (
              <Save className="w-4 h-4" />
            )}
            {saving ? "Saving…" : saveSuccess ? "Saved" : "Save Changes"}
          </button>
        </div>
      </div>

      {/* Error banner */}
      {error && (
        <div className="flex items-center gap-3 bg-destructive/10 border border-destructive/30 rounded-lg px-5 py-3">
          <AlertTriangle className="w-4 h-4 text-destructive shrink-0" />
          <span className="text-sm text-destructive">{error}</span>
        </div>
      )}

      {/* Section tabs */}
      <div className="flex gap-1 overflow-x-auto border-b border-border pb-px">
        {sections.map(({ key, label, icon: Icon }) => (
          <button
            key={key}
            onClick={() => setActiveSection(key)}
            className={cn(
              "inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium whitespace-nowrap transition-colors border-b-2 -mb-px",
              activeSection === key
                ? "border-primary text-primary"
                : "border-transparent text-text-tertiary hover:text-foreground hover:border-primary/30"
            )}
          >
            <Icon className="w-4 h-4" />
            {label}
          </button>
        ))}
      </div>

      {/* Active section content */}
      <div>
        {activeSection === "guild" && (
          <GuildSection
            data={guildDraft}
            onChange={setGuildDraft}
            meta={meta}
          />
        )}
        {activeSection === "leveling" && (
          <LevelingSection
            data={gameDraft.leveling}
            onChange={(v) => updateGameSection("leveling", v)}
          />
        )}
        {activeSection === "economy" && (
          <EconomySection
            data={gameDraft.economy}
            onChange={(v) => updateGameSection("economy", v)}
          />
        )}
        {activeSection === "inventory" && (
          <InventorySection
            data={gameDraft.inventory}
            onChange={(v) => updateGameSection("inventory", v)}
          />
        )}
        {activeSection === "lootdrop" && (
          <LootdropSection
            data={gameDraft.lootdrop}
            onChange={(v) => updateGameSection("lootdrop", v)}
          />
        )}
        {activeSection === "trivia" && (
          <TriviaSection
            data={gameDraft.trivia}
            onChange={(v) => updateGameSection("trivia", v)}
          />
        )}
        {activeSection === "moderation" && (
          <ModerationSection
            data={gameDraft.moderation}
            onChange={(v) => updateGameSection("moderation", v)}
          />
        )}
        {activeSection === "commands" && (
          <CommandsSection
            commands={gameDraft.commands}
            meta={meta}
            onChange={(v) => updateGameSection("commands", v)}
          />
        )}
      </div>

      {/* Dirty indicator footer */}
      {dirty && (
        <div className="sticky bottom-0 -mx-6 px-6 py-3 bg-background/80 backdrop-blur border-t border-border flex items-center justify-between">
          <span className="text-sm text-warning font-medium">
            You have unsaved changes
          </span>
          <div className="flex items-center gap-3">
            <button
              onClick={handleReset}
              className="text-sm text-text-tertiary hover:text-foreground transition-colors"
            >
              Discard
            </button>
            <button
              onClick={handleSave}
              disabled={saving}
              className="inline-flex items-center gap-2 rounded-md bg-primary text-primary-foreground px-4 py-1.5 text-sm font-medium hover:bg-primary/90 transition-colors"
            >
              {saving ? (
                <Loader2 className="w-3.5 h-3.5 animate-spin" />
              ) : (
                <Save className="w-3.5 h-3.5" />
              )}
              Save
            </button>
          </div>
        </div>
      )}
    </div>
  );
}
