/**
 * BotTank.js
 * AI-controlled bot tank for 3v3 team mode.
 * Used to fill empty slots when matchmaking times out,
 * or to take over disconnected players.
 * Reuses EnemyTank-style AI logic adapted for team play.
 */

const Tank = require('./Tank');
const {
  TANK_CONFIG,
  TANK_TYPE,
  DIRECTION,
  DIR_VECTORS,
  TILE_SIZE,
  MAP_OFFSET_X,
  MAP_OFFSET_Y,
} = require('../base/GameGlobal');

/** AI States */
const BOT_STATE = {
  PATROL: 'patrol',
  ATTACK_BASE: 'attack_base',
  DEFEND: 'defend',
};

class BotTank extends Tank {
  /**
   * @param {object} params
   * @param {number} params.col - Spawn grid column.
   * @param {number} params.row - Spawn grid row.
   * @param {string} params.team - 'A' or 'B'.
   * @param {string} params.playerId - Bot player id.
   * @param {string} [params.color] - Tank color override.
   */
  constructor(params) {
    const cfg = TANK_CONFIG[TANK_TYPE.PLAYER];
    const spawnX = MAP_OFFSET_X + params.col * TILE_SIZE + TILE_SIZE / 2;
    const spawnY = MAP_OFFSET_Y + params.row * TILE_SIZE + TILE_SIZE / 2;

    super({
      x: spawnX,
      y: spawnY,
      speed: cfg.speed * 0.9, // Slightly slower than human players
      hp: cfg.hp,
      color: params.color || (params.team === 'A' ? '#4A90D9' : '#E94560'),
      size: cfg.size,
      colliderSize: cfg.colliderSize || cfg.size,
      direction: params.team === 'A' ? DIRECTION.RIGHT : DIRECTION.LEFT,
    });

    this.team = params.team;
    this.playerId = params.playerId;
    this.lives = 999; // Unlimited lives for 3v3

    // AI state
    this._botState = BOT_STATE.PATROL;
    this._moveTimer = 0;
    this._dirChangeInterval = 1.5 + Math.random() * 2;
    this._shootTimer = 0;
    this._shootInterval = 1.2 + Math.random() * 1.5;
    this._stuckTimer = 0;
    this._lastX = spawnX;
    this._lastY = spawnY;

    // Active bullets tracking
    this.activeBullets = 0;
    this._maxBullets = 1;

    // Target (enemy base position)
    this._targetBase = null;

    // Shield (invincibility) — same as PlayerTank
    this._shieldTimer = 0;
    this._shieldBlink = false;
    this._blinkTimer = 0;
  }

  /**
   * Activate shield (invincibility).
   * @param {number} duration - Duration in ms.
   */
  activateShield(duration) {
    this._shieldTimer = duration;
    this._blinkTimer = 0;
    this._shieldBlink = false;
  }

  /**
   * Update bot tank state (shield timer etc.).
   * @param {number} dt - Delta time in seconds.
   */
  update(dt) {
    if (!this.alive) return;

    // Shield timer (same as PlayerTank.update)
    if (this._shieldTimer > 0) {
      this._shieldTimer -= dt * 1000;
      this._blinkTimer += dt * 1000;
      if (this._blinkTimer >= 100) {
        this._blinkTimer = 0;
        this._shieldBlink = !this._shieldBlink;
      }
      if (this._shieldTimer <= 0) {
        this._shieldTimer = 0;
        this._shieldBlink = false;
      }
    }
  }

  /**
   * Override takeDamage to check shield.
   * @param {number} amount
   * @returns {boolean} Whether destroyed.
   */
  takeDamage(amount = 1) {
    if (this._shieldTimer > 0) return false; // invincible
    return super.takeDamage(amount);
  }

  /**
   * Set the target base position for the bot to attack.
   * @param {{x: number, y: number}} basePos
   */
  setTargetBase(basePos) {
    this._targetBase = basePos;
  }

