/**
 * ASS 字幕文件生成器
 * ==================
 * 
 * 根据字幕打轴结果生成标准 ASS 格式字幕文件
 */

import { invoke } from '@tauri-apps/api/core';

interface AssDialogue {
  start: string;    // 格式: 0:00:05.12
  end: string;      // 格式: 0:00:10.50
  style: string;
  text: string;
}

export interface AssStyle {
  name: string;
  fontName: string;
  fontSize: number;
  primaryColor: string;    // &H00FFFFFF = 白色
  secondaryColor: string;  // &H000000FF = 红色
  outlineColor: string;    // &H00000000 = 黑色描边
  backColor: string;       // &H00000000 = 黑色阴影
  bold: boolean;
  italic: boolean;
  underline: boolean;
  strikeOut: boolean;
  scaleX: number;
  scaleY: number;
  spacing: number;
  angle: number;
  borderStyle: number;     // 1=描边, 3=透明背景
  outline: number;         // 描边宽度
  shadow: number;          // 阴影深度
  alignment: number;       // 1=左下, 2=中下, 3=右下, 4=左中, 5=中中, 6=右中, 7=左上, 8=中上, 9=右上
  marginL: number;
  marginR: number;
  marginV: number;
}

/**
 * 转换 HTML 颜色 #RRGGBB[AA] 为 ASS 格式 &HAABBGGRR
 * ASS 颜色顺序: AA(alpha) BB GG RR → 和 HTML 的 RR GG BB 相反
 * - #RRGGBB → alpha 固定为 00 (完全不透明)
 * - #RRGGBBAA → 使用提供的 alpha（AA 是 CSS 标准 alpha，ASS alpha 是反的：00=不透明, FF=透明）
 */
export function htmlColorToAss(htmlColor: string): string {
  const hex = htmlColor.replace('#', '');
  if (hex.length === 8) {
    // #RRGGBBAA — CSS alpha 需要反转成 ASS alpha
    const r = hex.slice(0, 2);
    const g = hex.slice(2, 4);
    const b = hex.slice(4, 6);
    const cssAlpha = parseInt(hex.slice(6, 8), 16);
    const assAlpha = (255 - cssAlpha).toString(16).padStart(2, '0');
    return `&H${assAlpha}${b}${g}${r}`;
  }
  const r = hex.slice(0, 2);
  const g = hex.slice(2, 4);
  const b = hex.slice(4, 6);
  return `&H00${b}${g}${r}`;
}

// 默认样式 - 适合抖音/竖屏视频
// 字体名必须与ASS 中的字体名一致
const DEFAULT_ASS_STYLE: AssStyle = {
  name: 'Default',
  fontName: 'DouyinSans',
  fontSize: 72,
  primaryColor: '&H00FFFFFF',     // 白色
  secondaryColor: '&H000000FF',   // 红色
  outlineColor: '&H00000000',     // 黑色描边
  backColor: '&H00000000',        // 黑色阴影
  bold: true,
  italic: false,
  underline: false,
  strikeOut: false,
  scaleX: 100,
  scaleY: 100,
  spacing: 0,
  angle: 0,
  borderStyle: 1,    // 描边
  outline: 4,        // 描边宽度
  shadow: 0,
  alignment: 2,      // 底部居中
  marginL: 180,      // 左右留白
  marginR: 180,
  marginV: 480,      // 距离底部
};

/**
 * 将毫秒转换为 ASS 时间格式 (H:MM:SS.cc)
 */
