/**
 * GitHub 提交日志获取服务
 * 用于从 GitHub API 获取项目的提交历史并转换为更新日志
 */

export interface GitHubCommit {
  sha: string;
  commit: {
    author: {
      name: string;
      email: string;
      date: string;
    };
    message: string;
  };
  html_url: string;
  author: {
    login: string;
    avatar_url: string;
  } | null;
}

export interface ChangelogEntry {
  id: string;
  date: string;
  version?: string;
  author: {
    name: string;
    avatar?: string;
    username?: string;
  };
  message: string;
  commitUrl: string;
  type: 'feature' | 'fix' | 'docs' | 'style' | 'refactor' | 'perf' | 'test' | 'chore' | 'update' | 'other';
  scope?: string;
}

const GITHUB_API_BASE = 'https://api.github.com';
const REPO_OWNER = 'xiamuceer-j';
const REPO_NAME = 'MuMuAINovel';

/**
 * 提交类型映射表
 * 统一不同别名到标准类型
 */
const TYPE_MAPPING: Record<string, ChangelogEntry['type']> = {
  // 功能类
  'feat': 'feature',
  'feature': 'feature',
  'update': 'update',
  
  // 修复类
  'fix': 'fix',
  
  // 文档类
  'docs': 'docs',
  'doc': 'docs',
  
  // 样式类
  'style': 'style',
  
  // 重构类
  'refactor': 'refactor',
  
  // 性能类
  'perf': 'perf',
  
  // 测试类
  'test': 'test',
  
  // 杂项类
  'chore': 'chore',
};

/**
 * 从提交信息中解析类型和作用域
 *
 * 匹配优先级（从高到低）：
 * 1. 标准 Conventional Commits 格式: type(scope): message 或 type: message
 * 2. 方括号格式: [type] message
 * 3. 简单前缀格式: type: message（支持中文冒号）
 * 4. 关键词模糊匹配（中英文）
 */
function parseCommitType(message: string): { type: ChangelogEntry['type']; scope?: string; cleanMessage: string } {
  const lowerMessage = message.toLowerCase().trim();
  
  // 优先级1：标准 Conventional Commits 格式 - type(scope): message 或 type: message
  // 匹配所有支持的类型
  const conventionalPattern = new RegExp(
    `^(${Object.keys(TYPE_MAPPING).join('|')})(?:\\(([^)]+)\\))?\\s*[:\\:：]\\s*(.+)`,
    'i'
  );
  const conventionalMatch = message.match(conventionalPattern);
  if (conventionalMatch) {
    const typeStr = conventionalMatch[1].toLowerCase();
    const mappedType = TYPE_MAPPING[typeStr] || 'other';
    return {
      type: mappedType,
      scope: conventionalMatch[2],
      cleanMessage: conventionalMatch[3].trim(),
    };
  }

  // 优先级2：方括号格式 - [type] message
  const bracketPattern = new RegExp(
    `^\\[(${Object.keys(TYPE_MAPPING).join('|')})\\]\\s*(.+)`,
    'i'
  );
  const bracketMatch = message.match(bracketPattern);
  if (bracketMatch) {
    const typeStr = bracketMatch[1].toLowerCase();
    const mappedType = TYPE_MAPPING[typeStr] || 'other';
    return {
      type: mappedType,
      cleanMessage: bracketMatch[2].trim(),
    };
  }

  // 优先级3：简单前缀格式 - type: message（支持英文和中文冒号）
  for (const [key, value] of Object.entries(TYPE_MAPPING)) {
    const prefixPattern = new RegExp(`^${key}\\s*[:\\:：]\\s*`, 'i');
    if (prefixPattern.test(lowerMessage)) {
      const cleanMsg = message.replace(prefixPattern, '').trim();
      return { type: value, cleanMessage: cleanMsg };
    }
  }

  // 优先级4：关键词模糊匹配（仅当前面都不匹配时）
  const keywordMap: Array<{ keywords: string[]; type: ChangelogEntry['type'] }> = [
    { keywords: ['修复', 'fix'], type: 'fix' },
    { keywords: ['优化', 'perf'], type: 'perf' },
    { keywords: ['文档', 'document'], type: 'docs' },
    { keywords: ['新增', '添加', '增加', 'add'], type: 'feature' },
    { keywords: ['更新', 'update'], type: 'update' },
    { keywords: ['样式', 'style'], type: 'style' },
    { keywords: ['重构', 'refactor'], type: 'refactor' },
    { keywords: ['测试', 'test'], type: 'test' },
  ];

  for (const { keywords, type } of keywordMap) {
    if (keywords.some(keyword => lowerMessage.includes(keyword))) {
      return { type, cleanMessage: message };
    }
  }

  // 默认类型
  return { type: 'other', cleanMessage: message };
}