  /**
   * Update bot AI and state.
   * @param {number} dt - Delta time in seconds.
   * @param {MapManager} mapManager
   * @param {Function} [onShoot] - Callback to fire a bullet.
   */
  updateAI(dt, mapManager, onShoot) {
    if (!this.alive) return;

    // Movement AI
    this._moveTimer += dt;
    this._shootTimer += dt;

    // Check if stuck
    const moved = Math.abs(this.x - this._lastX) + Math.abs(this.y - this._lastY);
    if (moved < 0.5) {
      this._stuckTimer += dt;
    } else {
      this._stuckTimer = 0;
    }
    this._lastX = this.x;
    this._lastY = this.y;

    // Determine AI behavior
    if (Math.random() < 0.5 && this._targetBase) {
      this._botState = BOT_STATE.ATTACK_BASE;
    } else {
      this._botState = BOT_STATE.PATROL;
    }

    // Direction change
    if (this._moveTimer >= this._dirChangeInterval || this._stuckTimer > 0.5) {
      this._moveTimer = 0;
      this._stuckTimer = 0;
      this._chooseDirection(mapManager);
    }

    // Move
    this.move(this.direction, dt, mapManager);

    // Shoot
    if (this._shootTimer >= this._shootInterval) {
      this._shootTimer = 0;
      this._shootInterval = 1 + Math.random() * 1.5;

      if (this.activeBullets < this._maxBullets && onShoot) {
        onShoot(this);
      }
    }
  }

  /**
   * Choose a new direction based on AI state.
   * @private
   */
  _chooseDirection(mapManager) {
    if (this._botState === BOT_STATE.ATTACK_BASE && this._targetBase) {
      this._chaseTarget(this._targetBase, mapManager);
    } else {
      this._randomDirection();
    }
  }

  /**
   * Chase a target position (enemy base).
   * @private
   */
  _chaseTarget(target, mapManager) {
    const dx = target.x - this.x;
    const dy = target.y - this.y;

    const dirs = [];
    if (Math.abs(dx) > Math.abs(dy)) {
      dirs.push(dx > 0 ? DIRECTION.RIGHT : DIRECTION.LEFT);
      dirs.push(dy > 0 ? DIRECTION.DOWN : DIRECTION.UP);
    } else {
      dirs.push(dy > 0 ? DIRECTION.DOWN : DIRECTION.UP);
      dirs.push(dx > 0 ? DIRECTION.RIGHT : DIRECTION.LEFT);
    }

    const allDirs = [DIRECTION.UP, DIRECTION.DOWN, DIRECTION.LEFT, DIRECTION.RIGHT];
    for (const d of allDirs) {
      if (!dirs.includes(d)) dirs.push(d);
    }

    // Try each direction, pick the first that isn't blocked
    for (const dir of dirs) {
      const vec = DIR_VECTORS[dir];
      const testX = this.x + vec.dx * TILE_SIZE;
      const testY = this.y + vec.dy * TILE_SIZE;
      const left = testX - this.colliderHalfSize;
      const top = testY - this.colliderHalfSize;

      if (mapManager && !mapManager.rectCollidesWithTerrain(left, top, this.colliderSize, this.colliderSize)) {
        this.direction = dir;
        return;
      }
    }

    // Fallback: random
    this.direction = allDirs[Math.floor(Math.random() * allDirs.length)];
  }

  /**
   * Choose a random direction with bias towards enemy base side.
   * @private
   */
  _randomDirection() {
    const dirs = [DIRECTION.UP, DIRECTION.DOWN, DIRECTION.LEFT, DIRECTION.RIGHT];

    // Bias towards enemy base direction
    if (Math.random() < 0.4) {
      // Team A bots go right, Team B bots go left
      this.direction = this.team === 'A' ? DIRECTION.RIGHT : DIRECTION.LEFT;
      return;
    }

    this.direction = dirs[Math.floor(Math.random() * dirs.length)];
  }

  /** Whether this bot can fire. */
  canFire() {
    return this.alive && this.activeBullets < this._maxBullets;
  }

  /** Check if this bot can break steel (always false for bots). */
  canBreakSteel() {
    return false;
  }

  /**
   * Render with bot indicator.
   * @param {CanvasRenderingContext2D} ctx
   */
  render(ctx) {
    if (!this.alive) return;
    super.render(ctx);

    // Bot indicator (small robot icon above tank)
    ctx.fillStyle = '#AAAAAA';
    ctx.font = '8px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText('🤖', this.x, this.y - this.halfSize - 6);
  }
}

module.exports = BotTank;
