import { drawTileMap } from './TileMap';
import { AgentSprite } from './AgentSprite';
import { getCharLabel } from './SpriteSheet';

const STATUS_ICONS = {
  idle: null,
  working: null,
  waiting: '❗',
  reporting: '📋',
  break: '☕',
};

export class OfficeRenderer {
  constructor(canvas, mapData) {
    this.canvas = canvas;
    this.ctx = canvas.getContext('2d');
    this.mapData = mapData;
    this.renderInfo = null;
    this.agents = {};
    this._animId = null;
    this._onClick = null;

    const agentIds = ['stock', 'music', 'claude'];
    for (const id of agentIds) {
      this.agents[id] = new AgentSprite(id, mapData.waypoints);
    }
  }

  start() {
    this._loop = this._loop.bind(this);
    this._animId = requestAnimationFrame(this._loop);
  }

  stop() {
    if (this._animId) {
      cancelAnimationFrame(this._animId);
      this._animId = null;
    }
  }

  resize(width, height) {
    this.canvas.width = width;
    this.canvas.height = height;
  }

  setOnClick(handler) {
    this._onClick = handler;
  }

  handleClick(canvasX, canvasY) {
    if (!this.renderInfo) return null;

    for (const [id, sprite] of Object.entries(this.agents)) {
      if (sprite.hitTest(canvasX, canvasY, this.renderInfo)) {
        if (this._onClick) this._onClick(id);
        return id;
      }
    }
    return null;
  }

  updateAgentState(agentId, state, detail) {
    const sprite = this.agents[agentId];
    if (sprite) {
      sprite.setState(state, detail);
      if (state === 'idle' || state === 'working' || state === 'waiting') {
        sprite.moveToDesk();
      }
    }
  }

  moveAgent(agentId, target) {
    const sprite = this.agents[agentId];
    if (sprite) {
      sprite.moveTo(target);
    }
  }

  _loop(timestamp) {
    const { ctx, canvas, mapData } = this;

    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = '#1a1a2e';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    this.renderInfo = drawTileMap(ctx, mapData, canvas.width, canvas.height);

    const now = Date.now();
    for (const sprite of Object.values(this.agents)) {
      sprite.update(now);
      sprite.draw(ctx, this.renderInfo);
    }

    for (const [id, sprite] of Object.entries(this.agents)) {
      this._drawOverlay(ctx, sprite, id);
    }

    this._animId = requestAnimationFrame(this._loop);
  }

  _drawOverlay(ctx, sprite, agentId) {
    if (!this.renderInfo) return;
    const { scale, offsetX, offsetY, tileSize } = this.renderInfo;
    const cx = offsetX + sprite.x * tileSize * scale + (tileSize * scale) / 2;
    const cy = offsetY + sprite.y * tileSize * scale - 10 * scale;

    const icon = STATUS_ICONS[sprite.state];
    if (icon) {
      ctx.font = `${14 * scale}px serif`;
      ctx.textAlign = 'center';
      ctx.fillText(icon, cx, cy - 15 * scale);
    }

    ctx.fillStyle = 'rgba(255,255,255,0.7)';
    ctx.font = `${8 * scale}px monospace`;
    ctx.textAlign = 'center';
    ctx.fillText(getCharLabel(agentId), cx, cy + 30 * scale + 30);

    if (sprite.detail && (sprite.state === 'working' || sprite.state === 'waiting')) {
      const bubbleY = cy - 25 * scale;
      ctx.fillStyle = 'rgba(0,0,0,0.7)';
      const textW = ctx.measureText(sprite.detail).width;
      ctx.fillRect(cx - textW / 2 - 6, bubbleY - 10, textW + 12, 16);
      ctx.fillStyle = '#fff';
      ctx.font = `${7 * scale}px monospace`;
      ctx.fillText(sprite.detail, cx, bubbleY);
    }
  }
}
