/**
 * RoomScene.js
 * PVP 1v1 online multiplayer scene.
 * Entering this scene automatically creates a room and triggers invite share.
 * From an invite card, auto-joins the specified room.
 */

const {
  SCREEN_WIDTH,
  SCREEN_HEIGHT,
  COLORS,
  SCENE,
  NET_MSG,
  SERVER_URL,
} = require('../base/GameGlobal');
const { t } = require('../i18n/I18n');

// ============================================================
// Layout Constants
// ============================================================
const BTN_WIDTH = Math.min(SCREEN_WIDTH * 0.5, 240);
const BTN_HEIGHT = Math.min(36, SCREEN_HEIGHT * 0.08);
const BTN_GAP = 14;
const CENTER_X = SCREEN_WIDTH / 2;

// ============================================================
// Room Scene States
// ============================================================
const ROOM_STATE = {
  CREATING: 'creating',   // Connecting and creating room (also initial state)
  WAITING: 'waiting',     // Room created, waiting for opponent
  JOINING: 'joining',     // Joining a room
  COUNTDOWN: 'countdown', // Both players ready, counting down
  ERROR: 'error',         // Error state
};

// ============================================================
// Room Scene
// ============================================================
const RoomScene = {
  _state: ROOM_STATE.CREATING,
  _roomCode: '',
  _errorMsg: '',
  _countdown: 3,
  _countdownTimer: 0,
  _animTimer: 0,
  _networkManager: null,
  _unsubscribers: [],

  // Server URL (from global config)
  _serverUrl: SERVER_URL,

  // Button rects (calculated in enter)
  _backBtnRect: null,
  _inviteBtnRect: null,

  enter(params) {
    this._errorMsg = '';
    this._countdown = 3;
    this._countdownTimer = 0;
    this._animTimer = 0;
    this._pendingStartData = null;
    this._networkManager = GameGlobal.networkManager;

    this._backBtnRect = {
      x: 10,
      y: 10,
      w: 60,
      h: 30,
    };

    // Invite friend button (shown in WAITING state)
    const inviteBtnW = Math.min(SCREEN_WIDTH * 0.5, 240);
    const inviteBtnH = Math.min(40, SCREEN_HEIGHT * 0.08);
    this._inviteBtnRect = {
      x: CENTER_X - inviteBtnW / 2,
      y: SCREEN_HEIGHT * 0.73,
      w: inviteBtnW,
      h: inviteBtnH,
    };

    // Setup network event listeners
    this._setupNetworkEvents();

    // Decide initial flow based on entry params
    if (params && params.roomId) {
      // From invite card — auto-join the room
      this._autoJoinRoom(params.roomId);
    } else {
      // Direct entry from menu — auto-create room + share (one-step invite)
      this._state = ROOM_STATE.CREATING;
      this._roomCode = '';
      this._handleInviteAndCreate();
    }
  },

  exit() {
    this._cleanupNetworkEvents();
    // Reset share content when leaving room
    const shareManager = GameGlobal.shareManager;
    if (shareManager) {
      shareManager.resetShareContent();
    }
  },

  _setupNetworkEvents() {
    this._cleanupNetworkEvents();
    const nm = this._networkManager;
    if (!nm) return;

    const unsubs = [];

    unsubs.push(nm.on(NET_MSG.ROOM_CREATED, (data) => {
      this._roomCode = data.roomId || data.roomCode || '';
      this._state = ROOM_STATE.WAITING;
      // Update share content so right-corner menu also carries the roomId
      this._updateShareContent();
    }));

    unsubs.push(nm.on(NET_MSG.ROOM_JOINED, (data) => {
      this._roomCode = data.roomId || data.roomCode || '';
      this._state = ROOM_STATE.WAITING;
    }));

    unsubs.push(nm.on(NET_MSG.OPPONENT_JOINED, () => {
      this._state = ROOM_STATE.COUNTDOWN;
      this._countdown = 3;
      this._countdownTimer = 0;
    }));

    unsubs.push(nm.on(NET_MSG.GAME_START, (data) => {
      // Server authoritative game start — always use server data (contains mapId)
      this._pendingStartData = data;
      if (this._state !== ROOM_STATE.COUNTDOWN) {
        // Guest path: not in countdown state, start game immediately
        this._startGame(data);
      } else if (this._countdown <= 0) {
        // Host path: countdown already finished, start immediately
        this._startGame(data);
      }
      // Host path: countdown still running, will pick up pendingStartData when done
    }));

    unsubs.push(nm.on(NET_MSG.ROOM_ERROR, (data) => {
      this._errorMsg = data.message || 'Unknown error';
      this._state = ROOM_STATE.ERROR;
    }));

    unsubs.push(nm.on('error', () => {
      this._errorMsg = t('common.connectFailed');
      this._state = ROOM_STATE.ERROR;
    }));

    unsubs.push(nm.on('disconnected', () => {
      if (this._state !== ROOM_STATE.CREATING) {
        this._errorMsg = t('common.disconnected');
        this._state = ROOM_STATE.ERROR;
      }
    }));

    this._unsubscribers = unsubs;
  },

  _cleanupNetworkEvents() {
    for (const unsub of this._unsubscribers) {
      if (typeof unsub === 'function') unsub();
    }
    this._unsubscribers = [];
  },

  update(dt) {
    this._animTimer += dt;

    if (this._state === ROOM_STATE.COUNTDOWN) {
      this._countdownTimer += dt;
      if (this._countdownTimer >= 1) {
        this._countdownTimer -= 1;
        this._countdown--;
        if (this._countdown <= 0) {
          // Countdown finished — only start if we already received server GAME_START
          if (this._pendingStartData) {
            this._startGame(this._pendingStartData);
          }
          // Otherwise wait for server GAME_START message
        }
      }
    }
  },

  /**
   * Update share content so the right-corner ··· menu always carries
   * the current roomId for 1v1 invite.
   * @private
   */
  _updateShareContent() {
    if (!this._roomCode) return;
    const shareManager = GameGlobal.shareManager;
    if (shareManager) {
      shareManager.setShareContent({
        title: t('room.shareTitle'),
        imageUrl: 'js/ui/images/1v1.png',
        query: `roomId=${this._roomCode}`,
      });
    }
  },

  /**
   * Handle "Invite Friend" button tap — trigger WeChat share.
   * MUST be called within a touch event for WeChat policy compliance.
   * @private
   */
  _handleInvite() {
    if (!this._roomCode) return;

    const shareData = {
      title: t('room.shareTitle'),
      imageUrl: 'js/ui/images/1v1.png',
      query: `roomId=${this._roomCode}`,
    };

    console.log(`[RoomScene] Sharing 1v1 invite with query: roomId=${this._roomCode}`);

    const shareManager = GameGlobal.shareManager;
    if (shareManager) {
      shareManager.triggerShare(shareData);
    } else {
      try {
        if (typeof wx !== 'undefined' && wx.showToast) {
          wx.showToast({
            title: '请点击右上角 ··· 转发给好友',
            icon: 'none',
            duration: 2500,
          });
        }
      } catch (e) {
        console.log('[RoomScene] Share not available, roomId:', this._roomCode);
      }
    }
  },

  /**
   * One-step invite: auto-create room then immediately share the invite card.
   * This is the primary action — automatically creates a room and triggers invite share
   * and we handle everything in one go.
   * MUST be called within a touch event for WeChat policy compliance.
   * @private
   */
  async _handleInviteAndCreate() {
    const nm = this._networkManager;

    if (!nm) {
      this._errorMsg = t('common.cannotConnect');
      this._state = ROOM_STATE.ERROR;
      return;
    }

    // If already connected and in a room (WAITING state), just re-share
    if (this._state === ROOM_STATE.WAITING && this._roomCode) {
      this._handleInvite();
      return;
    }

    // Connect if needed
    if (!nm.connected) {
      this._state = ROOM_STATE.CREATING;
      const ok = await nm.connect(this._serverUrl);
      if (!ok) {
        this._errorMsg = t('common.cannotConnect');
        this._state = ROOM_STATE.ERROR;
        return;
      }
    }

    // Create room — the ROOM_CREATED event handler will set state to WAITING
    // and store the roomCode. We need to share AFTER the room is created,
    // so we listen for the event once.
    const shareOnCreated = (data) => {
      const roomId = data.roomId || data.roomCode || '';
      if (!roomId) return;

      const shareData = {
        title: t('room.shareTitle'),
        imageUrl: 'js/ui/images/1v1.png',
        query: `roomId=${roomId}`,
      };

      console.log(`[RoomScene] Auto-sharing 1v1 invite after room created: roomId=${roomId}`);

      const shareManager = GameGlobal.shareManager;
      if (shareManager) {
        shareManager.triggerShare(shareData);
      } else {
        try {
          if (typeof wx !== 'undefined' && wx.showToast) {
            wx.showToast({
              title: '请点击右上角 ··· 转发给好友',
              icon: 'none',
              duration: 2500,
            });
          }
        } catch (e) {
          console.log('[RoomScene] Share not available after room created');
        }
      }
    };

    // Subscribe one-time for auto-share after room creation
    const unsub = nm.on(NET_MSG.ROOM_CREATED, (data) => {
      // Unsubscribe immediately (one-time listener)
      unsub();
      shareOnCreated(data);
    });

    // Now create the room
    nm.createRoom();
  },

  _startGame(data) {
    const sm = GameGlobal.sceneManager;
    if (!sm._scenes.has(SCENE.TEAM_GAME)) {
      const TeamGameScene = require('./TeamGameScene');
      sm.register(SCENE.TEAM_GAME, TeamGameScene);
    }

    const myPlayerId = this._networkManager ? this._networkManager.playerId : 'local';
    const playerSlot = this._networkManager ? this._networkManager.playerSlot : 1;

    // Build teamA/teamB from GAME_START data (sent by server for 1v1 via TeamRoom)
    let teamA = data.teamA || [];
    let teamB = data.teamB || [];

    // Fallback: if server didn't send teamA/teamB (legacy), construct from playerSlot
    if (teamA.length === 0 && teamB.length === 0) {
      if (playerSlot === 1) {
        teamA = [{ playerId: myPlayerId, isBot: false }];
        teamB = [{ playerId: 'opponent', isBot: false }];
      } else {
        teamA = [{ playerId: 'opponent', isBot: false }];
        teamB = [{ playerId: myPlayerId, isBot: false }];
      }
    }

    sm.switchTo(SCENE.TEAM_GAME, {
      teamId: this._roomCode,
      roomId: data.roomId || this._roomCode,
      mapId: data.mapId || null,
      teamA,
      teamB,
      teamABaseHp: data.teamABaseHp,
      teamBBaseHp: data.teamBBaseHp,
      myPlayerId,
      battleMode: data.battleMode || '1v1',
    });
  },

  render(ctx) {
    // Background
    ctx.fillStyle = COLORS.MENU_BG;
    ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

    // Top bar
    const gradient = ctx.createLinearGradient(0, 0, SCREEN_WIDTH, 0);
    gradient.addColorStop(0, '#0f3460');
    gradient.addColorStop(0.5, '#e94560');
    gradient.addColorStop(1, '#0f3460');
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, SCREEN_WIDTH, 4);

    // Back button
    this._drawButton(ctx, this._backBtnRect, t('common.back'), false, 12);

    // Title
    ctx.fillStyle = COLORS.MENU_TITLE;
    ctx.font = 'bold 24px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(t('room.title'), CENTER_X, SCREEN_HEIGHT * 0.12);

    // Render based on state
    switch (this._state) {
      case ROOM_STATE.CREATING:
      case ROOM_STATE.JOINING:
        this._renderConnecting(ctx);
        break;
      case ROOM_STATE.WAITING:
        this._renderWaiting(ctx);
        break;
      case ROOM_STATE.COUNTDOWN:
        this._renderCountdown(ctx);
        break;
      case ROOM_STATE.ERROR:
        this._renderError(ctx);
        break;
    }
  },

  _renderConnecting(ctx) {
    const dots = '.'.repeat(Math.floor(this._animTimer * 3) % 4);
    ctx.fillStyle = '#FFFFFF';
    ctx.font = '16px Arial';
    ctx.textAlign = 'center';
    ctx.fillText(t('room.connecting', { dots }), CENTER_X, SCREEN_HEIGHT * 0.5);
  },

  _renderWaiting(ctx) {
    // Room code display
    ctx.fillStyle = '#FFFFFF';
    ctx.font = '14px Arial';
    ctx.textAlign = 'center';
    ctx.fillText(t('room.roomCode'), CENTER_X, SCREEN_HEIGHT * 0.32);

    ctx.fillStyle = COLORS.MENU_TITLE;
    ctx.font = 'bold 36px Arial';
    ctx.fillText(this._roomCode, CENTER_X, SCREEN_HEIGHT * 0.42);

    // Waiting animation
    const dots = '.'.repeat(Math.floor(this._animTimer * 2) % 4);
    ctx.fillStyle = '#AAAAAA';
    ctx.font = '16px Arial';
    ctx.fillText(t('room.waiting', { dots }), CENTER_X, SCREEN_HEIGHT * 0.52);

    // Invite friend button (primary action)
    this._drawButton(ctx, this._inviteBtnRect, t('room.inviteFriend'), false, 16, '#e94560');

    // Hint text below the button
    ctx.fillStyle = '#666666';
    ctx.font = '12px Arial';
    ctx.fillText(t('room.shareHint'), CENTER_X, SCREEN_HEIGHT * 0.84);
  },

  _renderCountdown(ctx) {
    ctx.fillStyle = '#00FF00';
    ctx.font = '14px Arial';
    ctx.textAlign = 'center';
    ctx.fillText(t('room.opponentFound'), CENTER_X, SCREEN_HEIGHT * 0.35);

    ctx.fillStyle = COLORS.MENU_TITLE;
    ctx.font = 'bold 64px Arial';
    ctx.fillText(String(this._countdown), CENTER_X, SCREEN_HEIGHT * 0.52);

    ctx.fillStyle = '#AAAAAA';
    ctx.font = '14px Arial';
    ctx.fillText(t('room.starting'), CENTER_X, SCREEN_HEIGHT * 0.65);
  },

  _renderError(ctx) {
    ctx.fillStyle = '#FF4444';
    ctx.font = '16px Arial';
    ctx.textAlign = 'center';
    ctx.fillText(this._errorMsg, CENTER_X, SCREEN_HEIGHT * 0.45);

    ctx.fillStyle = '#AAAAAA';
    ctx.font = '14px Arial';
    ctx.fillText(t('room.tapBack'), CENTER_X, SCREEN_HEIGHT * 0.55);
  },

  _drawButton(ctx, rect, label, pressed, fontSize, bgColor) {
    if (!rect) return;
    const fs = fontSize || 16;

    ctx.fillStyle = bgColor || (pressed ? '#0f3460' : COLORS.MENU_BTN);
    ctx.strokeStyle = COLORS.MENU_BTN_BORDER;
    ctx.lineWidth = 2;

    // Rounded rect
    const r = 6;
    ctx.beginPath();
    ctx.moveTo(rect.x + r, rect.y);
    ctx.lineTo(rect.x + rect.w - r, rect.y);
    ctx.arcTo(rect.x + rect.w, rect.y, rect.x + rect.w, rect.y + r, r);
    ctx.lineTo(rect.x + rect.w, rect.y + rect.h - r);
    ctx.arcTo(rect.x + rect.w, rect.y + rect.h, rect.x + rect.w - r, rect.y + rect.h, r);
    ctx.lineTo(rect.x + r, rect.y + rect.h);
    ctx.arcTo(rect.x, rect.y + rect.h, rect.x, rect.y + rect.h - r, r);
    ctx.lineTo(rect.x, rect.y + r);
    ctx.arcTo(rect.x, rect.y, rect.x + r, rect.y, r);
    ctx.closePath();
    ctx.fill();
    ctx.stroke();

    ctx.fillStyle = pressed ? COLORS.MENU_TITLE : COLORS.MENU_BTN_TEXT;
    ctx.font = `bold ${fs}px Arial`;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(label, rect.x + rect.w / 2, rect.y + rect.h / 2);
  },

  _hitTest(tx, ty, rect) {
    if (!rect) return false;
    return tx >= rect.x && tx <= rect.x + rect.w && ty >= rect.y && ty <= rect.y + rect.h;
  },

  handleTouch(eventType, e) {
    if (eventType !== 'touchstart') return;

    const touch = e.touches[0];
    const tx = touch.clientX;
    const ty = touch.clientY;

    // Back button (always available)
    if (this._hitTest(tx, ty, this._backBtnRect)) {
      this._goBack();
      return;
    }

    switch (this._state) {
      case ROOM_STATE.ERROR:
        this._state = ROOM_STATE.CREATING;
        this._errorMsg = '';
        break;

      case ROOM_STATE.WAITING:
        // Invite friend button
        if (this._hitTest(tx, ty, this._inviteBtnRect)) {
          this._handleInvite();
        }
        // Allow going back while waiting
        break;
    }
  },

  /**
   * Auto-join a 1v1 room when entering from an invite card.
   * @param {string} roomId - Room ID from the invite card query parameter.
   */
  async _autoJoinRoom(roomId) {
    this._state = ROOM_STATE.JOINING;
    this._errorMsg = '';
    const nm = this._networkManager;

    if (!nm) {
      this._errorMsg = t('common.cannotConnect');
      this._state = ROOM_STATE.ERROR;
      return;
    }

    try {
      if (!nm.connected) {
        const ok = await nm.connect(this._serverUrl);
        if (!ok) {
          this._errorMsg = t('common.cannotConnect');
          this._state = ROOM_STATE.ERROR;
          return;
        }
      }

      console.log(`[RoomScene] Auto-joining 1v1 room ${roomId}`);
      nm.joinRoom(roomId);
    } catch (e) {
      console.error('[RoomScene] Auto-join failed:', e);
      this._errorMsg = t('common.cannotConnect');
      this._state = ROOM_STATE.ERROR;
    }
  },

  _goBack() {
    // Disconnect if connected
    if (this._networkManager && this._networkManager.connected) {
      this._networkManager.disconnect();
    }
    const sm = GameGlobal.sceneManager;
    sm.switchTo(SCENE.MENU);
  },
};

module.exports = RoomScene;
