// src/pages/agent-office/canvas/OfficeRenderer.js

import mapData from '../assets/office-map.json';
import { TileMap } from './TileMap.js';
import { FurnitureRenderer } from './FurnitureRenderer.js';
import { Pathfinder } from './Pathfinder.js';
import { AgentSprite } from './AgentSprite.js';
import { OverlayRenderer } from './OverlayRenderer.js';
import { getTheme } from './themes.js';

const AGENT_META = {
  stock:      { displayName: '주식 트레이더', emoji: '📈', color: '#4488cc' },
  music:      { displayName: '음악 프로듀서', emoji: '🎵', color: '#44aa88' },
  blog:       { displayName: '블로그 마케터', emoji: '✍️', color: '#d97706' },
  realestate: { displayName: '청약 애널리스트', emoji: '🏢', color: '#c026d3' },
  lotto:      { displayName: '로또 큐레이터', emoji: '🎱', color: '#ef4444' }
};

export class OfficeRenderer {
  constructor(canvas) {
    this.canvas = canvas;
    this.ctx = canvas.getContext('2d');

    // 맵 & 렌더러
    this.tileMap = new TileMap(mapData);
    this.furnitureRenderer = new FurnitureRenderer(mapData.furniture, mapData.tileSize);
    this.pathfinder = new Pathfinder(mapData.cols, mapData.rows);
    this.overlayRenderer = new OverlayRenderer();

    // blocked 타일 설정
    this.pathfinder.setWalls(mapData.floor);
    this.pathfinder.setBlocked(mapData.blocked);

    // 테마 & 뷰포트
    this.theme = getTheme(
      (typeof localStorage !== 'undefined' && localStorage.getItem('agent-office-theme')) || 'modern'
    );
    this.zoom = 2;
    this.panX = 0;
    this.panY = 0;
    this._isPanning = false;
    this._panStart = { x: 0, y: 0 };

    // 에이전트
    this.agents = new Map();
    this._initAgents();

    // 게임 루프
    this._lastTime = 0;
    this._animId = null;
    this._lastDpr = window.devicePixelRatio || 1;

    // 드래그 감지
    this._mouseDownPos = { x: 0, y: 0 };
    this._wasDragging = false;

    // 이벤트
    this._setupInputHandlers();
  }

  _initAgents() {
    for (const [id, meta] of Object.entries(AGENT_META)) {
      const waypoint = mapData.waypoints[`desk_${id}`];
      if (!waypoint) continue;
      const sprite = new AgentSprite(id, meta, waypoint.col, waypoint.row, this.pathfinder);
      sprite.deskCol = waypoint.col;
      sprite.deskRow = waypoint.row;
      this.agents.set(id, sprite);
    }
  }