/**
 * 获取GitHub提交历史
 */
export async function fetchGitHubCommits(page: number = 1, perPage: number = 30): Promise<GitHubCommit[]> {
  try {
    const url = `${GITHUB_API_BASE}/repos/${REPO_OWNER}/${REPO_NAME}/commits?author=${REPO_OWNER}&page=${page}&per_page=${perPage}`;
    
    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'Accept': 'application/vnd.github.v3+json',
      },
      cache: 'no-cache',
    });

    if (!response.ok) {
      throw new Error(`GitHub API 请求失败: ${response.status} ${response.statusText}`);
    }

    return await response.json();
  } catch (error) {
    console.error('获取 GitHub 提交历史失败:', error);
    throw error;
  }
}

/**
 * 将GitHub提交转换为更新日志条目
 */
export function convertCommitsToChangelog(commits: GitHubCommit[]): ChangelogEntry[] {
  return commits.map(commit => {
    const { type, scope, cleanMessage } = parseCommitType(commit.commit.message);
    
    return {
      id: commit.sha,
      date: commit.commit.author.date,
      author: {
        name: commit.commit.author.name,
        avatar: commit.author?.avatar_url,
        username: commit.author?.login,
      },
      message: cleanMessage,
      commitUrl: commit.html_url,
      type,
      scope,
    };
  });
}

/**
 * 获取格式化的更新日志
 */
export async function fetchChangelog(page: number = 1, perPage: number = 30): Promise<ChangelogEntry[]> {
  const commits = await fetchGitHubCommits(page, perPage);
  return convertCommitsToChangelog(commits);
}

/**
 * 按日期分组更新日志
 */
export function groupChangelogByDate(entries: ChangelogEntry[]): Map<string, ChangelogEntry[]> {
  const grouped = new Map<string, ChangelogEntry[]>();
  
  entries.forEach(entry => {
    const date = new Date(entry.date).toISOString().split('T')[0];
    const existing = grouped.get(date) || [];
    existing.push(entry);
    grouped.set(date, existing);
  });
  
  return grouped;
}

/**
 * 检查是否应该获取更新日志（避免频繁请求）
 */
export function shouldFetchChangelog(): boolean {
  const lastFetch = localStorage.getItem('changelog_last_fetch');
  
  if (!lastFetch) {
    return true;
  }
  
  const lastFetchTime = new Date(lastFetch).getTime();
  const now = Date.now();
  const oneHourMs = 60 * 60 * 1000; // 1小时
  
  return now - lastFetchTime >= oneHourMs;
}

/**
 * 记录更新日志获取时间
 */
export function markChangelogFetched(): void {
  localStorage.setItem('changelog_last_fetch', new Date().toISOString());
}

/**
 * 获取缓存的更新日志
 */
export function getCachedChangelog(): ChangelogEntry[] | null {
  const cached = localStorage.getItem('changelog_cache');
  if (cached) {
    try {
      return JSON.parse(cached);
    } catch {
      return null;
    }
  }
  return null;
}

/**
 * 缓存更新日志
 */
export function cacheChangelog(entries: ChangelogEntry[]): void {
  localStorage.setItem('changelog_cache', JSON.stringify(entries));
}

/**
 * 清除更新日志缓存
 * 用于强制刷新数据
 */
export function clearChangelogCache(): void {
  localStorage.removeItem('changelog_cache');
  localStorage.removeItem('changelog_last_fetch');
}