// autocomplete.ts
let _usermapCache: Record<string, any> | null = null;

function getUsermapCache(): Record<string, any> {
  if (!_usermapCache) {
    try { _usermapCache = JSON.parse(fs.readFileSync(Paths.data("usermap.json"), "utf8")); }
    catch { _usermapCache = {}; }
  }
  return _usermapCache!;
}

// interactions.ts
  const chars = JSON.parse(
    fs.readFileSync(path.join(__dirname, "../../data/characters.json"), "utf8")
  );

 // subcommands/switch.ts
  function findSharedChar(userKey: string, charName: string): { ownerKey: string; char: any } | null {
  try {
    const chars = JSON.parse(fs.readFileSync(CHARS_PATH, "utf8"));
    for (const [ownerKey, data] of Object.entries(chars) as [string, any][]) {
      if (ownerKey === userKey) continue;
      const char = data.characters?.find(
        (c: any) => c.name.toLowerCase() === charName.toLowerCase() && c.sharedWith?.includes(userKey)
      );
      if (char) return { ownerKey, char };
    }
  } catch {}
  return null;
}

// subcommands.admin.ts (userMap)
  if (sub === "map") {
    const target  = interaction.options.getUser("user", true);
    const userKey = interaction.options.getString("userkey", true);

    // Check if userKey exists in characters.json
    const fs   = require("fs");
    const path = require("path");
    const chars = JSON.parse(fs.readFileSync(path.join(__dirname, "../../../data/characters.json"), "utf8"));
    if (!chars[userKey]) {
      return void replyAndDelete(interaction, `❌ No characters found for userKey **${userKey}**. Make sure it exists in characters.json first.`, true);
    }

    // Check if this Discord ID is already mapped
    const existing = getUsermapEntryById(target.id, target.username);
    const entry = existing ?? { file: userKey, aliases: [target.globalName ?? target.username] };
    entry.file  = userKey;

    setUsermapEntry(target.id, entry);
    return void replyAndDelete(interaction, `✅ Mapped **${target.username}** (${target.id}) → **${userKey}**`, true);
  }

  const raw  = JSON.parse(fs.readFileSync(path.join(__dirname, "../../../data/usermap.json"), "utf8"));


// subcommands/char (looks a lot like the previous one, maybe extract?)
function findSharedChar(userKey: string, charName: string): { ownerKey: string; charName: string } | null {
  try {
    const chars = JSON.parse(fs.readFileSync(CHARS_PATH, "utf8"));
    for (const [ownerKey, data] of Object.entries(chars) as [string, any][]) {
      if (ownerKey === userKey) continue;
      const char = data.characters?.find(
        (c: any) => c.name.toLowerCase() === charName.toLowerCase() && c.sharedWith?.includes(userKey)
      );
      if (char) return { ownerKey, charName: char.name };
    }
  } catch {}
  return null;
}

// subcommands/share.ts
function loadRawChars(): any {
  return JSON.parse(fs.readFileSync(CHARS_PATH, "utf8"));
}

// subcommands/poll/seed.ts
    usermap = JSON.parse(fs.readFileSync(path.join(__dirname, "../../../data/usermap.json"), "utf8"));

// attendance.ts
 function load(): void {
   try { _data = JSON.parse(fs.readFileSync(Paths.data("attendance.json"), "utf8")); }
   catch { _data = {}; }
 }

  function save(): void {
   fs.writeFileSync(Paths.data("attendance.json"), JSON.stringify(_data, null, 2));
 }

// borrow.ts
 let _prefs: Record<string, { ownerKey: string; charName: string }> = {};

function loadPrefs(): void {
  try { _prefs = JSON.parse(fs.readFileSync(PREFS_PATH, "utf8")); }
  catch { _prefs = {}; }
}

function savePrefs(): void {
  try { fs.writeFileSync(PREFS_PATH, JSON.stringify(_prefs, null, 2)); }
  catch (err) { console.error("Failed to save sessionPreferences.json:", err); }
}

// systems/charSelect.ts

  const sharedChars: Character[] = [];
  try {
    const chars = JSON.parse(fs.readFileSync(CHARS_PATH, "utf8"));
    for (const [ownerKey, data] of Object.entries(chars) as [string, any][]) {
      if (ownerKey === userKey) continue;
      for (const c of data.characters ?? []) {
        if (c.sharedWith?.includes(userKey)) sharedChars.push(c);
      }
    }
  } catch {}

// systems/config.ts
let _cfg: BotConfig = {};

