/**
 * 财务数据处理工具函数
 * 包含股票代码规范化、数据格式化等通用功能
 */

import type { MarketType, CompanyInfo, FinancialMetricConfig } from '@/types';

// ============================================================================
// 股票代码处理
// ============================================================================

/**
 * 规范化A股代码为ts_code格式
 * @param input - 输入的股票代码
 * @returns 规范化后的ts_code，如果无效则返回null
 * 
 * @example
 * ```typescript
 * normalizeTsCode('600519') // '600519.SH'
 * normalizeTsCode('000001') // '000001.SZ'
 * normalizeTsCode('600519.SH') // '600519.SH'
 * normalizeTsCode('invalid') // null
 * ```
 */
export function normalizeTsCode(input: string): string | null {
  const code = (input || "").trim();
  if (!code) return null;
  
  // 仅支持数字代码的简易规则：6开头上证，0/3开头深证
  if (/^\d{6}$/.test(code)) {
    if (code.startsWith("6")) return `${code}.SH`;
    if (code.startsWith("0") || code.startsWith("3")) return `${code}.SZ`;
  }
  
  // 若已含交易所后缀则直接返回
  if (/^\d{6}\.(SH|SZ)$/i.test(code)) return code.toUpperCase();
  
  return null;
}

/**
 * 验证股票代码是否有效
 * @param code - 股票代码
 * @returns 是否为有效的股票代码
 */
export function isValidTsCode(code: string): boolean {
  return normalizeTsCode(code) !== null;
}

/**
 * 从输入中提取股票代码
 * @param input - 可能包含股票代码和公司名的输入
 * @returns 提取的股票代码，如果没有找到则返回null
 */
export function extractTsCode(input: string): string | null {
  const trimmed = input.trim();
  
  // 尝试从输入开头提取代码
  const codeMatch = trimmed.match(/^(\d{6}(?:\.[A-Z]{2})?)/);
  if (codeMatch) {
    return normalizeTsCode(codeMatch[1]);
  }
  
  return null;
}

// ============================================================================
// 数据格式化
// ============================================================================

/**
 * 格式化财务数值显示
 * @param value - 原始数值
 * @param group - 指标分组
 * @param api - API接口名
 * @param metricKey - 指标键名
 * @returns 格式化后的字符串
 */
export function formatFinancialValue(
  value: number | null | undefined,
  group?: string,
  api?: string,
  metricKey?: string
): string {
  if (value === null || typeof value === "undefined") return "-";
  
  const num = Number(value);
  if (Number.isNaN(num)) return "-";
  
  const nf1 = new Intl.NumberFormat("zh-CN", { 
    minimumFractionDigits: 1, 
    maximumFractionDigits: 1 
  });
  const nf0 = new Intl.NumberFormat("zh-CN", { 
    maximumFractionDigits: 0 
  });
  
  // 报表类统一按亿元显示（1位小数，千分位）
  if (group === "income" || group === "balancesheet" || group === "cashflow" || metricKey === "revenue") {
    const scaled = num / 1e8;
    return nf1.format(scaled);
  }
  
  // 市值 total_mv（daily_basic，万元）-> 亿元，整数（千分位）
  if (api === "daily_basic" && metricKey === "total_mv") {
    const scaledYi = num / 1e4;
    return nf0.format(Math.round(scaledYi));
  }
  
  // 员工数 / 股东数 -> 整数（千分位），不做单位换算
  if (metricKey === "employees" || metricKey === "holder_num") {
    return nf0.format(Math.round(num));
  }
  
  // 其他数值 -> 1位小数 + 千分位
  return nf1.format(num);
}

/**
 * 获取指标单位文本
 * @param group - 指标分组
 * @param api - API接口名
 * @param metricKey - 指标键名
 * @returns 单位文本，如果不需要显示单位则返回空字符串
 */
export function getMetricUnit(group?: string, api?: string, metricKey?: string): string {
  // 报表类和市值显示亿元单位
  if (
    group === "income" || 
    group === "balancesheet" || 
    group === "cashflow" || 
    metricKey === "total_mv"
  ) {
    return "（亿元）";
  }
  
  return "";
}

// ============================================================================
// 配置处理
// ============================================================================

/**
 * 扁平化API分组配置
 * @param apiGroups - API分组配置对象
 * @param groupOrder - 分组顺序数组
 * @returns 扁平化的配置项数组和映射对象
 */
