// Shared Multiplayer Module — used by Chess, Ludo, Domino
// Handles: opponent bar, synced emotes, connection status, rematch, friend add, disconnect

import * as net from './net.js';
import * as store from './store.js';
import * as audio from './audio.js';
import * as juice from './juice.js';
import * as scene from './scene.js';
import * as modal from './modal.js';
import { emoji } from './theme.js';
import { DEFAULT_RATING } from './config.js';
import { t } from './i18n.js';

let currentMatchId = null;
let currentMatchType = null; // 'chess' | 'ludo' | 'domino'
let opponentData = null;
let emoteCallback = null;
let disconnectTimer = null;
let lastOpponentPing = Date.now();

// ========== OPPONENT BAR ==========
export function renderOpponentBar(container, opponent, options = {}) {
  opponentData = opponent;
  const { showRating = true, position = 'top' } = options;

  const bar = document.createElement('div');
  bar.id = 'mp-opponent-bar';
  bar.style.cssText = 'display:flex;align-items:center;gap:10px;padding:8px 12px;background:var(--bg-panel);cursor:pointer;';
  bar.innerHTML = `
    <div style="position:relative;">
      <div style="width:36px;height:36px;border-radius:50%;background:var(--bg-hover);display:flex;align-items:center;justify-content:center;font-size:14px;overflow:hidden;">
        ${opponent.avatar_url ? `<img src="${opponent.avatar_url}" style="width:100%;height:100%;object-fit:cover;border-radius:50%;">` : emoji('person', '👤', 14)}
      </div>
      <div id="mp-conn-dot" style="position:absolute;bottom:-1px;right:-1px;width:10px;height:10px;border-radius:50%;background:var(--success);border:2px solid var(--bg-panel);"></div>
    </div>
    <div style="flex:1;">
      <div style="font-size:13px;font-weight:600;color:var(--text-primary);">${opponent.display_name || opponent.username || t('common.opponent')}</div>
      ${showRating ? `<div style="font-size:11px;color:var(--text-muted);">${emoji('star', '⭐', 11)} ${opponent.rating || opponent.elo_rapid || DEFAULT_RATING}</div>` : ''}
    </div>
    <div id="mp-opponent-status" style="font-size:10px;color:var(--text-muted);"></div>
  `;

  // Tap to show profile actions
  bar.addEventListener('click', () => {
    audio.play('click');
    showOpponentActions(container, opponent);
  });

  if (position === 'top') container.prepend(bar);
  else container.appendChild(bar);

  return bar;
}

function showOpponentActions(container, opponent) {
  const existing = document.getElementById('mp-opponent-menu');
  if (existing) { existing.remove(); return; }

  const menu = document.createElement('div');
  menu.id = 'mp-opponent-menu';
  menu.style.cssText = 'position:absolute;top:50px;right:12px;background:var(--bg-card);border:1px solid rgba(255,255,255,0.08);border-radius:12px;padding:8px;z-index:100;box-shadow:0 8px 24px rgba(0,0,0,0.5);display:flex;flex-direction:column;gap:4px;min-width:140px;';
  menu.innerHTML = `
    <button class="mp-action" data-action="profile">${emoji('person', '👤', 12)} ${t('mp.profile')}</button>
    <button class="mp-action" data-action="friend">${emoji('add_friend', '➕', 12)} ${t('mp.add_friend')}</button>
    <button class="mp-action" data-action="mute">${emoji('mute', '🔇', 12)} ${t('block.mute')}</button>
    <button class="mp-action" data-action="block" style="color:var(--error);">${emoji('block', '🚫', 12)} ${t('block.block')}</button>
    <button class="mp-action" data-action="report" style="color:var(--error);">${emoji('warning', '⚠️', 12)} ${t('mp.report')}</button>
  `;

  const style = document.createElement('style');
  style.textContent = '.mp-action{background:none;border:none;color:var(--text-light);font-size:12px;font-weight:500;padding:8px 12px;text-align:right;cursor:pointer;border-radius:6px;font-family:inherit;width:100%;transition:background 0.1s;}.mp-action:hover{background:rgba(255,255,255,0.05);}.mp-action:active{background:rgba(255,255,255,0.1);}';
  menu.appendChild(style);

  menu.querySelector('[data-action="friend"]').addEventListener('click', async () => {
    const btn = menu.querySelector('[data-action="friend"]');
    btn.style.opacity = '0.5';
    btn.style.pointerEvents = 'none';
    const result = await addFriendFromGame(opponent.id);
    if (result === true) {
      btn.textContent = t('common.sent');
      btn.style.color = 'var(--success)';
    } else {
      btn.textContent = result || t('common.already_sent');
      btn.style.color = 'var(--text-muted)';
    }
    juice.hapticLight();
    setTimeout(() => menu.remove(), 1500);
  });

  menu.querySelector('[data-action="mute"]').addEventListener('click', async () => {
    const btn = menu.querySelector('[data-action="mute"]');
    btn.style.opacity = '0.5';
    btn.style.pointerEvents = 'none';
    try {
      await net.post('friends.php', { action: 'mute', target_id: opponent.id });
      btn.textContent = '✓ ' + t('block.muted');
      btn.style.color = 'var(--text-muted)';
    } catch (e) {}
    juice.hapticLight();
    setTimeout(() => menu.remove(), 1000);
  });

  menu.querySelector('[data-action="block"]').addEventListener('click', async () => {
    menu.remove();
    const confirmed = await modal.confirm(t('block.confirm_block'), {
      title: t('mp.block'),
      icon: '🚫',
      confirmText: t('common.confirm'),
      cancelText: t('common.cancel'),
      danger: true
    });
    if (!confirmed) return;
    try {
      await net.post('friends.php', { action: 'block', target_id: opponent.id });
      juice.hapticLight();
    } catch (e) {}
  });

  menu.querySelector('[data-action="report"]').addEventListener('click', () => {
    reportOpponent(opponent.id);
    menu.querySelector('[data-action="report"]').textContent = t('mp.reported');
    setTimeout(() => menu.remove(), 1000);
  });

  menu.querySelector('[data-action="profile"]').addEventListener('click', () => {
    menu.remove();
    scene.push('profile-view', { playerId: opponent.id });
  });

  // Close on outside click
  setTimeout(() => {
    document.addEventListener('click', function close(e) {
      if (!menu.contains(e.target)) { menu.remove(); document.removeEventListener('click', close); }
    });
  }, 100);

  container.style.position = 'relative';
  container.appendChild(menu);
}

