import type { RowDataPacket } from 'mysql2'
import { db, DB } from './db'
import { getClassCss } from './character-info'

export interface GameCharacter {
  name: string
  online: boolean
  level: number
  classCss: string // clase CSS de color por clase (priest, warrior…), para el <select>
}

/** Personajes de una cuenta de juego (acore_characters). Vacío si no está poblada. */
export async function getGameCharacters(accountId: number): Promise<GameCharacter[]> {
  try {
    const [rows] = await db(DB.characters).query<RowDataPacket[]>(
      'SELECT name, online, class, level FROM characters WHERE account = ?',
      [accountId],
    )
    return rows.map((r) => ({ name: r.name, online: r.online === 1, level: Number(r.level), classCss: getClassCss(r.class) }))
  } catch {
    return []
  }
}

/** Id de la cuenta dueña de un personaje por su nombre (único), o null. */
/**
 * Busca un personaje por nombre SIN distinguir mayúsculas y devuelve su nombre
 * CANÓNICO (el de la BD) además de su cuenta.
 *
 * El COLLATE no es adorno: `characters.name` es `utf8mb4_bin`, o sea sensible a
 * mayúsculas, y sin él "innakh" no encuentra a "Innakh". Y hay que quedarse con
 * el nombre de la BD porque es el que va al comando SOAP del correo.
 */
export async function findCharacterByName(
  name: string,
): Promise<{ name: string; account: number } | null> {
  const trimmed = name.trim()
  if (!trimmed) return null
  try {
    const [rows] = await db(DB.characters).query<RowDataPacket[]>(
      'SELECT name, account FROM characters WHERE name = ? COLLATE utf8mb4_general_ci LIMIT 1',
      [trimmed],
    )
    return rows[0] ? { name: String(rows[0].name), account: Number(rows[0].account) } : null
  } catch {
    return null
  }
}

export async function getAccountIdByCharacterName(name: string): Promise<number | null> {
  const trimmed = name.trim()
  if (!trimmed) return null
  try {
    const [rows] = await db(DB.characters).query<RowDataPacket[]>(
      'SELECT account FROM characters WHERE name = ? LIMIT 1',
      [trimmed],
    )
    return rows[0] ? Number(rows[0].account) : null
  } catch {
    return null
  }
}

/** True si el personaje pertenece a la cuenta y está desconectado. */
export async function characterIsOfflineAndOwned(accountId: number, name: string): Promise<boolean> {
  const chars = await getGameCharacters(accountId)
  const c = chars.find((ch) => ch.name === name)
  return Boolean(c && !c.online)
}
