/**
 * Fabric.js 封面渲染 Hook
 * ========================
 *
 * 使用 Fabric.js v6 在 Canvas 上渲染封面预览，支持：
 * - 背景图加载（居中裁剪填充）
 * - 双标题模板 / 标题+标签模板
 * - 文字描边阴影效果
 * - PNG 导出
 */

import { useRef, useCallback, useEffect } from 'react';
import { Canvas, FabricText, FabricImage, Shadow } from 'fabric';
import { getLocalFileUrl } from '../utils/fileUrl';
import { loadCustomFont } from '../utils/canvasSubtitleDrawer';

// 预览显示尺寸 (9:16 竖屏，337×600)
const DISPLAY_WIDTH = 337;
const DISPLAY_HEIGHT = 600;
// 内部渲染尺寸（用于导出，1080×1920 高清）
const CANVAS_WIDTH = 1080;
const CANVAS_HEIGHT = 1920;

type CoverTemplate = 'dual-title';

interface CoverDesignConfig {
  template: CoverTemplate;
  backgroundImage: string | null;
  mainTitle: string;
  subtitle: string;
  avatarImage?: string | null;
}

interface TemplateDef {
  mainTitle: {
    fontSize: number;
    fill: string;
    top: number;
    fontWeight: string;
    shadow: Shadow;
  };
  subtitle: {
    fontSize: number;
    fill: string;
    top: number;
    shadow: Shadow;
  };
}

const FONT_FAMILY = '"DouyinSansBold", "PingFang SC", "Microsoft YaHei", sans-serif';

/**
 * 加载本地图片文件为 HTMLImageElement
 * 使用 Rust 校验 + convertFileSrc 安全访问本地文件
 */
async function loadLocalImage(imagePath: string): Promise<HTMLImageElement> {
  const url = await getLocalFileUrl(imagePath);

  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => resolve(img);
    img.onerror = (err) => reject(err);
    img.src = url;
  });
}

const TEMPLATES: Record<CoverTemplate, TemplateDef> = {
  'dual-title': {
    mainTitle: {
      fontSize: 144,
      fill: '#FFD700',
      top: 200,
      fontWeight: 'bold',
      shadow: new Shadow({
        color: 'rgba(0,0,0,0.9)',
        blur: 30,
        offsetX: 8,
        offsetY: 8,
      }),
    },
    subtitle: {
      fontSize: 72,
      fill: '#FF8C00',
      top: 380,
      shadow: new Shadow({
        color: 'rgba(0,0,0,0.85)',
        blur: 12,
        offsetX: 5,
        offsetY: 5,
      }),
    },
  },
};

function wrapTextByWidth(
  text: string,
  maxWidth: number,
  fontSize: number
): string[] {
  if (!text.trim()) {return [];}

  // 把中英文逗号、顿号替换为换行（语义断句）
  text = text
    .replace(/，/g, '\n')
    .replace(/,/g, '\n')
    .replace(/、/g, '\n');

  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d')!;
  ctx.font = `${fontSize}px ${FONT_FAMILY}`;

  // 按换行分割，再对每行按宽度自动换行
  const paragraphs = text.split('\n');
  const lines: string[] = [];

  for (const paragraph of paragraphs) {
    const trimmed = paragraph.trim();
    if (!trimmed) {continue;}
    const chars = trimmed.split('');
    let currentLine = '';

    for (const char of chars) {
      const testLine = currentLine + char;
      const metrics = ctx.measureText(testLine);
      if (metrics.width > maxWidth && currentLine.length > 0) {
        lines.push(currentLine);
        currentLine = char;
      } else {
        currentLine = testLine;
      }
    }
    if (currentLine) {lines.push(currentLine);}
  }
  return lines;
}

