import type { RowDataPacket } from 'mysql2'
import { db, DB } from './db'
import { authenticate } from './auth'
import { checkSecurityToken } from './security-token'
import { is2faEnabled } from './two-factor'

/**
 * Condiciones para transferir un personaje a otra cuenta (/transfer-character):
 * personaje desconectado, contraseña correcta, token de seguridad, 2FA activo,
 * cuenta destino válida, y —para Caballeros de la Muerte— la cuenta destino debe
 * tener un personaje de nivel 55+ y no tener ya un DK. Bloqueo de 5 s tras una
 * transferencia reciente. Se comprueba ANTES del pago (SumUp).
 */
export async function checkTransferEligibility(
  accountId: number,
  email: string,
  character: string,
  body: Record<string, unknown>,
): Promise<{ ok: boolean; message?: string }> {
  const destination = String(body.destination_account ?? '').trim()
  const password = String(body.password ?? '')
  const token = String(body.security_token ?? '').trim()
  if (!destination || !password || !token) {
    return { ok: false, message: 'Completa la cuenta destino, la contraseña y el token de seguridad.' }
  }

  // Personaje: de la cuenta, desconectado, clase.
  const [chRows] = await db(DB.characters).query<RowDataPacket[]>(
    'SELECT class, online FROM characters WHERE name = ? AND account = ? LIMIT 1',
    [character, accountId],
  )
  const ch = chRows[0]
  if (!ch) return { ok: false, message: 'El personaje no pertenece a tu cuenta.' }
  if (ch.online === 1) return { ok: false, message: 'El personaje debe estar desconectado.' }
  const isDK = Number(ch.class) === 6

  // Contraseña + token de seguridad + 2FA activo.
  if (!(await authenticate(email, password))) return { ok: false, message: 'La contraseña de tu cuenta es incorrecta.' }
  if (!(await checkSecurityToken(accountId, token))) return { ok: false, message: 'El token de seguridad no es válido.' }
  if (!(await is2faEnabled(accountId))) return { ok: false, message: 'Debes tener el 2FA activado en tu cuenta.' }

  // Cuenta destino (por nombre de cuenta).
  let destId = 0
  try {
    const [acc] = await db(DB.auth).query<RowDataPacket[]>('SELECT id FROM account WHERE username = ? LIMIT 1', [destination])
    destId = acc[0] ? Number(acc[0].id) : 0
  } catch {
    return { ok: false, message: 'No se pudo verificar la cuenta de destino.' }
  }
  if (!destId) return { ok: false, message: 'La cuenta de destino no existe.' }
  if (destId === accountId) return { ok: false, message: 'La cuenta de destino no puede ser la tuya.' }

  // Condiciones de Caballero de la Muerte.
  if (isDK) {
    const [lvl] = await db(DB.characters).query<RowDataPacket[]>(
      'SELECT 1 FROM characters WHERE account = ? AND level >= 55 LIMIT 1',
      [destId],
    )
    if (!lvl[0]) {
      return { ok: false, message: 'La cuenta destino debe tener un personaje de nivel 55 o superior para recibir un Caballero de la Muerte.' }
    }
    const [dk] = await db(DB.characters).query<RowDataPacket[]>(
      'SELECT 1 FROM characters WHERE account = ? AND class = 6 LIMIT 1',
      [destId],
    )
    if (dk[0]) return { ok: false, message: 'La cuenta destino ya tiene un Caballero de la Muerte.' }
  }

  // Bloqueo de 5 s tras una transferencia reciente de esta cuenta.
  try {
    const [recent] = await db(DB.default).query<RowDataPacket[]>(
      "SELECT id FROM stripelog WHERE account_id = ? AND service = 'transfer' AND fulfilled = 1 AND timestamp > (NOW() - INTERVAL 5 SECOND) LIMIT 1",
      [accountId],
    )
    if (recent[0]) return { ok: false, message: 'Espera unos segundos antes de transferir otro personaje.' }
  } catch {
    /* ignore */
  }

  return { ok: true }
}