export function loadConfig(): void {
  try { _cfg = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8")); }
  catch { _cfg = {}; }
}

export function saveConfig(): void {
  try { fs.writeFileSync(CONFIG_PATH, JSON.stringify(_cfg, null, 2)); }
  catch (err) { console.error("Failed to save config.json:", err); }
}

// systems/emojis.ts
function loadEmojiMap(): Record<string, string> {
   if (_map) return _map;
 
   _map = {};
   const dir = Paths.emojis();
 
   if (!fs.existsSync(dir)) {
     // Fallback to legacy messages/emojis.json
     try {
       _map = JSON.parse(fs.readFileSync(Paths.messages("emojis.json"), "utf8"));
       console.warn("[emojis] data/emojis/ not found, using legacy messages/emojis.json");
     } catch {}
     return _map!;
   }
 
   for (const file of fs.readdirSync(dir)) {
     if (!file.endsWith(".json")) continue;
     try {
       const data = JSON.parse(fs.readFileSync(Paths.emojis(file), "utf8"));
       Object.assign(_map!, data);
     } catch (err) {
       console.error(`[emojis] Failed to load ${file}:`, err);
     }
   }
 
   return _map!;
 }

 // systems/history.ts
 export function loadResult(date: string, slot: number): TGResult | null {
  try {
    return JSON.parse(fs.readFileSync(historyPath(historyKey(date, slot)), "utf8"));
  } catch {
    return null;
  }
}

export function saveResult(result: TGResult): void {
  if (!fs.existsSync(HISTORY_DIR)) fs.mkdirSync(HISTORY_DIR, { recursive: true });
  const key = historyKey(result.date, result.slot);
  fs.writeFileSync(historyPath(key), JSON.stringify(result, null, 2));
}

export function listRecentResults(limit = 10): TGResult[] {
  if (!fs.existsSync(HISTORY_DIR)) return [];
  return fs.readdirSync(HISTORY_DIR)
    .filter((f) => f.endsWith(".json"))
    .sort()
    .reverse()
    .slice(0, limit)
    .map((f) => {
      try { return JSON.parse(fs.readFileSync(path.join(HISTORY_DIR, f), "utf8")) as TGResult; }
      catch { return null; }
    })
    .filter(Boolean) as TGResult[];
}

// systems.impersonate.ts
    const usermap = JSON.parse(fs.readFileSync(Paths.data("usermap.json"), "utf-8"));

// systems/messages.ts
export function loadMessages(): void {
  try {
    MESSAGES.global = JSON.parse(fs.readFileSync(path.join(MESSAGES_DIR, "global.json"), "utf8"));
  } catch (err) {
    console.error("Failed to load global.json:", err);
  }

  try {
    MESSAGES.userMap = JSON.parse(fs.readFileSync(USERMAP_PATH, "utf8"));
  } catch {
    MESSAGES.userMap = {};
  }

  const usersDir = path.join(MESSAGES_DIR, "users");
  MESSAGES.users = {};
  if (fs.existsSync(usersDir)) {
    for (const file of fs.readdirSync(usersDir)) {
      if (!file.endsWith(".json")) continue;
      const key = path.basename(file, ".json");
      try {
        MESSAGES.users[key] = JSON.parse(fs.readFileSync(path.join(usersDir, file), "utf8"));
      } catch (err) {
        console.error(`Failed to load user message file ${file}:`, err);
      }
    }
  }

  console.log(`Messages loaded — ${Object.keys(MESSAGES.users).length} user file(s).`);
}

export function setUsermapEntry(discordId: string, entry: UsermapEntry): void {
  MESSAGES.userMap[discordId] = entry;
  
  // Persist to disk
  const USERMAP_PATH = path.join(__dirname, "../../data/usermap.json");
  try {
    const raw = JSON.parse(fs.readFileSync(USERMAP_PATH, "utf8"));
    raw[discordId] = entry;
    fs.writeFileSync(USERMAP_PATH, JSON.stringify(raw, null, 2));
  } catch (err) {
    console.error("Failed to save usermap.json:", err);
  }
}
export function removeUsermapEntry(discordId: string): void {
  delete MESSAGES.userMap[discordId];

  const USERMAP_PATH = path.join(__dirname, "../../data/usermap.json");
  try {
    const raw = JSON.parse(fs.readFileSync(USERMAP_PATH, "utf8"));
    delete raw[discordId];
    fs.writeFileSync(USERMAP_PATH, JSON.stringify(raw, null, 2));
  } catch (err) {
    console.error("Failed to save usermap.json:", err);
  }
}

// systems/pollPersistence.ts
export namespace persist {
  export function save(polls: Map<number, PollState>): void {
    try {
      fs.writeFileSync(PERSIST_PATH, JSON.stringify(serialize(polls), null, 2), "utf8");
    } catch (err) {
      console.error("[pollPersistence] Failed to save poll state:", err);
    }
  }

  export function load(): Map<number, PollState> | null {
    try {
      if (!fs.existsSync(PERSIST_PATH)) return null;
      const raw  = fs.readFileSync(PERSIST_PATH, "utf8");
      const data = JSON.parse(raw) as SerializedPollState[];
      const polls = deserialize(data);
      console.log(`[pollPersistence] Restored ${polls.size} poll(s) from disk.`);
      return polls;
    } catch (err) {
      console.error("[pollPersistence] Failed to load poll state:", err);
      return null;
    }
  }

  export function clear(): void {
    try {
      if (fs.existsSync(PERSIST_PATH)) fs.unlinkSync(PERSIST_PATH);
    } catch (err) {
      console.error("[pollPersistence] Failed to clear poll state:", err);
    }
  }
}

// systems/score.ts
 function getHistoryPath(historyKey: HistoryKey): string {
   return Paths.data("tg-history", `${historyKey}.json`);
 }
 
 function loadHistory(historyKey: HistoryKey): { scores: TGScore[] } {
   try { return JSON.parse(fs.readFileSync(getHistoryPath(historyKey), "utf8")); }
   catch { return { scores: [] }; }
 }
 
 function saveHistory(historyKey: HistoryKey, data: { scores: TGScore[] }): void {
   fs.writeFileSync(getHistoryPath(historyKey), JSON.stringify(data, null, 2));
 }

 // systems/registry.ts
  function loadUsermap(): Record<string, RawUsermapValue> {
   if (!_cache) {
     try { _cache = JSON.parse(fs.readFileSync(Paths.data("usermap.json"), "utf8")); }
     catch { _cache = {}; }
   }
   return _cache!;
 }