  /** 줌/팬/클릭 이벤트 핸들러 */
  _setupInputHandlers() {
    // 마우스 휠 줌
    this.canvas.addEventListener('wheel', (e) => {
      e.preventDefault();
      const oldZoom = this.zoom;
      if (e.deltaY < 0) {
        this.zoom = Math.min(this.zoom + 0.5, 4);
      } else {
        this.zoom = Math.max(this.zoom - 0.5, 1);
      }
      // 마우스 위치 기준 줌
      if (this.zoom !== oldZoom) {
        const rect = this.canvas.getBoundingClientRect();
        const mx = e.clientX - rect.left;
        const my = e.clientY - rect.top;
        const ratio = this.zoom / oldZoom;
        this.panX = mx - (mx - this.panX) * ratio;
        this.panY = my - (my - this.panY) * ratio;
      }
    }, { passive: false });

    // 마우스 드래그 패닝
    this.canvas.addEventListener('mousedown', (e) => {
      if (e.button === 0) {
        this._isPanning = true;
        this._panStart = { x: e.clientX - this.panX, y: e.clientY - this.panY };
        this._mouseDownPos = { x: e.clientX, y: e.clientY };
        this._wasDragging = false;
      }
    });
    this._onMouseMove = (e) => {
      if (this._isPanning) {
        this.panX = e.clientX - this._panStart.x;
        this.panY = e.clientY - this._panStart.y;
        const dx = e.clientX - this._mouseDownPos.x;
        const dy = e.clientY - this._mouseDownPos.y;
        if (Math.abs(dx) > 5 || Math.abs(dy) > 5) this._wasDragging = true;
      }
    };
    this._onMouseUp = () => {
      this._isPanning = false;
    };
    window.addEventListener('mousemove', this._onMouseMove);
    window.addEventListener('mouseup', this._onMouseUp);

    // 터치 (모바일)
    let lastTouchDist = 0;
    let lastTouchCenter = { x: 0, y: 0 };
    this.canvas.addEventListener('touchstart', (e) => {
      if (e.touches.length === 1) {
        this._isPanning = true;
        this._panStart = { x: e.touches[0].clientX - this.panX, y: e.touches[0].clientY - this.panY };
      } else if (e.touches.length === 2) {
        this._isPanning = false;
        const dx = e.touches[0].clientX - e.touches[1].clientX;
        const dy = e.touches[0].clientY - e.touches[1].clientY;
        lastTouchDist = Math.hypot(dx, dy);
        lastTouchCenter = {
          x: (e.touches[0].clientX + e.touches[1].clientX) / 2,
          y: (e.touches[0].clientY + e.touches[1].clientY) / 2
        };
      }
    }, { passive: false });
    this.canvas.addEventListener('touchmove', (e) => {
      e.preventDefault();
      if (e.touches.length === 1 && this._isPanning) {
        this.panX = e.touches[0].clientX - this._panStart.x;
        this.panY = e.touches[0].clientY - this._panStart.y;
      } else if (e.touches.length === 2) {
        const dx = e.touches[0].clientX - e.touches[1].clientX;
        const dy = e.touches[0].clientY - e.touches[1].clientY;
        const dist = Math.hypot(dx, dy);
        const oldZoom = this.zoom;
        this.zoom = Math.min(4, Math.max(1, this.zoom * (dist / lastTouchDist)));
        lastTouchDist = dist;
        const rect = this.canvas.getBoundingClientRect();
        const cx = lastTouchCenter.x - rect.left;
        const cy = lastTouchCenter.y - rect.top;
        const ratio = this.zoom / oldZoom;
        this.panX = cx - (cx - this.panX) * ratio;
        this.panY = cy - (cy - this.panY) * ratio;
      }
    }, { passive: false });
    this.canvas.addEventListener('touchend', () => {
      this._isPanning = false;
    });
  }

  /** 클릭 히트 테스트 — AgentOffice에서 호출 */
  hitTest(clientX, clientY) {
    const rect = this.canvas.getBoundingClientRect();
    const screenX = clientX - rect.left;
    const screenY = clientY - rect.top;
    const { col, row } = this.tileMap.screenToTile(screenX, screenY, this.zoom, this.panX, this.panY);

    // 에이전트 히트 (역순, 최상위 우선)
    for (const [id, sprite] of [...this.agents.entries()].reverse()) {
      const dx = Math.abs(sprite.x - col);
      const dy = Math.abs(sprite.y - row);
      if (dx < 1.2 && dy < 1.5) {
        return { type: 'agent', id };
      }
    }
    return { type: 'empty' };
  }

  /** 에이전트 상태 업데이트 (WebSocket에서 호출) */
  updateAgentState(agentId, state, detail) {
    const sprite = this.agents.get(agentId);
    if (!sprite) return;
    sprite.onStateChange(state, detail, mapData.waypoints);
  }

  /** 에이전트 알림 배지 설정 */
  setAgentNotification(agentId, count) {
    const sprite = this.agents.get(agentId);
    if (sprite) sprite.notificationCount = count;
  }

  /** 테마 변경 */
  setTheme(themeName) {
    this.theme = getTheme(themeName);
    if (typeof localStorage !== 'undefined') {
      localStorage.setItem('agent-office-theme', themeName);
    }
  }