// ========== SYNCED EMOTES ==========
let lastEmoteTimestamp = 0;

export async function sendEmote(matchId, matchType, emoteKey) {
  const endpoint = matchType === 'ludo' ? 'ludo-match.php' : 'game.php';
  const userId = store.get('auth.userId');

  try {
    await net.post(endpoint, {
      action: 'move',
      match_id: matchId,
      game_state: JSON.stringify({
        emote: { key: emoteKey, from: userId, t: Date.now() }
      })
    });
  } catch (e) {}
}

export function onEmoteReceived(callback) {
  emoteCallback = callback;
}

export function checkForEmote(gameState, myUserId) {
  if (!gameState) return null;
  const gs = typeof gameState === 'string' ? JSON.parse(gameState) : gameState;
  if (!gs || !gs.emote || gs.emote.from === myUserId) return null;
  if (gs.emote.t <= lastEmoteTimestamp) return null;
  if (Date.now() - gs.emote.t > 15000) return null;
  lastEmoteTimestamp = gs.emote.t;
  return gs.emote;
}

// ========== CONNECTION STATUS ==========
export function updateConnectionStatus(isConnected) {
  const dot = document.getElementById('mp-conn-dot');
  if (dot) {
    dot.style.background = isConnected ? 'var(--success)' : 'var(--error)';
  }
  lastOpponentPing = Date.now();
}

// Deprecated: use match-session.js startDisconnectWatch instead
export function startDisconnectWatch(matchId, matchType, timeoutMs = 60000) {
  currentMatchId = matchId;
  currentMatchType = matchType;
  disconnectTimer = setInterval(() => {
    const elapsed = Date.now() - lastOpponentPing;
    const dot = document.getElementById('mp-conn-dot');
    const status = document.getElementById('mp-opponent-status');

    if (elapsed > timeoutMs) {
      if (dot) dot.style.background = 'var(--error)';
      if (status) status.textContent = t('game.opponent_disconnected');
      clearInterval(disconnectTimer);
    } else if (elapsed > 15000) {
      if (dot) dot.style.background = 'var(--amber)';
      if (status) status.textContent = t('game.weak_connection');
    } else {
      if (dot) dot.style.background = 'var(--success)';
      if (status) status.textContent = '';
    }
  }, 5000);
}

export function stopDisconnectWatch() {
  if (disconnectTimer) { clearInterval(disconnectTimer); disconnectTimer = null; }
}

// ========== REMATCH ==========
export async function requestRematch(matchId, matchType) {
  const endpoint = matchType === 'ludo' ? 'ludo-match.php' : 'game.php';
  try {
    await net.post(endpoint, {
      action: 'move',
      match_id: matchId,
      game_state: JSON.stringify({ rematch_request: store.get('auth.userId') })
    });
    return true;
  } catch (e) { return false; }
}

export function checkForRematch(gameState, myUserId) {
  if (!gameState) return false;
  const gs = typeof gameState === 'string' ? JSON.parse(gameState) : gameState;
  return gs.rematch_request && gs.rematch_request !== myUserId;
}

// ========== FRIEND ADD ==========
export async function addFriendFromGame(opponentId) {
  try {
    const res = await net.post('friends.php', { action: 'request', target_id: opponentId });
    if (res.error) {
      if (res.error.includes('Already friends')) return t('common.already_friends');
      if (res.error.includes('pending')) return t('common.already_sent');
      return res.error;
    }
    juice.hapticLight();
    return true;
  } catch (e) {
    const msg = e.message || '';
    if (msg.includes('Already') || msg.includes('pending')) return t('common.already_sent');
    return false;
  }
}

// ========== REPORT ==========
export async function reportOpponent(opponentId, reason = 'in_game') {
  try {
    await net.post('friends.php', { action: 'report', target_id: opponentId, reason });
    audio.play('click');
  } catch (e) {}
}

// ========== FETCH OPPONENT PROFILE ==========
export async function fetchOpponentProfile(opponentId) {
  try {
    const data = await net.get('profile.php', { id: opponentId });
    return data;
  } catch (e) { return null; }
}

// ========== CLEANUP ==========
export function cleanup() {
  stopDisconnectWatch();
  emoteCallback = null;
  opponentData = null;
  currentMatchId = null;
  lastEmoteTimestamp = 0;
  const menu = document.getElementById('mp-opponent-menu');
  if (menu) menu.remove();
}
