/**
 * LINE 官方导出 TXT 格式解析器
 * 支持私聊和群聊，支持多语言导出（EN / ZH-CN / ZH-TW / JA）
 *
 * 格式特征：
 * - 头部格式（私聊和群聊相同）：
 *   Line 1: [LINE] {name}的聊天记录 / Chat history with/in {name} / ...
 *   Line 2: 保存日期: YYYY/MM/DD HH:MM / Saved on: ...
 *   Line 3: (空行)
 * - 日期行：YYYY/MM/DD（星期）或 Day, MM/DD/YYYY
 * - 消息格式：TIME\t{sender}\t{content}（Tab 分隔）
 * - 系统消息：TIME\t\t{content}（双 Tab，无发送者）
 * - 时间格式：HH:MM / 上午|下午HH:MM / 午前|午後HH:MM / HH:MMam|pm
 * - 多行消息：用双引号包裹
 *
 * 私聊 vs 群聊区分：
 * - EN: "Chat history with {name}" (私聊) vs "Chat history in {name}" (群聊)
 * - JA: "{name}とのトーク履歴" (私聊) vs "{name}のトーク履歴" (群聊)
 * - ZH-CN: "与{name}的聊天记录" (私聊) vs "{name}的聊天记录" (群聊)
 * - ZH-TW: "與{name}的聊天記錄" (私聊) vs "{name}的聊天記錄" (群聊)
 */

import * as fs from 'fs'
import * as path from 'path'
import { KNOWN_PLATFORMS, ChatType, MessageType } from '@openchatlab/shared-types'
import type {
  FormatFeature,
  FormatModule,
  Parser,
  ParseOptions,
  ParseEvent,
  ParsedMeta,
  ParsedMember,
  ParsedMessage,
} from '../types'
import { getFileSize, createProgress } from '../utils'

// ==================== 特征定义 ====================