export function useCoverFabric() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const fabricCanvasRef = useRef<Canvas | null>(null);

  // 初始化 Fabric Canvas
  const initCanvas = useCallback(() => {
    if (!canvasRef.current || fabricCanvasRef.current) {return;}

    const canvas = new Canvas(canvasRef.current, {
      width: CANVAS_WIDTH,
      height: CANVAS_HEIGHT,
      backgroundColor: '#1a1a2e',
      selection: false,
      interactive: false,
    });

    // 设置 Canvas 内部渲染尺寸（高分辨率）
    // 同时设置 CSS 显示尺寸（小尺寸预览）
    canvas.setDimensions(
      {
        width: CANVAS_WIDTH,
        height: CANVAS_HEIGHT,
      },
      {
        cssOnly: false,
      }
    );
    canvas.setDimensions(
      {
        width: DISPLAY_WIDTH,
        height: DISPLAY_HEIGHT,
      },
      {
        cssOnly: true,
      }
    );

    fabricCanvasRef.current = canvas;
  }, []);

  // 加载背景图（支持本地路径或 HTTP/相对 URL）
  const loadBackground = useCallback(
    async (canvas: Canvas, imagePath: string): Promise<void> => {
      try {
        let img: HTMLImageElement;

        const isRemoteUrl =
          imagePath.startsWith('http://') ||
          imagePath.startsWith('https://') ||
          imagePath.startsWith('//');

        if (isRemoteUrl) {
          // 网络图片：HTTP / HTTPS / 协议相对 URL
          img = await new Promise<HTMLImageElement>((resolve, reject) => {
            const image = new Image();
            image.crossOrigin = 'anonymous';
            image.onload = () => resolve(image);
            image.onerror = (e) => reject(e);
            image.src = imagePath;
          });
        } else {
          // 本地文件路径（支持 macOS /Users/...、Linux /home/...、Windows C:\...、UNC \\server\...）
          img = await loadLocalImage(imagePath);
        }

        const fabricImg = new FabricImage(img);
        // 使用 Math.min 确保图片完整显示在 Canvas 内，不会被过度放大
        const scale = Math.min(
          CANVAS_WIDTH / (fabricImg.width || 1),
          CANVAS_HEIGHT / (fabricImg.height || 1)
        );
        fabricImg.scale(scale);
        // 居中定位
        const scaledWidth = (fabricImg.width || 1) * scale;
        const scaledHeight = (fabricImg.height || 1) * scale;
        fabricImg.set({
          left: (CANVAS_WIDTH - scaledWidth) / 2,
          top: (CANVAS_HEIGHT - scaledHeight) / 2,
          originX: 'left',
          originY: 'top',
          selectable: false,
          evented: false,
        });
        canvas.add(fabricImg);
        canvas.sendObjectToBack(fabricImg);
        canvas.renderAll();
      } catch {
        // no-op: 背景图加载失败已在内部处理
      }
    },
    []
  );

  // 加载封面形象（叠加在背景之上，文字之下）
  const loadAvatarImage = useCallback(
    async (canvas: Canvas, imageUrl: string): Promise<number> => {
      const img = await new Promise<HTMLImageElement>((resolve, reject) => {
        const image = new Image();
        image.crossOrigin = 'anonymous';
        image.onload = () => resolve(image);
        image.onerror = (e) => reject(e);
        image.src = imageUrl;
      });

      const fabricImg = new FabricImage(img);
      // 计算缩放：宽度/高度最大占画布的 68%
      const maxWidth = CANVAS_WIDTH * 0.68;
      const maxHeight = CANVAS_HEIGHT * 0.68;
      const scale = Math.min(
        maxWidth / (fabricImg.width || 1),
        maxHeight / (fabricImg.height || 1)
      );
      fabricImg.scale(scale);

      const scaledHeight = (fabricImg.height || 1) * scale;

      // 左下区域定位：左侧留边，底部与背景对齐
      const leftMargin = 40;
      fabricImg.set({
        left: leftMargin,
        top: CANVAS_HEIGHT - scaledHeight,
        originX: 'left',
        originY: 'top',
        selectable: false,
        evented: false,
      });
      canvas.add(fabricImg);
      canvas.renderAll();

      return scaledHeight;
    },
    []
  );

  // 渲染封面
  const renderCover = useCallback(
    async (config: CoverDesignConfig) => {
      const canvas = fabricCanvasRef.current;
      if (!canvas) {return;}

      // 确保自定义字体已加载（有缓存检查，不会重复加载）
      await loadCustomFont().catch(() => {
      });

      canvas.clear();
      canvas.backgroundColor = '#1a1a2e';

      // 1. 背景图
      if (config.backgroundImage) {
        try {
          await loadBackground(canvas, config.backgroundImage);
        } catch {
          // no-op: 背景图加载失败已在内部处理
        }
      }

      // 2. 封面形象（叠加在背景之上）
      if (config.avatarImage) {
        try {
          await loadAvatarImage(canvas, config.avatarImage);
        } catch (err) {
          console.warn('[useCoverFabric] 封面形象加载失败:', err);
        }
      }

      const template = TEMPLATES[config.template];

      // 预计算主副标题行数
      const mainTitleLines = config.mainTitle.trim()
        ? wrapTextByWidth(config.mainTitle.trim(), CANVAS_WIDTH - 120, template.mainTitle.fontSize).slice(0, 2)
        : [];
      const subtitleLines = config.subtitle.trim()
        ? wrapTextByWidth(config.subtitle.trim(), CANVAS_WIDTH - 120, template.subtitle.fontSize).slice(0, 2)
        : [];

      const mainTitleLineHeight = template.mainTitle.fontSize * 1.2;
      const subtitleLineHeight = template.subtitle.fontSize * 1.5;

      // 文字位置固定，不再根据封面形象高度和文字行数动态计算
      const mainTitleTop = template.mainTitle.top;
      const subtitleTop = template.subtitle.top;

      // 3. 主标题（放在人物上方最外侧）
      if (mainTitleLines.length > 0) {
        mainTitleLines.forEach((line, i) => {
          const text = new FabricText(line, {
            left: CANVAS_WIDTH / 2,
            top: mainTitleTop + i * mainTitleLineHeight,
            fontSize: template.mainTitle.fontSize,
            fill: template.mainTitle.fill,
            fontWeight: template.mainTitle.fontWeight,
            fontFamily: FONT_FAMILY,
            textAlign: 'center',
            originX: 'center',
            originY: 'top',
            selectable: false,
            evented: false,
            shadow: template.mainTitle.shadow,
          });
          canvas.add(text);
        });
      }

      // 4. 副标题（放在人物上方，主标题下方）
      if (subtitleLines.length > 0) {
        subtitleLines.forEach((line, i) => {
          const text = new FabricText(line, {
            left: CANVAS_WIDTH / 2,
            top: subtitleTop + i * subtitleLineHeight,
            fontSize: template.subtitle.fontSize,
            fill: template.subtitle.fill,
            fontWeight: 'bold',
            stroke: '#000000',
            strokeWidth: 5,
            paintFirst: 'stroke',
            fontFamily: FONT_FAMILY,
            textAlign: 'center',
            originX: 'center',
            originY: 'top',
            selectable: false,
            evented: false,
            shadow: template.subtitle.shadow,
          });
          canvas.add(text);
        });
      }

      canvas.renderAll();
    },
    [loadBackground, loadAvatarImage]
  );

  // 导出 PNG
  const exportPng = useCallback((): string => {
    const canvas = fabricCanvasRef.current;
    if (!canvas) {return '';}
    return canvas.toDataURL({ format: 'png', quality: 1, multiplier: 1 });
  }, []);

  // 销毁
  const destroy = useCallback(() => {
    fabricCanvasRef.current?.dispose();
    fabricCanvasRef.current = null;
  }, []);

  // 组件卸载时清理
  useEffect(() => {
    return () => {
      destroy();
    };
  }, [destroy]);

  return {
    canvasRef,
    initCanvas,
    renderCover,
    exportPng,
    destroy,
  };
}
