/**
 * TeamRoomSceneFactory.js
 * Factory function that creates a team room scene object.
 * Shared by 2v2 and 3v3 team rooms — eliminates code duplication.
 *
 * Usage:
 *   const Team2v2RoomScene = createTeamRoomScene({
 *     teamSize: 2,
 *     battleMode: '2v2',
 *     i18nPrefix: 'team2v2Room',
 *     logTag: 'Team2v2Room',
 *   });
 */

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

// ============================================================
// Layout Constants (shared across all team room variants)
// ============================================================
const BTN_WIDTH = Math.min(SCREEN_WIDTH * 0.35, 180);
const BTN_HEIGHT = Math.min(36, SCREEN_HEIGHT * 0.07);
const BTN_GAP = 10;
const CENTER_X = SCREEN_WIDTH / 2;
const SLOT_WIDTH = Math.min(SCREEN_WIDTH * 0.15, 80);
const SLOT_HEIGHT = Math.min(SCREEN_HEIGHT * 0.18, 90);
const SLOT_GAP = 8;

// ============================================================
// Team Room States (shared)
// ============================================================
const TEAM_STATE = {
  MODE_SELECT: 'mode_select',
  JOINING: 'joining',
  FORMING: 'forming',
  MATCHING: 'matching',
  COUNTDOWN: 'countdown',
  ERROR: 'error',
};

// ============================================================
// i18n helper
// ============================================================
function tp(prefix, key, params) {
  const fullKey = `${prefix}.${key}`;
  return params ? t(fullKey, params) : t(fullKey);
}