export const feature: FormatFeature = {
  id: 'line-native-txt',
  name: 'LINE 官方导出 TXT',
  platform: KNOWN_PLATFORMS.LINE,
  priority: 35,
  extensions: ['.txt'],
  signatures: {
    head: [
      // 头部标识（多语言）
      /^\[LINE\] /m,
      /^(?:\[LINE\] )?Chat history (?:with|in) /m,
      // Tab 分隔的消息格式（支持多种时间格式）
      /^((?:上午|下午|午前|午後)?\d{1,2}:\d{2}(?:[AaPp][Mm])?)\t[^\t\n]+\t/m,
      // 空格分隔的消息格式（部分 LINE 导出）
      /^((?:上午|下午|午前|午後)?\d{1,2}:\d{2}(?:[AaPp][Mm])?) [^\s]+ /m,
      // LINE 独有的日期行格式：YYYY.MM.DD DayOfWeek（英文星期全称）
      /^\d{4}\.\d{2}\.\d{2}\s+(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)/m,
      // LINE 日文/中文日期行格式：YYYY/M/D(曜日)
      /^\d{4}\/\d{1,2}\/\d{1,2}[（(][月火水木金土日]/m,
      // LINE 中文日期行格式：YYYY/M/D周X
      /^\d{4}\/\d{1,2}\/\d{1,2}周/m,
    ],
    // 文件名特征：[LINE] 出现在文件名中
    filename: [/\[LINE\]/i],
  },
}

// ==================== 辅助函数 ====================

/**
 * 从文件名提取聊天名称
 */
function extractNameFromFilePath(filePath: string): string {
  const basename = path.basename(filePath, '.txt')
  // 移除 [LINE] 前缀
  const name = basename.replace(/^\[LINE\]\s*/i, '').trim()
  return name || '未知聊天'
}

/**
 * 从头部提取聊天名称和类型
 * 支持：英文、日文、简体中文、繁体中文
 */
function extractNameFromHeader(header: string): { name: string; isGroup: boolean } | null {
  // ===== 英文 =====
  // 私聊：Chat history with {name}
  const enPrivateMatch = header.match(/^(?:\[LINE\] )?Chat history with (.+)$/m)
  if (enPrivateMatch) return { name: enPrivateMatch[1].trim(), isGroup: false }
  // 群聊：Chat history in {name}
  const enGroupMatch = header.match(/^(?:\[LINE\] )?Chat history in (.+)$/m)
  if (enGroupMatch) return { name: enGroupMatch[1].trim(), isGroup: true }

  // ===== 日文 =====
  // 私聊：{name}とのトーク履歴
  const jaPrivateMatch = header.match(/^\[LINE\] (.+)とのトーク履歴/)
  if (jaPrivateMatch) return { name: jaPrivateMatch[1].trim(), isGroup: false }
  // 群聊：{name}のトーク履歴
  const jaGroupMatch = header.match(/^\[LINE\] (.+)のトーク履歴/)
  if (jaGroupMatch) return { name: jaGroupMatch[1].trim(), isGroup: true }

  // ===== 简体中文 =====
  // 私聊：与{name}的聊天记录
  const zhCnPrivateMatch = header.match(/^\[LINE\] 与(.+)的聊天记录/)
  if (zhCnPrivateMatch) return { name: zhCnPrivateMatch[1].trim(), isGroup: false }
  // 群聊：{name}的聊天记录
  const zhCnGroupMatch = header.match(/^\[LINE\] (.+)的聊天记录/)
  if (zhCnGroupMatch) return { name: zhCnGroupMatch[1].trim(), isGroup: true }

  // ===== 繁体中文 =====
  // 私聊：與{name}的聊天記錄
  const zhTwPrivateMatch = header.match(/^\[LINE\] 與(.+)的聊天記錄/)
  if (zhTwPrivateMatch) return { name: zhTwPrivateMatch[1].trim(), isGroup: false }
  // 群聊：{name}的聊天記錄
  const zhTwGroupMatch = header.match(/^\[LINE\] (.+)的聊天記錄/)
  if (zhTwGroupMatch) return { name: zhTwGroupMatch[1].trim(), isGroup: true }

  return null
}

/**
 * 日期行正则模式
 */
const DATE_PATTERNS = [
  // 2025.12.10 Wednesday
  /^(\d{4})\.(\d{2})\.(\d{2})\s+(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)?/,
  // 2026/1/30周五 or 2026/1/30(金)
  /^(\d{4})\/(\d{1,2})\/(\d{1,2})/,
  // Fri, 1/30/2026
  /^[A-Za-z]+,\s*(\d{1,2})\/(\d{1,2})\/(\d{4})/,
]

/**
 * 尝试解析日期行
 */
function parseDateLine(line: string): Date | null {
  for (const pattern of DATE_PATTERNS) {
    const match = line.match(pattern)
    if (match) {
      // 根据不同格式提取年月日
      if (pattern === DATE_PATTERNS[0] || pattern === DATE_PATTERNS[1]) {
        // YYYY.MM.DD or YYYY/M/D
        const year = parseInt(match[1])
        const month = parseInt(match[2]) - 1
        const day = parseInt(match[3])
        return new Date(year, month, day)
      } else if (pattern === DATE_PATTERNS[2]) {
        // M/D/YYYY
        const month = parseInt(match[1]) - 1
        const day = parseInt(match[2])
        const year = parseInt(match[3])
        return new Date(year, month, day)
      }
    }
  }
  return null
}

/**
 * 消息行正则模式
 * 时间格式：HH:MM / HH:MMam|pm / 上午|下午|午前|午後HH:MM
 */
// 私聊/群聊（有发送者）：TIME\t{name}\t{content}
const PRIVATE_MSG_PATTERN = /^((?:上午|下午|午前|午後)?\d{1,2}:\d{2}(?:[AaPp][Mm])?)\t([^\t]+)\t(.*)$/
// 群聊：HH:MM {name} {content} (已废弃，实际都用 Tab 分隔)
const GROUP_MSG_PATTERN = /^((?:上午|下午|午前|午後)?\d{1,2}:\d{2}(?:[AaPp][Mm])?) ([^\s]+) (.*)$/
// 系统消息：双 Tab（无发送者），如「下午07:04\t\tXXX已加入群組」
const SYSTEM_MSG_PATTERN = /^((?:上午|下午|午前|午後)?\d{1,2}:\d{2}(?:[AaPp][Mm])?)\t\t(.+)$/

/**
 * 特殊消息类型映射（多语言：EN / ZH-CN / ZH-TW / JA）
 */
const SPECIAL_MESSAGE_TYPES: Record<string, MessageType> = {
  // 图片 / Photo
  '[Photo]': MessageType.IMAGE, // EN
  '[照片]': MessageType.IMAGE, // ZH-CN / ZH-TW
  '[写真]': MessageType.IMAGE, // JA
  Photos: MessageType.IMAGE, // EN (fallback)

  // 语音 / Voice
  '[Voice message]': MessageType.VOICE, // EN
  '[语音信息]': MessageType.VOICE, // ZH-CN
  '[語音訊息]': MessageType.VOICE, // ZH-TW
  '[ボイスメッセージ]': MessageType.VOICE, // JA
  Audio: MessageType.VOICE, // EN (fallback)

  // 视频 / Video
  '[Video]': MessageType.VIDEO, // EN
  '[视频]': MessageType.VIDEO, // ZH-CN
  '[影片]': MessageType.VIDEO, // ZH-TW
  '[動画]': MessageType.VIDEO, // JA
  Videos: MessageType.VIDEO, // EN (fallback)

  // 文件 / File
  '[File]': MessageType.FILE, // EN
  '[文件]': MessageType.FILE, // ZH-CN
  '[檔案]': MessageType.FILE, // ZH-TW
  '[ファイル]': MessageType.FILE, // JA

  // 贴纸 / Sticker
  '[Sticker]': MessageType.EMOJI, // EN
  '[贴图]': MessageType.EMOJI, // ZH-CN
  '[貼圖]': MessageType.EMOJI, // ZH-TW
  '[スタンプ]': MessageType.EMOJI, // JA
  Stickers: MessageType.EMOJI, // EN (fallback)

  // 位置 / Location
  '[Location]': MessageType.LOCATION, // EN
  '[位置]': MessageType.LOCATION, // ZH-CN / ZH-TW
  '[位置情報]': MessageType.LOCATION, // JA

  // 记事本 / Notes
  '[Notes]': MessageType.TEXT, // EN
  '[记事本]': MessageType.TEXT, // ZH-CN
  '[記事本]': MessageType.TEXT, // ZH-TW
  '[ノート]': MessageType.TEXT, // JA
}

/**
 * 检测消息类型
 */
function detectMessageType(content: string): MessageType {
  // 检查特殊消息类型
  for (const [pattern, type] of Object.entries(SPECIAL_MESSAGE_TYPES)) {
    if (content === pattern || content.startsWith(pattern)) {
      return type
    }
  }

  // 检查 [null] 开头的位置消息
  if (content.startsWith('[null]') && content.includes('maps.google.com')) {
    return MessageType.LOCATION
  }

  // 检查系统消息（多语言：EN / ZH-CN / ZH-TW / JA）
  if (
    // --- 加入群组 / Join group ---
    content.includes(' joined the group') || // EN
    content.includes('已加入该群') || // ZH-CN
    content.includes('已加入群組') || // ZH-TW
    content.includes('がグループに参加しました') || // JA
    // --- 拉人进群 / Added to group ---
    content.includes(' added ') || // EN
    content.includes(' to the group') || // EN
    content.includes('已将') || // ZH-CN
    content.includes('添加至群') || // ZH-CN
    content.includes('添加到群') || // ZH-CN (另一格式)
    content.includes('已新增') || // ZH-TW
    content.includes('至群組') || // ZH-TW
    content.includes('をグループに追加しました') || // JA
    // --- 退出群组 / Left group ---
    content.includes(' left the group') || // EN
    content.includes('已退群') || // ZH-CN
    content.includes('已離開群組') || // ZH-TW
    content.includes('がグループを退会しました') || // JA
    // --- 设定公告 / Announcement ---
    content.includes('made an announcement') || // EN
    content.includes('发布了通告') || // ZH-CN
    content.includes('已設定公告') || // ZH-TW
    content.includes('がアナウンスしました') || // JA
    // --- 收回讯息 / Unsent message ---
    content.includes('unsent a message') || // EN
    content === 'Message unsent.' || // EN
    content.includes('撤回了一条消息') || // ZH-CN
    content.includes('已收回訊息') || // ZH-TW
    content.includes('送信を取り消しました') || // JA
    // --- 其他 / Others ---
    content.startsWith('Auto-reply') // EN 自动回复
  ) {
    return MessageType.SYSTEM
  }

  // 检查链接
  if (content.match(/^https?:\/\//)) {
    return MessageType.LINK
  }

  return MessageType.TEXT
}

// ==================== 解析器实现 ====================

async function* parseLINE(options: ParseOptions): AsyncGenerator<ParseEvent, void, unknown> {
  const { filePath, batchSize = 5000, onProgress, onLog } = options

  const totalBytes = getFileSize(filePath)
  let messagesProcessed = 0

  // 发送初始进度
  const initialProgress = createProgress('parsing', 0, totalBytes, 0, '')
  yield { type: 'progress', data: initialProgress }
  onProgress?.(initialProgress)

  onLog?.('info', `开始解析 LINE 导出文件，大小: ${(totalBytes / 1024 / 1024).toFixed(2)} MB`)

  // 读取整个文件（LINE 导出通常不大）
  const content = fs.readFileSync(filePath, 'utf-8')
  // 处理 Windows 换行符 (\r\n)
  const lines = content.split('\n').map((line) => line.replace(/\r$/, ''))

  // 解析状态
  let currentDate: Date | null = null
  let chatName = extractNameFromFilePath(filePath)
  let isPrivateChat = false
  let useTabSeparator = false
  const memberMap = new Map<string, ParsedMember>()
  const messages: ParsedMessage[] = []
  let lastMessage: ParsedMessage | null = null
  let lineIndex = 0

  // 检测是否有头部
  if (lines.length > 0) {
    const firstLine = lines[0].trim()
    onLog?.('debug', `LINE 第一行: "${firstLine}"`)
    const headerResult = extractNameFromHeader(firstLine)
    if (headerResult) {
      chatName = headerResult.name
      isPrivateChat = !headerResult.isGroup
      useTabSeparator = true // 两种头部格式都使用 Tab 分隔
      lineIndex = 3 // 跳过头部（标题、保存时间、空行）
      onLog?.('debug', `LINE 检测到头部，名称: ${headerResult.name}, 群聊: ${headerResult.isGroup}`)
    }
  }

  // 如果没有检测到头部，检查第一条消息的格式
  if (!isPrivateChat && lines.length > 0) {
    for (const line of lines) {
      if (PRIVATE_MSG_PATTERN.test(line)) {
        useTabSeparator = true
        onLog?.('debug', `LINE 检测到 Tab 分隔格式`)
        break
      }
      if (GROUP_MSG_PATTERN.test(line)) {
        useTabSeparator = false
        onLog?.('debug', `LINE 检测到空格分隔格式`)
        break
      }
    }
  }

  onLog?.('debug', `LINE 解析配置: useTabSeparator=${useTabSeparator}, lineIndex=${lineIndex}`)

  // 解析消息
  let debugLogCount = 0
  for (let i = lineIndex; i < lines.length; i++) {
    const line = lines[i]

    // 尝试解析日期行
    const dateResult = parseDateLine(line)
    if (dateResult) {
      currentDate = dateResult
      if (debugLogCount < 5) {
        onLog?.('debug', `LINE 日期行[${i}]: ${line} -> ${dateResult.toISOString()}`)
      }
      continue
    }

    // 尝试解析消息行
    const msgPattern = useTabSeparator ? PRIVATE_MSG_PATTERN : GROUP_MSG_PATTERN
    const msgMatch = line.match(msgPattern)

    // 调试前几行
    if (debugLogCount < 5 && line.trim()) {
      onLog?.('debug', `LINE 行[${i}]: "${line.substring(0, 50)}..." match=${!!msgMatch}`)
      debugLogCount++
    }

    if (msgMatch) {
      const [, timeStr, sender, contentRaw] = msgMatch
      let content = contentRaw.trim()

      // 处理 LINE 导出的多行消息格式（用双引号包裹）
      let isQuotedMultiline = false
      if (content.startsWith('"')) {
        content = content.substring(1) // 移除开头的引号
        isQuotedMultiline = !content.endsWith('"') // 单行带引号则直接处理
        if (content.endsWith('"')) {
          content = content.substring(0, content.length - 1) // 移除结尾引号
        }
      }

      // 解析时间（支持中文上午/下午、日文午前/午後、英文am/pm）
      let hours = 0
      let minutes = 0

      const prefix = timeStr.match(/^(上午|下午|午前|午後)/)?.[1]
      const cleanTime = timeStr.replace(/^(上午|下午|午前|午後)/, '')
      const partsMatch = cleanTime.match(/^(\d{1,2}):(\d{2})([AaPp][Mm])?$/i)

      if (partsMatch) {
        hours = parseInt(partsMatch[1])
        minutes = parseInt(partsMatch[2])
        const suffix = partsMatch[3]?.toLowerCase()

        // 英文后缀
        if (suffix === 'pm' && hours < 12) hours += 12
        if (suffix === 'am' && hours === 12) hours = 0

        // 中文/日文前缀 (下午/午後 = PM, 上午/午前 = AM)
        if ((prefix === '下午' || prefix === '午後') && hours < 12) hours += 12
        if ((prefix === '上午' || prefix === '午前') && hours === 12) hours = 0
      } else {
        // Fallback
        const parts = timeStr.split(':').map(Number)
        hours = parts[0]
        minutes = parts[1]
      }

      let timestamp: number

      if (currentDate) {
        const msgDate = new Date(currentDate)
        msgDate.setHours(hours, minutes, 0, 0)
        timestamp = Math.floor(msgDate.getTime() / 1000)
      } else {
        // 如果没有日期，使用当前日期
        const now = new Date()
        now.setHours(hours, minutes, 0, 0)
        timestamp = Math.floor(now.getTime() / 1000)
      }

      // 检测消息类型
      const msgType = detectMessageType(content)

      // 更新成员信息
      if (!memberMap.has(sender)) {
        memberMap.set(sender, {
          platformId: sender,
          accountName: sender,
        })
      }

      // 创建消息
      lastMessage = {
        senderPlatformId: sender,
        senderAccountName: sender,
        timestamp,
        type: msgType,
        content: content || null,
        _isQuotedMultiline: isQuotedMultiline, // 临时标记，用于追加多行内容时处理结尾引号
      } as ParsedMessage & { _isQuotedMultiline?: boolean }
      messages.push(lastMessage)
      messagesProcessed++

      // 更新进度
      if (messagesProcessed % 1000 === 0) {
        const progress = createProgress(
          'parsing',
          i,
          lines.length,
          messagesProcessed,
          `已处理 ${messagesProcessed} 条消息...`
        )
        onProgress?.(progress)
      }
    } else {
      // 尝试解析系统消息（双 Tab）
      const systemMatch = line.match(SYSTEM_MSG_PATTERN)
      if (systemMatch) {
        const [, timeStr, contentRaw] = systemMatch
        const content = contentRaw.trim()

        // 解析时间（支持中文、日文、英文）
        let hours = 0
        let minutes = 0

        const prefix = timeStr.match(/^(上午|下午|午前|午後)/)?.[1]
        const cleanTime = timeStr.replace(/^(上午|下午|午前|午後)/, '')
        const partsMatch = cleanTime.match(/^(\d{1,2}):(\d{2})([AaPp][Mm])?$/i)

        if (partsMatch) {
          hours = parseInt(partsMatch[1])
          minutes = parseInt(partsMatch[2])
          const suffix = partsMatch[3]?.toLowerCase()

          if (suffix === 'pm' && hours < 12) hours += 12
          if (suffix === 'am' && hours === 12) hours = 0

          if ((prefix === '下午' || prefix === '午後') && hours < 12) hours += 12
          if ((prefix === '上午' || prefix === '午前') && hours === 12) hours = 0
        } else {
          const parts = timeStr.split(':').map(Number)
          hours = parts[0]
          minutes = parts[1]
        }

        let timestamp: number
        if (currentDate) {
          const msgDate = new Date(currentDate)
          msgDate.setHours(hours, minutes, 0, 0)
          timestamp = Math.floor(msgDate.getTime() / 1000)
        } else {
          const now = new Date()
          now.setHours(hours, minutes, 0, 0)
          timestamp = Math.floor(now.getTime() / 1000)
        }

        // 创建系统消息
        lastMessage = {
          senderPlatformId: 'system',
          senderAccountName: '系統',
          timestamp,
          type: MessageType.SYSTEM,
          content: content || null,
        }
        messages.push(lastMessage)
        messagesProcessed++
      } else if (line.trim() && lastMessage) {
        // 非消息行，追加到上一条消息（多行内容）
        let appendLine = line
        const quotedMsg = lastMessage as ParsedMessage & { _isQuotedMultiline?: boolean }

        // 检查是否为带引号多行消息的最后一行（以 " 结尾）
        if (quotedMsg._isQuotedMultiline && appendLine.endsWith('"')) {
          appendLine = appendLine.substring(0, appendLine.length - 1) // 移除结尾引号
          delete quotedMsg._isQuotedMultiline // 清除临时标记
        }

        if (lastMessage.content) {
          lastMessage.content += '\n' + appendLine
        } else {
          lastMessage.content = appendLine
        }
      }
    }
  }

  // 根据成员数判断聊天类型
  const memberCount = memberMap.size
  const chatType = memberCount <= 2 ? ChatType.PRIVATE : ChatType.GROUP

  // 发送 meta
  const meta: ParsedMeta = {
    name: chatName,
    platform: KNOWN_PLATFORMS.LINE,
    type: chatType,
  }
  yield { type: 'meta', data: meta }

  // 发送成员
  const members = Array.from(memberMap.values())
  yield { type: 'members', data: members }

  // 分批发送消息
  for (let i = 0; i < messages.length; i += batchSize) {
    const batch = messages.slice(i, i + batchSize)
    yield { type: 'messages', data: batch }
  }

  // 完成
  const doneProgress = createProgress('done', totalBytes, totalBytes, messagesProcessed, '')
  yield { type: 'progress', data: doneProgress }
  onProgress?.(doneProgress)

  onLog?.('info', `解析完成: ${messagesProcessed} 条消息, ${memberCount} 个成员`)

  yield {
    type: 'done',
    data: { messageCount: messagesProcessed, memberCount },
  }
}

// ==================== 导出 ====================

export const parser_: Parser = {
  feature,
  parse: parseLINE,
}

const module_: FormatModule = {
  feature,
  parser: parser_,
}

export default module_
