const { query } = require('../../utils/db')

const COLS = 'account, user_id, char_name, linked_at'

// Upsert a link. account is the PK, so a re-link moves the account to the new
// user (the sidecar already treats /link/confirm as authoritative).
async function upsert({ account, userId, charName }) {
  await query(
    `INSERT INTO shard_account_links (account, user_id, char_name)
     VALUES (?, ?, ?)
     ON DUPLICATE KEY UPDATE user_id = VALUES(user_id), char_name = VALUES(char_name)`,
    [account, userId, charName || null],
  )
  return getByAccount(account)
}

async function getByAccount(account) {
  const rows = await query(`SELECT ${COLS} FROM shard_account_links WHERE account = ? LIMIT 1`, [account])
  return rows[0] || null
}

const listByUser = (userId) =>
  query(`SELECT ${COLS} FROM shard_account_links WHERE user_id = ? ORDER BY linked_at DESC`, [userId])

async function isOwnedBy(account, userId) {
  const rows = await query(
    'SELECT 1 FROM shard_account_links WHERE account = ? AND user_id = ? LIMIT 1',
    [account, userId],
  )
  return rows.length > 0
}

const remove = (account, userId) =>
  query('DELETE FROM shard_account_links WHERE account = ? AND user_id = ?', [account, userId])

// Drop the mirror for an account regardless of which user held it — used to
// reconcile when the tie is severed at the source (an in-game [unlink →
// account.unlinked event, or a site-side DELETE /link/{account}).
const removeByAccount = (account) =>
  query('DELETE FROM shard_account_links WHERE account = ?', [account])

module.exports = { upsert, getByAccount, listByUser, isOwnedBy, remove, removeByAccount }