export function flattenApiGroups(
  apiGroups: Record<string, FinancialMetricConfig[]>,
  groupOrder: string[] = ["income", "fina_indicator", "balancesheet", "cashflow", "daily_basic", "daily", "unknown"]
): {
  items: FinancialMetricConfig[];
  groupMap: Record<string, string>;
  apiMap: Record<string, string>;
} {
  const items: FinancialMetricConfig[] = [];
  const groupMap: Record<string, string> = {};
  const apiMap: Record<string, string> = {};
  
  for (const group of groupOrder) {
    const arr = Array.isArray(apiGroups[group]) ? apiGroups[group] : [];
    for (const item of arr) {
      const param = (item?.tushareParam || "").trim();
      if (!param) continue;
      
      const api = (item?.api || "").trim();
      items.push({ 
        displayText: item.displayText, 
        tushareParam: param, 
        api, 
        group 
      });
      groupMap[param] = group;
      apiMap[param] = api;
    }
  }
  
  return { items, groupMap, apiMap };
}

// ============================================================================
// 错误处理
// ============================================================================

/**
 * 增强错误信息
 * @param error - 原始错误
 * @returns 增强后的错误信息
 */
export function enhanceErrorMessage(error: unknown): string {
  const errorMsg = error instanceof Error ? error.message : "未知错误";
  
  // 网络相关错误
  if (errorMsg.includes('fetch') || errorMsg.includes('NetworkError')) {
    return "网络连接失败，请检查后端服务是否已启动或网络连接是否正常。";
  }
  
  if (errorMsg.includes('timeout')) {
    return "请求超时，请稍后重试。";
  }
  
  // 数据相关错误
  if (errorMsg.includes('未查询到数据')) {
    return "未查询到数据，请确认代码或稍后重试。";
  }
  
  // 服务相关错误
  if (errorMsg.includes('500') || errorMsg.includes('Internal Server Error')) {
    return "服务器内部错误，请稍后重试或联系管理员。";
  }
  
  if (errorMsg.includes('404') || errorMsg.includes('Not Found')) {
    return "请求的资源不存在，请检查输入参数。";
  }
  
  // 默认错误处理
  if (!errorMsg || errorMsg === "未知错误") {
    return "查询失败，请检查后端服务是否已启动。";
  }
  
  return errorMsg;
}

/**
 * 判断错误是否可重试
 * @param error - 错误对象或错误信息
 * @returns 是否可重试
 */
export function isRetryableError(error: unknown): boolean {
  const errorMsg = error instanceof Error ? error.message : String(error);
  
  return (
    errorMsg.includes('网络') || 
    errorMsg.includes('连接') || 
    errorMsg.includes('超时') ||
    errorMsg.includes('timeout') ||
    errorMsg.includes('fetch') ||
    errorMsg.includes('NetworkError')
  );
}

// ============================================================================
// 数据验证
// ============================================================================

/**
 * 验证市场类型是否支持
 * @param market - 市场类型
 * @returns 是否支持该市场
 */
export function isSupportedMarket(market: string): market is MarketType {
  return ['cn', 'us', 'hk', 'jp', 'other'].includes(market);
}

/**
 * 验证公司信息是否有效
 * @param company - 公司信息对象
 * @returns 是否为有效的公司信息
 */
export function isValidCompanyInfo(company: unknown): company is CompanyInfo {
  return (
    typeof company === 'object' &&
    company !== null &&
    typeof (company as CompanyInfo).ts_code === 'string' &&
    isValidTsCode((company as CompanyInfo).ts_code)
  );
}

// ============================================================================
// 本地存储工具
// ============================================================================

/**
 * 检查localStorage是否可用
 * @returns localStorage是否可用
 */
export function isLocalStorageAvailable(): boolean {
  try {
    const testKey = '__localStorage_test__';
    localStorage.setItem(testKey, 'test');
    localStorage.removeItem(testKey);
    return true;
  } catch {
    return false;
  }
}

/**
 * 安全地从localStorage获取数据
 * @param key - 存储键
 * @param defaultValue - 默认值
 * @returns 存储的数据或默认值
 */
export function safeGetFromStorage<T>(key: string, defaultValue: T): T {
  if (!isLocalStorageAvailable()) {
    return defaultValue;
  }
  
  try {
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : defaultValue;
  } catch {
    return defaultValue;
  }
}

/**
 * 安全地向localStorage保存数据
 * @param key - 存储键
 * @param value - 要保存的数据
 * @returns 是否保存成功
 */
export function safeSetToStorage(key: string, value: unknown): boolean {
  if (!isLocalStorageAvailable()) {
    return false;
  }
  
  try {
    localStorage.setItem(key, JSON.stringify(value));
    return true;
  } catch {
    return false;
  }
}

export const formatReportPeriod = (period: string): string => {
  if (!period || period.length !== 8) {
    return period;
  }
  const year = period.substring(0, 4);
  const monthDay = period.substring(4);

  switch (monthDay) {
    case '1231':
      return `${year}A`;
    case '0930':
      return `${year}Q3`;
    case '0630':
      return `${year}Q2`;
    case '0331':
      return `${year}Q1`;
    default:
      return period;
  }
};