/**
 * Canvas 2D 字幕渲染 Hook
 * ========================
 *
 * 替代 assjs + CSS 标题叠加，统一使用 Canvas 2D 绘制大标题/小标题/字幕。
 * 确保预览侧使用同一渲染引擎，与 FFmpeg libass 的描边几何更接近。
 *
 * 坐标系：以 ASS 的 PlayResY=1920 为基准，按 Canvas 显示高度缩放。
 */

import { useEffect, useRef, useCallback } from 'react';
import type { AssStyle } from '../utils/assGenerator';
import {
  PLAY_RES_Y,
  CANVAS_FONT_COMPENSATION,
  setCanvasFont,
  drawTextBlock,
  drawTextLine,
  truncateText,
  loadCustomFont,
} from '../utils/canvasSubtitleDrawer';

interface Utterance {
  text: string;
  startTime: number; // ms
  endTime: number;   // ms
}

interface UseCanvasSubtitleRendererOptions {
  videoRef: React.RefObject<HTMLVideoElement | null>;
  canvasRef: React.RefObject<HTMLCanvasElement | null>;
  utterances: Utterance[];
  mainTitle?: string;
  subTitle?: string;
  subtitleStyle: Partial<AssStyle>;
  mainTitleStyle?: Partial<AssStyle>;
  subTitleStyle?: Partial<AssStyle>;
  enabled: boolean;
}

export function useCanvasSubtitleRenderer(options: UseCanvasSubtitleRendererOptions) {
  const {
    videoRef,
    canvasRef,
    utterances,
    mainTitle,
    subTitle,
    subtitleStyle,
    mainTitleStyle,
    subTitleStyle,
    enabled,
  } = options;

  const rafRef = useRef<number | null>(null);
  const fontLoadedRef = useRef(false);

  const drawFrame = useCallback(() => {
    const video = videoRef.current;
    const canvas = canvasRef.current;
    if (!video || !canvas || !enabled) {return;}

    const ctx = canvas.getContext('2d');
    if (!ctx) {return;}

    // 获取显示尺寸
    const rect = canvas.getBoundingClientRect();
    const displayWidth = rect.width;
    const displayHeight = rect.height;
    if (displayWidth === 0 || displayHeight === 0) {return;}

    // 高 DPI 适配
    const dpr = window.devicePixelRatio || 1;
    if (canvas.width !== Math.floor(displayWidth * dpr) || canvas.height !== Math.floor(displayHeight * dpr)) {
      canvas.width = Math.floor(displayWidth * dpr);
      canvas.height = Math.floor(displayHeight * dpr);
    }

    ctx.save();
    ctx.scale(dpr, dpr);

    // 清空画布
    ctx.clearRect(0, 0, displayWidth, displayHeight);

    // 计算缩放比例（基于高度）
    // 扣除 <video controls> 控制条高度（约 40px），确保预览与视频画面比例一致
    const VIDEO_CONTROLS_HEIGHT = 40;
    const scale = Math.max(1, displayHeight - VIDEO_CONTROLS_HEIGHT) / PLAY_RES_Y;

    const currentTimeMs = video.currentTime * 1000;

    // ---- 绘制大标题（全视频时长，顶部居中，单行截断） ----
    // ASS alignment=8: marginV 是文字块顶部到画面顶部的距离
    // Canvas fillText y 是基线，基线 = 顶部 + ascent
    if (mainTitle && mainTitleStyle) {
      setCanvasFont(ctx, mainTitleStyle, scale, 1.0);
      const marginV = (mainTitleStyle.marginV ?? 360) * scale;
      const fontSize = (mainTitleStyle.fontSize ?? 104) * scale;
      const metrics = ctx.measureText(mainTitle);
      const ascent = metrics.actualBoundingBoxAscent || fontSize * 0.72;
      const startY = marginV + ascent;
      drawTextBlock(ctx, mainTitle, displayWidth / 2, startY, mainTitleStyle, scale, displayWidth, 1);
    }

    // ---- 绘制小标题（全视频时长，在大标题下方，单行截断） ----
    if (subTitle && subTitleStyle) {
      setCanvasFont(ctx, subTitleStyle, scale, 1.0);
      const marginV = (subTitleStyle.marginV ?? 480) * scale;
      const fontSize = (subTitleStyle.fontSize ?? 88) * scale;
      const metrics = ctx.measureText(subTitle);
      const ascent = metrics.actualBoundingBoxAscent || fontSize * 0.72;
      const startY = marginV + ascent;
      drawTextBlock(ctx, subTitle, displayWidth / 2, startY, subTitleStyle, scale, displayWidth, 1);
    }

    // ---- 绘制字幕（按时间轴，单行截断） ----
    if (utterances.length > 0) {
      setCanvasFont(ctx, subtitleStyle, scale);
      const activeUtterances = utterances.filter(
        (u) => currentTimeMs >= u.startTime && currentTimeMs <= u.endTime
      );

      for (const u of activeUtterances) {
        const marginV = (subtitleStyle.marginV ?? 480) * scale;
        const fontSize = (subtitleStyle.fontSize ?? 64) * scale * CANVAS_FONT_COMPENSATION;
        const maxWidth = displayWidth - 40 * scale;

        // 去掉 ASS 换行符，超长截断，只显示单行
        const text = u.text.replace(/\\N/g, '');
        const truncated = truncateText(ctx, text, maxWidth);

        // ASS alignment=2: marginV 是文字块底部到画面底部的距离
        // Canvas fillText y 是基线，基线 = 底部 - marginV - descent
        const metrics = ctx.measureText(truncated);
        const descent = metrics.actualBoundingBoxDescent || fontSize * 0.28;
        const y = displayHeight - marginV - descent;

        drawTextLine(ctx, truncated, displayWidth / 2, y, subtitleStyle, scale, displayWidth);
      }
    }

    ctx.restore();
  }, [enabled, utterances, mainTitle, subTitle, subtitleStyle, mainTitleStyle, subTitleStyle, videoRef, canvasRef]);

  useEffect(() => {
    if (!enabled) {return;}

    // 加载字体
    if (!fontLoadedRef.current) {
      loadCustomFont().then(() => {
        fontLoadedRef.current = true;
        drawFrame();
      });
    }

    const video = videoRef.current;
    if (!video) {return;}

    const onFrame = () => {
      drawFrame();
      if (!video.paused) {
        rafRef.current = requestAnimationFrame(onFrame);
      }
    };

    const onPlay = () => {
      if (rafRef.current) {cancelAnimationFrame(rafRef.current);}
      rafRef.current = requestAnimationFrame(onFrame);
    };

    const onPause = () => {
      if (rafRef.current) {
        cancelAnimationFrame(rafRef.current);
        rafRef.current = null;
      }
      drawFrame();
    };

    // 初始绘制一帧（静态）
    drawFrame();

    video.addEventListener('play', onPlay);
    video.addEventListener('pause', onPause);
    video.addEventListener('seeked', drawFrame);
    video.addEventListener('timeupdate', drawFrame);

    return () => {
      if (rafRef.current) {cancelAnimationFrame(rafRef.current);}
      video.removeEventListener('play', onPlay);
      video.removeEventListener('pause', onPause);
      video.removeEventListener('seeked', drawFrame);
      video.removeEventListener('timeupdate', drawFrame);
    };
  }, [enabled, drawFrame, videoRef]);

  // 当样式或内容变化时，强制重绘
  useEffect(() => {
    if (enabled) {
      drawFrame();
    }
  }, [enabled, drawFrame]);
}

export default useCanvasSubtitleRenderer;