function msToAssTime(ms: number): string {
  const totalSeconds = Math.floor(ms / 1000);
  const hours = Math.floor(totalSeconds / 3600);
  const minutes = Math.floor((totalSeconds % 3600) / 60);
  const seconds = totalSeconds % 60;
  const centiseconds = Math.floor((ms % 1000) / 10);
  
  return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${centiseconds.toString().padStart(2, '0')}`;
}

/**
 * 将 borderStyle=3（背景色块）转换为 borderStyle=1 + 粗描边
 * 当前 FFmpeg 嵌入版 libass 不支持 BorderStyle=3，需用粗描边模拟背景色效果
 */
function convertBorderStyle3(style: AssStyle): AssStyle {
  if (style.borderStyle !== 3) {return style;}
  const outline = Math.max(6, Math.round(style.fontSize * 0.12));
  return {
    ...style,
    borderStyle: 1,
    outline,
    outlineColor: style.backColor,
  };
}

/**
 * 生成 ASS 文件内容
 */
function generateAssContent(
  dialogues: Array<{ start: string; end: string; style: string; text: string }>,
  styles: AssStyle[],
  width: number = 1080,
  height: number = 1920
): string {
  const scriptInfo = `[Script Info]
Title: Meijiaka Auto Generated Subtitle
ScriptType: v4.00+
PlayResX: ${width}
PlayResY: ${height}
Timer: 100.0000

`;

  const stylesHeader = `[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
`;

  const stylesBody = styles.map(s => {
    const ns = convertBorderStyle3(s);
    return `Style: ${ns.name},${ns.fontName},${ns.fontSize},${ns.primaryColor},${ns.secondaryColor},${ns.outlineColor},${ns.backColor},${ns.bold ? 1 : 0},${ns.italic ? 1 : 0},${ns.underline ? 1 : 0},${ns.strikeOut ? 1 : 0},${ns.scaleX},${ns.scaleY},${ns.spacing},${ns.angle},${ns.borderStyle},${ns.outline},${ns.shadow},${ns.alignment},${ns.marginL},${ns.marginR},${ns.marginV},1`;
  }).join('\n');

  const eventsHeader = `\n[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
`;

  const events = dialogues.map(d =>
    `Dialogue: 0,${d.start},${d.end},${d.style},,0,0,0,,${d.text}`
  ).join('\n');

  return scriptInfo + stylesHeader + stylesBody + eventsHeader + events;
}

/**
 * 去掉字幕文本句末的标点符号
 * 打轴会把一句话分成多段，每一段末尾都可能有标点，需要全部删除
 */
export function trimTrailingPunctuation(text: string): string {
  // 匹配末尾所有标点符号：。！？．…；,!、，?
  return text.replace(/[。！？．…；,!、，?]+$/, '');
}

/**
 * 从打轴结果生成 ASS 内容（支持大标题/小标题）
 */
export function generateAssFromAlignment(
  utterances: Array<{ text: string; startTime: number; endTime: number }>,
  options: {
    subtitleStyle?: Partial<AssStyle>;
    mainTitle?: string;
    subTitle?: string;
    mainTitleStyle?: Partial<AssStyle>;
    subTitleStyle?: Partial<AssStyle>;
    videoDurationMs?: number;
    /** 是否将大标题/小标题包含在 ASS 中（默认 true） */
    includeTitlesInAss?: boolean;
  } = {}
): string {
  const { subtitleStyle, mainTitle, subTitle, mainTitleStyle, subTitleStyle, videoDurationMs, includeTitlesInAss = true } = options;

  const mergedSubtitleStyle = { ...DEFAULT_ASS_STYLE, ...subtitleStyle, name: 'Default' };

  const styles: AssStyle[] = [mergedSubtitleStyle];
  const dialogues: AssDialogue[] = utterances.map(u => ({
    start: msToAssTime(u.startTime),
    end: msToAssTime(u.endTime),
    style: 'Default',
    text: trimTrailingPunctuation(u.text),
  }));

  // 大标题：覆盖整个视频时长，显示在顶部
  if (includeTitlesInAss && mainTitle && mainTitleStyle && videoDurationMs) {
    styles.push({ ...DEFAULT_ASS_STYLE, ...mainTitleStyle, name: 'MainTitle' });
    dialogues.push({
      start: '0:00:00.00',
      end: msToAssTime(videoDurationMs),
      style: 'MainTitle',
      text: mainTitle,
    });
  }

  // 小标题：覆盖整个视频时长，显示在大标题下方
  if (includeTitlesInAss && subTitle && subTitleStyle && videoDurationMs) {
    styles.push({ ...DEFAULT_ASS_STYLE, ...subTitleStyle, name: 'SubTitle' });
    dialogues.push({
      start: '0:00:00.00',
      end: msToAssTime(videoDurationMs),
      style: 'SubTitle',
      text: subTitle,
    });
  }

  return generateAssContent(dialogues, styles);
}

/**
 * 生成封面标题 ASS 内容
 *
 * 标题固定在中上位置，允许换行
 */

/**
 * 保存 ASS 文件到本地
 */
export async function saveAssFile(
  projectId: string,
  filename: string,
  content: string
): Promise<string> {
  // 将内容转为 Base64
  const encoder = new TextEncoder();
  const data = encoder.encode(content);
  const base64 = btoa(String.fromCharCode(...data));

  const result = await invoke<{ code: number; data?: string; message: string }>('save_project_asset', {
    projectId,
    filename,
    base64Data: base64,
  });

  if (result.code !== 200 || !result.data) {
    throw new Error(result.message);
  }

  return result.data;
}