// ============================================================
// Factory
// ============================================================
function createTeamRoomScene(config) {
  const {
    teamSize,
    battleMode,
    i18nPrefix,
    logTag,
    shareImageUrl = '',
  } = config;

  return {
    _state: TEAM_STATE.MODE_SELECT,
    _teamData: null,
    _errorMsg: '',
    _animTimer: 0,
    _matchTimer: 0,
    _countdown: 3,
    _countdownTimer: 0,
    _networkManager: null,
    _unsubscribers: [],
    _isLeader: false,
    _myPlayerId: null,
    _serverUrl: SERVER_URL,

    // Button rects
    _createTeamBtnRect: null,
    _soloMatchBtnRect: null,
    _backBtnRect: null,
    _inviteBtnRect: null,
    _matchBtnRect: null,
    _readyBtnRect: null,
    _disbandBtnRect: null,
    _leaveBtnRect: null,
    _cancelMatchBtnRect: null,
    _slotRects: [],
    _kickBtnRects: [],
    _avatarImages: {},

    // ---- Lifecycle ----

    enter(params) {
      this._state = TEAM_STATE.MODE_SELECT;
      this._teamData = null;
      this._errorMsg = '';
      this._animTimer = 0;
      this._matchTimer = 0;
      this._countdown = 3;
      this._countdownTimer = 0;
      this._networkManager = GameGlobal.networkManager;
      this._myPlayerId = this._networkManager ? this._networkManager.playerId : 'player_' + Date.now();
      this._isLeader = false;
      this._avatarImages = {};

      this._buildLayout();
      this._setupNetworkEvents();
      this._setupProfileListener();

      if (params && params.teamId) {
        this._autoJoinTeam(params.teamId);
      }
    },

    exit() {
      this._cleanupNetworkEvents();
      this._cleanupProfileListener();
      const shareManager = GameGlobal.shareManager;
      if (shareManager) {
        shareManager.resetShareContent();
      }
    },

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

      if (this._state === TEAM_STATE.MATCHING) {
        this._matchTimer += dt;
      }

      if (this._state === TEAM_STATE.COUNTDOWN) {
        this._countdownTimer += dt;
        if (this._countdownTimer >= 1) {
          this._countdownTimer -= 1;
          this._countdown--;
        }
      }
    },

    // ---- Layout ----

    _buildLayout() {
      const modeY = SCREEN_HEIGHT * 0.4;

      this._createTeamBtnRect = {
        x: CENTER_X - BTN_WIDTH / 2,
        y: modeY,
        w: BTN_WIDTH,
        h: BTN_HEIGHT,
      };
      this._soloMatchBtnRect = {
        x: CENTER_X - BTN_WIDTH / 2,
        y: modeY + BTN_HEIGHT + BTN_GAP,
        w: BTN_WIDTH,
        h: BTN_HEIGHT,
      };
      this._backBtnRect = { x: 10, y: 10, w: 60, h: 30 };

      const totalSlotsWidth = teamSize * SLOT_WIDTH + (teamSize - 1) * SLOT_GAP;
      const slotsStartX = CENTER_X - totalSlotsWidth / 2;
      const slotsY = SCREEN_HEIGHT * 0.25;

      this._slotRects = [];
      this._kickBtnRects = [];
      for (let i = 0; i < teamSize; i++) {
        const x = slotsStartX + i * (SLOT_WIDTH + SLOT_GAP);
        this._slotRects.push({ x, y: slotsY, w: SLOT_WIDTH, h: SLOT_HEIGHT });
        this._kickBtnRects.push({ x: x + SLOT_WIDTH - 18, y: slotsY + 2, w: 16, h: 16 });
      }

      const actionY = SCREEN_HEIGHT * 0.58;
      const smallBtnW = BTN_WIDTH * 0.8;

      this._inviteBtnRect = {
        x: CENTER_X - smallBtnW - BTN_GAP / 2,
        y: actionY,
        w: smallBtnW,
        h: BTN_HEIGHT,
      };
      this._matchBtnRect = {
        x: CENTER_X + BTN_GAP / 2,
        y: actionY,
        w: smallBtnW,
        h: BTN_HEIGHT,
      };
      this._readyBtnRect = {
        x: CENTER_X - smallBtnW / 2,
        y: actionY,
        w: smallBtnW,
        h: BTN_HEIGHT,
      };
      this._disbandBtnRect = {
        x: CENTER_X - smallBtnW - BTN_GAP / 2,
        y: actionY + BTN_HEIGHT + BTN_GAP,
        w: smallBtnW,
        h: BTN_HEIGHT,
      };
      this._leaveBtnRect = {
        x: CENTER_X - smallBtnW / 2,
        y: actionY + BTN_HEIGHT + BTN_GAP,
        w: smallBtnW,
        h: BTN_HEIGHT,
      };
      this._cancelMatchBtnRect = {
        x: CENTER_X - BTN_WIDTH / 2,
        y: SCREEN_HEIGHT * 0.7,
        w: BTN_WIDTH,
        h: BTN_HEIGHT,
      };
    },

    // ---- Share ----

    _updateShareContent() {
      if (!this._teamData || !this._teamData.teamId) return;
      const shareManager = GameGlobal.shareManager;
      if (shareManager) {
        shareManager.setShareContent({
          title: tp(i18nPrefix, 'shareTitle'),
          imageUrl: shareImageUrl,
          query: `teamId=${this._teamData.teamId}&mode=${battleMode}`,
        });
      }
    },

    // ---- Network Events ----

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

      const unsubs = [];

      unsubs.push(nm.on(NET_MSG.TEAM_STATE, (data) => {
        if (data.teamA) {
          for (const m of data.teamA) {
            if (m.avatarUrl && this._avatarImages[m.playerId] === null) {
              delete this._avatarImages[m.playerId];
            }
          }
        }
        if (data.teamB) {
          for (const m of data.teamB) {
            if (m.avatarUrl && this._avatarImages[m.playerId] === null) {
              delete this._avatarImages[m.playerId];
            }
          }
        }

        this._teamData = data;
        this._isLeader = data.leaderId === this._myPlayerId;

        if (data.state === 'forming') {
          this._state = TEAM_STATE.FORMING;
        } else if (data.state === 'matching') {
          this._state = TEAM_STATE.MATCHING;
        }

        this._updateShareContent();
      }));

      unsubs.push(nm.on(NET_MSG.TEAM_DISBAND, (data) => {
        this._teamData = null;
        this._state = TEAM_STATE.MODE_SELECT;
        if (data.reason === 'kicked') {
          this._errorMsg = t('common.kicked');
          this._state = TEAM_STATE.ERROR;
        }
      }));

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

      unsubs.push(nm.on(NET_MSG.TEAM_GAME_START, (data) => {
        this._startTeamGame(data);
      }));

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

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

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

      this._unsubscribers = unsubs;
    },

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

    // ---- Profile Listener ----

    _setupProfileListener() {
      this._cleanupProfileListener();
      const bus = (typeof GameGlobal !== 'undefined') ? GameGlobal.eventBus : null;
      if (!bus || typeof bus.on !== 'function') return;

      this._profileUnsub = bus.on('profile:updated', () => {
        if (this._teamData && this._networkManager && this._networkManager.connected) {
          this._networkManager.send(NET_MSG.PING);
        }
        if (this._myPlayerId && this._avatarImages[this._myPlayerId] !== undefined) {
          delete this._avatarImages[this._myPlayerId];
        }
      });
    },

    _cleanupProfileListener() {
      if (this._profileUnsub) {
        this._profileUnsub();
        this._profileUnsub = null;
      }
    },

    // ---- Game Start ----

    _startTeamGame(data) {
      const sm = GameGlobal.sceneManager;
      if (!sm._scenes.has(SCENE.TEAM_GAME)) {
        const TeamGameScene = require('./TeamGameScene');
        sm.register(SCENE.TEAM_GAME, TeamGameScene);
      }
      sm.switchTo(SCENE.TEAM_GAME, {
        teamId: this._teamData ? this._teamData.teamId : null,
        mapId: data.mapId,
        teamA: data.teamA,
        teamB: data.teamB,
        teamABaseHp: data.teamABaseHp,
        teamBBaseHp: data.teamBBaseHp,
        battleMode: data.battleMode || battleMode,
        roomId: data.roomId || '',
        myPlayerId: this._myPlayerId,
      });
    },

    // ---- Render ----

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

      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);

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

      ctx.fillStyle = COLORS.MENU_TITLE;
      ctx.font = 'bold 22px Arial';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(tp(i18nPrefix, 'title'), CENTER_X, SCREEN_HEIGHT * 0.08);

      switch (this._state) {
        case TEAM_STATE.MODE_SELECT:
          this._renderModeSelect(ctx);
          break;
        case TEAM_STATE.JOINING:
          this._renderJoining(ctx);
          break;
        case TEAM_STATE.FORMING:
          this._renderForming(ctx);
          break;
        case TEAM_STATE.MATCHING:
          this._renderMatching(ctx);
          break;
        case TEAM_STATE.COUNTDOWN:
          this._renderCountdown(ctx);
          break;
        case TEAM_STATE.ERROR:
          this._renderError(ctx);
          break;
      }
    },

    _renderJoining(ctx) {
      const dots = '.'.repeat(Math.floor(this._animTimer * 3) % 4);
      ctx.fillStyle = '#FFFFFF';
      ctx.font = '18px Arial';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(tp(i18nPrefix, 'joining') + dots, CENTER_X, SCREEN_HEIGHT * 0.45);
    },

    _renderModeSelect(ctx) {
      ctx.fillStyle = '#AAAAAA';
      ctx.font = '14px Arial';
      ctx.textAlign = 'center';
      ctx.fillText(tp(i18nPrefix, 'chooseMode'), CENTER_X, SCREEN_HEIGHT * 0.28);

      this._drawButton(ctx, this._createTeamBtnRect, tp(i18nPrefix, 'createTeam'));
      this._drawButton(ctx, this._soloMatchBtnRect, tp(i18nPrefix, 'soloMatch'));
    },

    _renderForming(ctx) {
      if (!this._teamData) return;

      ctx.fillStyle = '#AAAAAA';
      ctx.font = '12px Arial';
      ctx.textAlign = 'center';
      ctx.fillText(tp(i18nPrefix, 'teamId', { id: this._teamData.teamId }), CENTER_X, SCREEN_HEIGHT * 0.16);

      const members = this._teamData.teamA || [];
      for (let i = 0; i < teamSize; i++) {
        const rect = this._slotRects[i];
        const member = members[i];

        ctx.fillStyle = member ? '#1e3a5f' : '#0d1b2a';
        ctx.strokeStyle = member ? (member.isLeader ? '#FFD700' : '#0f3460') : '#333333';
        ctx.lineWidth = member && member.isLeader ? 3 : 1;
        this._drawRoundRect(ctx, rect.x, rect.y, rect.w, rect.h, 8);
        ctx.fill();
        ctx.stroke();

        if (member) {
          const avatarR = Math.min(rect.w, rect.h) * 0.32;
          const avatarCX = rect.x + rect.w / 2;
          const avatarCY = rect.y + rect.h * 0.42;
          this._drawAvatar(ctx, member, avatarCX, avatarCY, avatarR);

          if (!member.isLeader) {
            ctx.fillStyle = member.ready ? '#00FF00' : '#FF6347';
            ctx.font = 'bold 10px Arial';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(
              member.ready ? tp(i18nPrefix, 'ready') : tp(i18nPrefix, 'notReady'),
              avatarCX, rect.y + rect.h * 0.88,
            );
          }

          if (this._isLeader && !member.isLeader && member.playerId !== this._myPlayerId) {
            const kickRect = this._kickBtnRects[i];
            ctx.fillStyle = '#FF4444';
            ctx.font = 'bold 12px Arial';
            ctx.fillText('✕', kickRect.x + kickRect.w / 2, kickRect.y + kickRect.h / 2);
          }
        } else {
          ctx.fillStyle = '#555555';
          ctx.font = '24px Arial';
          ctx.textAlign = 'center';
          ctx.textBaseline = 'middle';
          ctx.fillText('+', rect.x + rect.w / 2, rect.y + rect.h / 2);

          ctx.fillStyle = '#666666';
          ctx.font = '10px Arial';
          ctx.fillText(tp(i18nPrefix, 'emptySlot'), rect.x + rect.w / 2, rect.y + rect.h * 0.78);
        }
      }

      if (this._isLeader) {
        this._drawButton(ctx, this._inviteBtnRect, tp(i18nPrefix, 'invite'));
        const allReady = members.length > 0 && members.every(m => m.ready || m.isLeader);
        this._drawButton(ctx, this._matchBtnRect, tp(i18nPrefix, 'startMatch'), false, 14, allReady ? null : '#555555');
        this._drawButton(ctx, this._disbandBtnRect, tp(i18nPrefix, 'disband'), false, 12, '#8B0000');
      } else {
        const myMember = members.find(m => m.playerId === this._myPlayerId);
        const readyLabel = myMember && myMember.ready ? tp(i18nPrefix, 'cancelReady') : tp(i18nPrefix, 'readyBtn');
        this._drawButton(ctx, this._readyBtnRect, readyLabel);
        this._drawButton(ctx, this._leaveBtnRect, tp(i18nPrefix, 'leaveTeam'), false, 12, '#8B0000');
      }
    },

    _renderMatching(ctx) {
      if (!this._teamData) return;

      const members = this._teamData.teamA || [];
      for (let i = 0; i < teamSize; i++) {
        const rect = this._slotRects[i];
        const member = members[i];

        ctx.fillStyle = member ? '#1e3a5f' : '#0d1b2a';
        ctx.strokeStyle = member ? (member.isLeader ? '#FFD700' : '#0f3460') : '#333333';
        ctx.lineWidth = member && member.isLeader ? 3 : 1;
        this._drawRoundRect(ctx, rect.x, rect.y, rect.w, rect.h, 8);
        ctx.fill();
        ctx.stroke();

        if (member) {
          const avatarR = Math.min(rect.w, rect.h) * 0.32;
          const avatarCX = rect.x + rect.w / 2;
          const avatarCY = rect.y + rect.h * 0.42;
          this._drawAvatar(ctx, member, avatarCX, avatarCY, avatarR);

          if (!member.isLeader) {
            ctx.fillStyle = member.ready ? '#00FF00' : '#FF6347';
            ctx.font = 'bold 10px Arial';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(
              member.ready ? tp(i18nPrefix, 'ready') : tp(i18nPrefix, 'notReady'),
              avatarCX, rect.y + rect.h * 0.88,
            );
          }
        } else {
          ctx.fillStyle = '#555555';
          ctx.font = '24px Arial';
          ctx.textAlign = 'center';
          ctx.textBaseline = 'middle';
          ctx.fillText('+', rect.x + rect.w / 2, rect.y + rect.h / 2);
        }
      }

      const elapsed = Math.floor(this._matchTimer);
      const dots = '.'.repeat(Math.floor(this._animTimer * 3) % 4);
      ctx.fillStyle = '#FFFFFF';
      ctx.font = '18px Arial';
      ctx.textAlign = 'center';
      ctx.fillText(tp(i18nPrefix, 'matching', { dots }), CENTER_X, SCREEN_HEIGHT * 0.55);

      ctx.fillStyle = '#AAAAAA';
      ctx.font = '14px Arial';
      ctx.fillText(tp(i18nPrefix, 'waitTime', { seconds: elapsed }), CENTER_X, SCREEN_HEIGHT * 0.62);

      if (this._isLeader) {
        this._drawButton(ctx, this._cancelMatchBtnRect, tp(i18nPrefix, 'cancelMatch'));
      }
    },

    _renderCountdown(ctx) {
      ctx.fillStyle = '#00FF00';
      ctx.font = '16px Arial';
      ctx.textAlign = 'center';
      ctx.fillText(tp(i18nPrefix, 'matchFound'), CENTER_X, SCREEN_HEIGHT * 0.35);

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

      ctx.fillStyle = '#AAAAAA';
      ctx.font = '14px Arial';
      ctx.fillText(tp(i18nPrefix, 'enterBattle'), 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(tp(i18nPrefix, 'tapBack'), CENTER_X, SCREEN_HEIGHT * 0.55);
    },

    // ---- Drawing Helpers ----

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

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

      this._drawRoundRect(ctx, rect.x, rect.y, rect.w, rect.h, 6);
      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);
    },

    _drawRoundRect(ctx, x, y, w, h, r) {
      ctx.beginPath();
      ctx.moveTo(x + r, y);
      ctx.lineTo(x + w - r, y);
      ctx.arcTo(x + w, y, x + w, y + r, r);
      ctx.lineTo(x + w, y + h - r);
      ctx.arcTo(x + w, y + h, x + w - r, y + h, r);
      ctx.lineTo(x + r, y + h);
      ctx.arcTo(x, y + h, x, y + h - r, r);
      ctx.lineTo(x, y + r);
      ctx.arcTo(x, y, x + r, y, r);
      ctx.closePath();
    },

    _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;
    },

    _drawAvatar(ctx, member, cx, cy, r) {
      const img = this._avatarImages[member.playerId];
      if (img) {
        ctx.save();
        ctx.beginPath();
        ctx.arc(cx, cy, r, 0, Math.PI * 2);
        ctx.clip();
        ctx.drawImage(img, cx - r, cy - r, r * 2, r * 2);
        ctx.restore();

        ctx.strokeStyle = member.isLeader ? '#FFD700' : '#4a90d9';
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.arc(cx, cy, r + 1, 0, Math.PI * 2);
        ctx.stroke();
      } else {
        if (member.playerId === this._myPlayerId) {
          const profile = (typeof GameGlobal !== 'undefined') ? GameGlobal.playerProfile : null;
          if (profile && profile.avatarUrl && !this._avatarImages[member.playerId]) {
            this._loadAvatar(member);
          }
        }

        const bgColor = member.isLeader ? '#FFD700' : '#4a90d9';
        ctx.fillStyle = bgColor;
        ctx.beginPath();
        ctx.arc(cx, cy, r, 0, Math.PI * 2);
        ctx.fill();

        ctx.fillStyle = 'rgba(255,255,255,0.7)';
        ctx.beginPath();
        ctx.arc(cx, cy - r * 0.2, r * 0.3, 0, Math.PI * 2);
        ctx.fill();
        ctx.beginPath();
        ctx.ellipse(cx, cy + r * 0.55, r * 0.55, r * 0.35, 0, Math.PI, 0);
        ctx.fill();

        ctx.strokeStyle = bgColor;
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.arc(cx, cy, r + 1, 0, Math.PI * 2);
        ctx.stroke();

        this._loadAvatar(member);
      }
    },

    _loadAvatar(member) {
      let avatarUrl = member.avatarUrl;
      if (member.playerId === this._myPlayerId) {
        const profile = (typeof GameGlobal !== 'undefined') ? GameGlobal.playerProfile : null;
        if (profile && profile.avatarUrl) {
          avatarUrl = profile.avatarUrl;
        }
      }

      if (!avatarUrl || this._avatarImages[member.playerId] !== undefined) return;

      this._avatarImages[member.playerId] = null;

      try {
        const img = wx.createImage();
        img.onload = () => {
          this._avatarImages[member.playerId] = img;
        };
        img.onerror = () => {
          // Keep null so we don't retry endlessly
        };
        img.src = avatarUrl;
      } catch (e) {
        // wx.createImage not available
      }
    },

    _getDisplayName(member) {
      if (!member) return '';
      const profile = GameGlobal.playerProfile;
      let raw = member.nickname || '';
      if (!raw) {
        if (profile && typeof profile.getDisplayName === 'function') {
          raw = profile.getDisplayName(member.playerId);
        } else {
          raw = member.playerId || '';
        }
      }
      if (profile && typeof profile.truncate === 'function') {
        return profile.truncate(raw, 4);
      }
      return raw.length > 8 ? raw.substring(0, 8) + '..' : raw;
    },

    // ---- Touch Handling ----

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

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

      if (this._hitTest(tx, ty, this._backBtnRect)) {
        this._goBack();
        return;
      }

      switch (this._state) {
        case TEAM_STATE.MODE_SELECT:
          if (this._hitTest(tx, ty, this._createTeamBtnRect)) {
            this._handleCreateTeam();
          } else if (this._hitTest(tx, ty, this._soloMatchBtnRect)) {
            this._handleSoloMatch();
          }
          break;

        case TEAM_STATE.FORMING:
          this._handleFormingTouch(tx, ty);
          break;

        case TEAM_STATE.MATCHING:
          if (this._isLeader && this._hitTest(tx, ty, this._cancelMatchBtnRect)) {
            this._handleCancelMatch();
          }
          break;

        case TEAM_STATE.ERROR:
          this._state = TEAM_STATE.MODE_SELECT;
          this._errorMsg = '';
          break;
      }
    },

    _handleFormingTouch(tx, ty) {
      if (!this._teamData) return;

      if (this._isLeader) {
        if (this._hitTest(tx, ty, this._inviteBtnRect)) {
          this._handleInvite();
          return;
        }
        if (this._hitTest(tx, ty, this._matchBtnRect)) {
          this._handleStartMatch();
          return;
        }
        if (this._hitTest(tx, ty, this._disbandBtnRect)) {
          this._handleDisband();
          return;
        }

        const members = this._teamData.teamA || [];
        for (let i = 0; i < members.length; i++) {
          const member = members[i];
          if (member && !member.isLeader && member.playerId !== this._myPlayerId) {
            if (this._hitTest(tx, ty, this._kickBtnRects[i])) {
              this._handleKick(member.playerId);
              return;
            }
          }
        }
      } else {
        if (this._hitTest(tx, ty, this._readyBtnRect)) {
          this._handleReady();
          return;
        }
        if (this._hitTest(tx, ty, this._leaveBtnRect)) {
          this._handleLeave();
          return;
        }
      }
    },

    // ---- Action Handlers ----

    async _handleCreateTeam() {
      const nm = this._networkManager;
      if (!nm) return;

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

      this._myPlayerId = nm.playerId;
      nm.createTeam(battleMode);
    },

    async _handleSoloMatch() {
      const nm = this._networkManager;
      if (!nm) return;

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

      this._myPlayerId = nm.playerId;
      this._matchTimer = 0;
      nm.soloMatch(battleMode);
    },

    async _autoJoinTeam(teamId) {
      const nm = this._networkManager;
      if (!nm) {
        this._errorMsg = t('common.cannotConnect');
        this._state = TEAM_STATE.ERROR;
        return;
      }

      this._state = TEAM_STATE.JOINING;
      this._errorMsg = '';

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

        this._myPlayerId = nm.playerId;
        console.log(`[${logTag}] Auto-joining team ${teamId} as ${this._myPlayerId}`);
        nm.send(NET_MSG.JOIN_TEAM, { teamId });
      } catch (e) {
        console.error(`[${logTag}] Auto-join failed:`, e);
        this._errorMsg = t('common.cannotConnect');
        this._state = TEAM_STATE.ERROR;
      }
    },

    _handleInvite() {
      if (!this._teamData) return;

      const teamId = this._teamData.teamId;
      const shareData = {
        title: tp(i18nPrefix, 'shareTitle'),
        imageUrl: shareImageUrl,
        query: `teamId=${teamId}&mode=${battleMode}`,
      };

      console.log(`[${logTag}] Sharing invite with query: teamId=${teamId}&mode=${battleMode}`);

      const shareManager = GameGlobal.shareManager;
      if (shareManager) {
        shareManager.triggerShare(shareData);
      } else {
        try {
          wx.showToast({
            title: '请点击右上角 ··· 转发给好友',
            icon: 'none',
            duration: 2500,
          });
        } catch (e) {
          console.log(`[${logTag}] Share not available, teamId:`, teamId);
        }
      }
    },

    _handleStartMatch() {
      const nm = this._networkManager;
      if (!nm || !this._teamData) return;

      const members = this._teamData.teamA || [];
      const allReady = members.length > 0 && members.every(m => m.ready || m.isLeader);
      if (!allReady) return;

      this._matchTimer = 0;
      nm.send(NET_MSG.MATCH_START, {});
    },

    _handleCancelMatch() {
      const nm = this._networkManager;
      if (!nm) return;
      nm.send(NET_MSG.MATCH_CANCEL, {});
    },

    _handleReady() {
      const nm = this._networkManager;
      if (!nm || !this._teamData) return;

      const myMember = (this._teamData.teamA || []).find(m => m.playerId === this._myPlayerId);
      nm.send(NET_MSG.TEAM_READY, { ready: myMember ? !myMember.ready : true });
    },

    _handleKick(playerId) {
      const nm = this._networkManager;
      if (!nm) return;
      nm.send(NET_MSG.TEAM_KICK, { playerId });
    },

    _handleDisband() {
      const nm = this._networkManager;
      if (!nm) return;
      nm.send(NET_MSG.TEAM_DISBAND, {});
    },

    _handleLeave() {
      const nm = this._networkManager;
      if (!nm) return;
      nm.send(NET_MSG.LEAVE_TEAM, {});
      this._teamData = null;
      this._state = TEAM_STATE.MODE_SELECT;
    },

    _goBack() {
      if (this._teamData) {
        const nm = this._networkManager;
        if (nm) {
          if (this._state === TEAM_STATE.MATCHING && this._isLeader) {
            nm.send(NET_MSG.MATCH_CANCEL, {});
          }
          if (this._isLeader) {
            nm.send(NET_MSG.TEAM_DISBAND, {});
          } else {
            nm.send(NET_MSG.LEAVE_TEAM, {});
          }
        }
      }

      const sm = GameGlobal.sceneManager;
      sm.switchTo(SCENE.MENU);
    },
  };
}

module.exports = { createTeamRoomScene, TEAM_STATE };
