import type { RowDataPacket } from 'mysql2'
import { db, DB } from './db'

/**
 * Rastreador de misiones (/quest-character): comprueba el estado (completada /
 * en curso / sin empezar) de misiones o cadenas de misiones en un personaje.
 *
 * Categorías (cooldown por personaje):
 *  - 'class'      cadenas de misiones de clase — cada 30 min
 *  - 'reputation' cadenas de misiones (reputación) — cada 1 h
 *  - 'specific'   una misión concreta por ID — cada 10 min
 */

export type QuestCategory = 'class' | 'reputation' | 'specific'

export const COOLDOWN_MS: Record<QuestCategory, number> = {
  reputation: 60 * 60 * 1000,
  class: 30 * 60 * 1000,
  specific: 10 * 60 * 1000,
}

export interface QuestOption {
  key: string
  category: Exclude<QuestCategory, 'specific'>
  classCss: string | null // clase a la que aplica ('warlock'…) o null (cualquier clase)
  label: string
  link?: { type: 'spell' | 'item' | 'faction'; id: number }
  icon?: string
  minLevel: number
  quests: number[] // IDs de misión de la cadena (variantes de facción combinadas)
}

// IDs de misión verificados en la BD WotLK 3.3.5a (wotlkdb.com): la misión FINAL
// que otorga cada habilidad, combinando variantes de facción/raza (el personaje
// solo tendrá en su registro las de su facción/raza). Editables aquí si hiciera falta.
export const QUEST_OPTIONS: QuestOption[] = [
  // Brujo
  { key: 'wl_voidwalker', category: 'class', classCss: 'warlock', label: 'Invocar abisario', link: { type: 'spell', id: 697 }, minLevel: 10, icon: 'spell_shadow_summonvoidwalker', quests: [1689, 1504, 1471] },
  { key: 'wl_succubus', category: 'class', classCss: 'warlock', label: 'Invocar súcubo', link: { type: 'spell', id: 712 }, minLevel: 20, icon: 'spell_shadow_summonsuccubus', quests: [1739, 1513, 1474] },
  { key: 'wl_felhunter', category: 'class', classCss: 'warlock', label: 'Invocar manáfago', link: { type: 'spell', id: 691 }, minLevel: 30, icon: 'spell_shadow_summonfelhunter', quests: [1795] },
  { key: 'wl_inferno', category: 'class', classCss: 'warlock', label: 'Inferno', link: { type: 'spell', id: 1122 }, minLevel: 50, icon: 'spell_shadow_summoninfernal', quests: [7603] },
  { key: 'wl_doom', category: 'class', classCss: 'warlock', label: 'Ritual de fatalidad', link: { type: 'spell', id: 18540 }, minLevel: 60, icon: 'spell_shadow_antimagicshell', quests: [7583] },
  // Cazador
  { key: 'hunter_pet', category: 'class', classCss: 'hunter', label: 'Habilidades de mascota', minLevel: 10, quests: [6103, 6086, 9675, 6081, 6089, 9673] },
  // Chamán
  { key: 'sh_earth', category: 'class', classCss: 'shaman', label: 'Tótem de tierra', link: { type: 'item', id: 5175 }, minLevel: 4, icon: 'spell_totem_wardofdraining', quests: [9451, 1518, 1521] },
  { key: 'sh_fire', category: 'class', classCss: 'shaman', label: 'Tótem de fuego', link: { type: 'item', id: 5176 }, minLevel: 10, icon: 'spell_totem_wardofdraining', quests: [9555, 1527] },
  { key: 'sh_water', category: 'class', classCss: 'shaman', label: 'Tótem de agua', link: { type: 'item', id: 5177 }, minLevel: 20, icon: 'spell_totem_wardofdraining', quests: [9509, 96] },
  { key: 'sh_air', category: 'class', classCss: 'shaman', label: 'Tótem de aire', link: { type: 'item', id: 5178 }, minLevel: 30, icon: 'spell_totem_wardofdraining', quests: [9554, 1531, 1532] },
  // Druida
  { key: 'dr_bear', category: 'class', classCss: 'druid', label: 'Forma de oso', link: { type: 'spell', id: 5487 }, minLevel: 10, icon: 'ability_racial_bearform', quests: [6001, 6002] },
  { key: 'dr_curepoison', category: 'class', classCss: 'druid', label: 'Curar envenenamiento', link: { type: 'spell', id: 8946 }, minLevel: 14, icon: 'spell_nature_nullifypoison', quests: [6125, 6130] },
  { key: 'dr_aquatic', category: 'class', classCss: 'druid', label: 'Forma acuática', link: { type: 'spell', id: 1066 }, minLevel: 16, icon: 'ability_druid_aquaticform', quests: [5061, 31] },
  { key: 'dr_flight', category: 'class', classCss: 'druid', label: 'Forma de vuelo presto', link: { type: 'spell', id: 40120 }, minLevel: 70, icon: 'ability_druid_flightform', quests: [11001] },
  // Guerrero
  { key: 'wr_defensive', category: 'class', classCss: 'warrior', label: 'Actitud defensiva', link: { type: 'spell', id: 71 }, minLevel: 10, icon: 'ability_warrior_defensivestance', quests: [1665, 1678, 1683, 9582, 10350, 1498, 1819] },
  { key: 'wr_berserker', category: 'class', classCss: 'warrior', label: 'Actitud rabiosa', link: { type: 'spell', id: 2458 }, minLevel: 30, icon: 'ability_racial_avatar', quests: [1719] },
  // Paladín
  { key: 'pal_redemption', category: 'class', classCss: 'paladin', label: 'Redención', link: { type: 'spell', id: 7328 }, minLevel: 12, icon: 'spell_holy_resurrection', quests: [1788, 9598, 9685] },
  // Reputación
  { key: 'rep_hodir', category: 'reputation', classCss: null, label: 'Los Hijos de Hodir', link: { type: 'faction', id: 1119 }, minLevel: 77, quests: [12843, 13064, 12915, 12956] },
]