  /** 줌 레벨 설정 */
  setZoom(level) {
    const cx = this.canvas.width / 2;
    const cy = this.canvas.height / 2;
    const oldZoom = this.zoom;
    this.zoom = Math.min(4, Math.max(1, level));
    const ratio = this.zoom / oldZoom;
    this.panX = cx - (cx - this.panX) * ratio;
    this.panY = cy - (cy - this.panY) * ratio;
  }

  /** 카메라를 맵 중앙에 맞추기 */
  centerCamera() {
    const mapW = mapData.cols * mapData.tileSize * this.zoom;
    const mapH = mapData.rows * mapData.tileSize * this.zoom;
    this.panX = (this.canvas.clientWidth - mapW) / 2;
    this.panY = (this.canvas.clientHeight - mapH) / 2;
  }

  /** 게임 루프 시작 */
  start() {
    this.centerCamera();
    this._lastTime = performance.now();
    this._loop(this._lastTime);
  }

  /** 게임 루프 중지 */
  stop() {
    if (this._animId) {
      cancelAnimationFrame(this._animId);
      this._animId = null;
    }
  }

  _loop(timestamp) {
    const dt = Math.min((timestamp - this._lastTime) / 1000, 0.1); // cap dt to avoid spiral
    this._lastTime = timestamp;

    this._update(dt);
    this._render();

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

  _update(dt) {
    for (const sprite of this.agents.values()) {
      sprite.update(dt);
    }
  }

  _render() {
    const ctx = this.ctx;
    const dpr = window.devicePixelRatio || 1;

    // 캔버스 크기 조정
    const displayW = this.canvas.clientWidth;
    const displayH = this.canvas.clientHeight;
    if (this.canvas.width !== displayW * dpr || this.canvas.height !== displayH * dpr || this._lastDpr !== dpr) {
      this.canvas.width = displayW * dpr;
      this.canvas.height = displayH * dpr;
      this._lastDpr = dpr;
    }
    // setTransform 방식으로 누적 없이 항상 올바른 변환 적용
    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);

    ctx.imageSmoothingEnabled = false;
    ctx.clearRect(0, 0, displayW, displayH);

    // 배경
    ctx.fillStyle = this.theme.wall.color;
    ctx.fillRect(0, 0, displayW, displayH);

    // 1. 타일맵 (바닥 + 벽)
    this.tileMap.render(ctx, this.theme, this.zoom, this.panX, this.panY);

    // 2. Y-sorted: 가구 + 에이전트
    const renderables = [];

    // 가구
    const furnitureItems = this.furnitureRenderer.getRenderables(this.theme, this.zoom, this.panX, this.panY);
    renderables.push(...furnitureItems);

    // 에이전트
    for (const sprite of this.agents.values()) {
      renderables.push({
        zY: sprite.y,
        draw: (ctx2) => sprite.draw(ctx2, this.zoom, this.panX, this.panY, mapData.tileSize)
      });
    }

    // Y좌표 정렬
    renderables.sort((a, b) => a.zY - b.zY);
    for (const item of renderables) {
      item.draw(ctx);
    }

    // 3. 오버레이 (항상 최상위)
    for (const sprite of this.agents.values()) {
      this.overlayRenderer.draw(ctx, sprite, this.theme, this.zoom, this.panX, this.panY, mapData.tileSize);
    }
  }

  /** 드래그 여부 반환 (클릭 이벤트 필터링용) */
  wasDragging() { return this._wasDragging; }

  /** 리사이즈 처리 */
  resize() {
    // 다음 프레임에서 자동 조정됨 (_render에서 크기 체크)
  }

  destroy() {
    this.stop();
    // window 이벤트 리스너 정리
    if (this._onMouseMove) window.removeEventListener('mousemove', this._onMouseMove);
    if (this._onMouseUp) window.removeEventListener('mouseup', this._onMouseUp);
  }
}