/** Opciones que un personaje (clase + nivel) puede rastrear. */
export function optionsFor(classCss: string, level: number): QuestOption[] {
  return QUEST_OPTIONS.filter(
    (o) => (o.classCss === null || o.classCss === classCss) && level >= o.minLevel && o.quests.length > 0,
  )
}

export type QuestState = 'rewarded' | 'inProgress' | 'none'
export interface QuestStatus {
  quest: number
  state: QuestState
}

/** Estado de cada misión (completada/en curso/sin empezar) para un personaje. */
export async function questStatuses(guid: number, quests: number[]): Promise<QuestStatus[]> {
  if (quests.length === 0) return []
  const ph = quests.map(() => '?').join(',')
  const rewarded = new Set<number>()
  const inProgress = new Set<number>()
  try {
    const [r] = await db(DB.characters).query<RowDataPacket[]>(
      `SELECT quest FROM character_queststatus_rewarded WHERE guid = ? AND quest IN (${ph})`,
      [guid, ...quests],
    )
    for (const row of r) rewarded.add(Number(row.quest))
    const [p] = await db(DB.characters).query<RowDataPacket[]>(
      `SELECT quest FROM character_queststatus WHERE guid = ? AND quest IN (${ph})`,
      [guid, ...quests],
    )
    for (const row of p) inProgress.add(Number(row.quest))
  } catch {
    /* ignore */
  }
  return quests.map((q) => ({
    quest: q,
    state: rewarded.has(q) ? 'rewarded' : inProgress.has(q) ? 'inProgress' : 'none',
  }))
}

/** Minutos restantes de cooldown para (personaje, categoría), o 0 si disponible. */
export async function cooldownRemainingMs(character: string, category: QuestCategory): Promise<number> {
  try {
    const [rows] = await db(DB.default).query<RowDataPacket[]>(
      'SELECT searched_at FROM questsearchhistory WHERE character_name = ? AND category = ? ORDER BY searched_at DESC LIMIT 1',
      [character, category],
    )
    if (!rows[0]) return 0
    const diff = Date.now() - new Date(rows[0].searched_at).getTime()
    return diff < COOLDOWN_MS[category] ? COOLDOWN_MS[category] - diff : 0
  } catch {
    return 0
  }
}

export async function recordSearch(character: string, category: QuestCategory): Promise<void> {
  try {
    await db(DB.default).query(
      'INSERT INTO questsearchhistory (character_name, category, searched_at) VALUES (?, ?, NOW())',
      [character, category],
    )
  } catch {
    /* ignore */
  }
}
