import * as XLSX from 'xlsx';
import type { ReportData, SunburstNode, RegionData, DurationStats, FunnelItem, BarChartCompareItem } from '../types/data';

/**
 * Excel Sheets Structure:
 * 1. 基础信息: Key-Value pairs for cover page
 * 2. 地图展示: Columns [省份, 数值]
 * 3. 地区统计: Columns [地区, 采集数量, 转换率, 成功率, 采集时长]
 * 4. 时长分布: Columns [地区, 0-5分钟, 5-10分钟, 10-20分钟, 20分钟以上]
 * 5. 页面漏损: Columns [环节, 占比]
 * 6. 企业全景洞察: Columns [一级行业, 二级行业, 数值]
 * 7. 劣质客户洞察: Columns [一级行业, 二级行业, 数值]
 * 8. 优质客户洞察: Columns [一级行业, 二级行业, 数值]
 * 9. 风险占比: Columns [指标类型, 标签, 数值, 全量大盘数值]
 * 10. 出口退税分布: Columns [指标类型, 标签, 本机构数值, 全量客户数值]
 * 11. 关联企业分布: Columns [指标类型, 标签, 本机构数值, 全量客户数值]
 * 12. 风险扫描分布: Columns [标签, 本机构数值, 全量客户数值]
 * 13. 图表描述: Columns [页面模块, 指标类型, 描述, 填写说明]
 */

interface MapRow {
  省份: string;
  数值: number;
}

interface BaseInfoRow {
  字段: string;
  数值: string | number;
}

interface RegionRow {
  地区: string;
  采集数量: number;
  转换率: string;
  成功率: string;
  采集时长: string | number;
}

interface DurationRow {
  地区: string;
  '0-5分钟': string;
  '5-10分钟': string;
  '10-20分钟': string;
  '20分钟以上': string;
}

interface FunnelRow {
  环节: string;
  占比: number;
}

interface PortraitRow {
  一级行业: string;
  二级行业: string;
  数值: number;
}

interface RiskPieRow {
  指标类型: 'invoiceRisk' | 'highTech' | 'importExport' | 'prepaidTax';
  标签: string;
  数值: number;
  全量大盘数值: number;
  描述?: string;
}

interface ExportTaxRow {
  指标类型: 'exportFreeTaxRebate' | 'exportTaxRebate';
  标签: string;
  本机构数值: number;
  全量客户数值: number;
  描述?: string;
}

interface AssociationRow {
  指标类型: 'loginPersonAssociation' | 'legalPersonAssociation';
  标签: string;
  本机构数值: number;
  全量客户数值: number;
  描述?: string;
}

interface RiskScanningRow {
  指标类型?: 'riskScanning';
  标签: string;
  本机构数值: number;
  全量客户数值: number;
  描述?: string;
}

interface BarChartDescRow {
  指标类型: 'exportFreeTaxRebate' | 'exportTaxRebate' | 'loginPersonAssociation' | 'legalPersonAssociation' | 'riskScanning';
  描述: string;
}

import { defaultReportData } from '../data/defaultData';

type ChartDescriptionKey = keyof NonNullable<ReportData['chartDescriptions']>;

const chartDescriptionKeys: ChartDescriptionKey[] = [
  'exportFreeTaxRebate',
  'exportTaxRebate',
  'loginPersonAssociation',
  'legalPersonAssociation',
  'riskScanning',
];

const ensurePercent = (val: unknown): string => {
  if (val === undefined || val === null) return '0%';
  if (typeof val === 'number') {
    return `${(val * 100).toFixed(2)}%`;
  }
  const str = String(val).trim();
  if (!str) return '0%';
  if (str.includes('%')) return str;
  const num = parseFloat(str);
  if (!isNaN(num)) {
    return `${(num * 100).toFixed(2)}%`;
  }
  return str.endsWith('%') ? str : `${str}%`;
};

const hasBarChartLabel = (row: { 标签?: unknown }): boolean => {
  return String(row['标签'] ?? '').trim().length > 0;
};

const isChartDescriptionKey = (value: unknown): value is ChartDescriptionKey => {
  return chartDescriptionKeys.includes(value as ChartDescriptionKey);
};

const setChartDescription = (
  reportData: ReportData,
  key: unknown,
  description: unknown
): void => {
  if (!isChartDescriptionKey(key)) return;
  const text = String(description ?? '').trim();
  if (!text) return;
  if (!reportData.chartDescriptions) reportData.chartDescriptions = {};
  reportData.chartDescriptions[key] = text;
};

const formatNumber = (val: unknown): number => {
  if (val === undefined || val === null) return 0;
  const num = parseFloat(String(val));
  if (isNaN(num)) return 0;
  return Math.round(num * 100) / 100;
};

export const parseExcelReportData = async (file: File): Promise<ReportData> => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      try {
        const data = new Uint8Array(e.target?.result as ArrayBuffer);
        const workbook = XLSX.read(data, { type: 'array' });
        
        // Use default as base to ensure all keys exist
        const reportData = JSON.parse(JSON.stringify(defaultReportData)) as ReportData;

        // 1. 基础信息
        const baseSheet = workbook.Sheets['基础信息'];
        if (baseSheet) {
          const baseRows = XLSX.utils.sheet_to_json<BaseInfoRow>(baseSheet, { raw: true });
          const baseObj: Record<string, unknown> = {};
          baseRows.forEach(row => {
            baseObj[row['字段']] = row['数值'];
          });
          reportData.companyName = String(baseObj['公司名称'] || '未知企业');
          reportData.stats = {
            successRate: ensurePercent(baseObj['采集成功率']),
            collectedCount: parseInt(String(baseObj['累计采集户数'])) || 0,
            growthRate: ensurePercent(baseObj['月增长率']),
            fiveMinRate: ensurePercent(baseObj['5分钟内完成比例']),
            avgDuration: formatNumber(baseObj['平均采集时长']),
          };
          reportData.portraitDescriptions = {
            all: String(baseObj['企业全景洞察描述'] || ''),
            poor: String(baseObj['风险客户洞察描述'] || ''),
            good: String(baseObj['优质客户洞察描述'] || ''),
          };
        }

        // 2. 地图展示
        const mapSheet = workbook.Sheets['地图展示'];
        if (mapSheet) {
          reportData.mapData = XLSX.utils.sheet_to_json<MapRow>(mapSheet).map((row) => ({
            name: row['省份'],
            value: row['数值'] || 0,
          }));
        }

        // 3. 地区统计
        const regionSheet = workbook.Sheets['地区统计'];
        if (regionSheet) {
          reportData.regionStatistics = XLSX.utils.sheet_to_json<RegionRow>(regionSheet, { raw: true }).map((row): RegionData => ({
            region: row['地区'],
            count: parseInt(String(row['采集数量'])) || 0,
            conversion: ensurePercent(row['转换率']),
            success: ensurePercent(row['成功率']),
            duration: String(formatNumber(row['采集时长'] || '0')),
          }));
        }

        // 3. 时长分布
        const durationSheet = workbook.Sheets['时长分布'];
        if (durationSheet) {
          reportData.durationStatistics = XLSX.utils.sheet_to_json<DurationRow>(durationSheet, { raw: true }).map((row): DurationStats => ({
            region: row['地区'],
            p0_5: ensurePercent(row['0-5分钟']),
            p5_10: ensurePercent(row['5-10分钟']),
            p10_20: ensurePercent(row['10-20分钟']),
            p20plus: ensurePercent(row['20分钟以上']),
          }));
        }

        // 4. 页面漏损
        const funnelSheet = workbook.Sheets['页面漏损'];
        if (funnelSheet) {
          reportData.funnelData = XLSX.utils.sheet_to_json<FunnelRow>(funnelSheet).map((row): FunnelItem => ({
            label: row['环节'],
            value: row['占比'] * 100 || 0,
          }));
        }

        // 5. 企业全景洞察
        const BLUE_PALETTE = ['#1B65B5', '#2386EE', '#52A3FF', '#85C1FF', '#B8DEFF'];

        const buildSunburst = (rows: PortraitRow[]) => {
          const categories: Record<string, SunburstNode> = {};
          rows.forEach(row => {
            const l1 = row['一级行业'];
            const l2 = row['二级行业'];
            const val = row['数值'] || 0;
            if (!categories[l1]) {
              categories[l1] = { name: l1, children: [] };
            }
            categories[l1].children?.push({ name: l2, value: val });
          });
          return Object.values(categories).map((cat, idx) => {
            const color = BLUE_PALETTE[idx % BLUE_PALETTE.length];
            return {
              ...cat,
              itemStyle: { color },
              children: cat.children?.map(child => ({ ...child, itemStyle: { color } }))
            };
          });
        };

        const allSheet = workbook.Sheets['企业全景洞察'];
        if (allSheet) {
          reportData.sunburstData = buildSunburst(XLSX.utils.sheet_to_json<PortraitRow>(allSheet));
        }

        const poorSheet = workbook.Sheets['劣质客户洞察'];
        if (poorSheet) {
          reportData.poorCustomerData = buildSunburst(XLSX.utils.sheet_to_json<PortraitRow>(poorSheet));
        }

        const goodSheet = workbook.Sheets['优质客户洞察'];
        if (goodSheet) {
          reportData.goodCustomerData = buildSunburst(XLSX.utils.sheet_to_json<PortraitRow>(goodSheet));
        }

        // 6. 风险占比
        const riskPieSheet = workbook.Sheets['风险占比'];
        if (riskPieSheet) {
          const rows = XLSX.utils.sheet_to_json<RiskPieRow>(riskPieSheet);
          rows.forEach(row => {
            const key = row['指标类型'];
            if (key) {
              reportData.riskIndicators[key] = {
                label: row['标签'],
                value: row['数值'] || 0,
                marketValue: row['全量大盘数值'] || 0,
                description: row['描述'] || '',
              };
            }
          });
        }

        // 7. 出口退税分布
        const exportTaxSheet = workbook.Sheets['出口退税分布'];
        if (exportTaxSheet) {
          const rows = XLSX.utils.sheet_to_json<ExportTaxRow>(exportTaxSheet);
          const groups: Record<string, BarChartCompareItem[]> = {};
          rows.forEach(row => {
            const cat = row['指标类型'];
            setChartDescription(reportData, cat, row['描述']);
            if (cat && hasBarChartLabel(row)) {
              if (!groups[cat]) groups[cat] = [];
              groups[cat].push({
                label: String(row['标签']).trim(),
                customerValue: formatNumber(row['本机构数值']),
                marketValue: formatNumber(row['全量客户数值']),
              });
            }
          });
          if (groups['exportFreeTaxRebate']) reportData.exportFreeTaxRebate = groups['exportFreeTaxRebate'];
          if (groups['exportTaxRebate']) reportData.exportTaxRebate = groups['exportTaxRebate'];
        }

        // 8. 关联企业分布
        const associationSheet = workbook.Sheets['关联企业分布'];
        if (associationSheet) {
          const rows = XLSX.utils.sheet_to_json<AssociationRow>(associationSheet);
          const groups: Record<string, BarChartCompareItem[]> = {};
          rows.forEach(row => {
            const cat = row['指标类型'];
            setChartDescription(reportData, cat, row['描述']);
            if (cat && hasBarChartLabel(row)) {
              if (!groups[cat]) groups[cat] = [];
              groups[cat].push({
                label: String(row['标签']).trim(),
                customerValue: formatNumber(row['本机构数值']),
                marketValue: formatNumber(row['全量客户数值']),
              });
            }
          });
          if (groups['loginPersonAssociation']) reportData.loginPersonAssociation = groups['loginPersonAssociation'];
          if (groups['legalPersonAssociation']) reportData.legalPersonAssociation = groups['legalPersonAssociation'];
        }

        // 9. 风险扫描分布
        const riskScanningSheet = workbook.Sheets['风险扫描分布'];
        if (riskScanningSheet) {
          const rows = XLSX.utils.sheet_to_json<RiskScanningRow>(riskScanningSheet);
          rows.forEach(row => {
            setChartDescription(reportData, row['指标类型'], row['描述']);
          });
          reportData.riskScanning = rows.filter(hasBarChartLabel).map((row): BarChartCompareItem => ({
            label: String(row['标签']).trim(),
            customerValue: formatNumber(row['本机构数值']),
            marketValue: formatNumber(row['全量客户数值']),
          }));
        }

        // 10. 图表描述（新模板优先）
        const chartDescriptionSheet = workbook.Sheets['图表描述'];
        if (chartDescriptionSheet) {
          const rows = XLSX.utils.sheet_to_json<BarChartDescRow>(chartDescriptionSheet);
          rows.forEach(row => {
            setChartDescription(reportData, row['指标类型'], row['描述']);
          });
        }

        resolve(reportData);
      } catch (err) {
        reject(err);
      }
    };
    reader.onerror = reject;
    reader.readAsArrayBuffer(file);
  });
};

export const generateExcelTemplate = () => {
  const wb = XLSX.utils.book_new();

  // Helper to ensure cells are treated as strings to avoid auto-formatting
  const toSheet = (data: Record<string, unknown>[]) => {
    const ws = XLSX.utils.json_to_sheet(data);
    // Force all cells to be strings to avoid Excel's "helpful" formatting
    Object.keys(ws).forEach(key => {
      if (key[0] === '!') return;
      const cell = ws[key];
      if (cell.v !== undefined) {
        cell.t = 's'; // Set type to string
        cell.v = String(cell.v);
      }
    });
    return ws;
  };

  // 1. 基础信息
  const baseWS = toSheet([
    { '字段': '公司名称', '数值': '某某科技公司' },
    { '字段': '采集成功率', '数值': '99.99%' },
    { '字段': '累计采集户数', '数值': '1200' },
    { '字段': '月增长率', '数值': '12%' },
    { '字段': '5分钟内完成比例', '数值': '95%' },
    { '字段': '平均采集时长', '数值': '3.5' },
    { '字段': '企业全景洞察描述', '数值': '基于行业分布与企业特征，全面展示企业画像数据。' },
    { '字段': '风险客户洞察描述', '数值': '识别可能存在合作风险的客户群体，帮助您提前制定应对策略。' },
    { '字段': '优质客户洞察描述', '数值': '展示高价值优质客户特征，帮助您优化服务策略。' },
  ]);
  XLSX.utils.book_append_sheet(wb, baseWS, '基础信息');

  // 2. 地图展示
  const mapWS = XLSX.utils.json_to_sheet([
    { '省份': '广东省', '数值': 9058 },
    { '省份': '江苏省', '数值': 4712 },
    { '省份': '四川省', '数值': 4560 },
  ]);
  XLSX.utils.book_append_sheet(wb, mapWS, '地图展示');

  // 3. 地区统计
  const regionWS = toSheet([
    { '地区': '广东省', '采集数量': '5000', '转换率': '85.5%', '成功率': '99.9%', '采集时长': '5.2' },
    { '地区': '江苏省', '采集数量': '4000', '转换率': '88.2%', '成功率': '99.5%', '采集时长': '4.8' },
  ]);
  XLSX.utils.book_append_sheet(wb, regionWS, '地区统计');

  // 3. 时长分布
  const durationWS = toSheet([
    { '地区': '广东省', '0-5分钟': '70%', '5-10分钟': '20%', '10-20分钟': '5%', '20分钟以上': '5%' },
  ]);
  XLSX.utils.book_append_sheet(wb, durationWS, '时长分布');

  // 4. 页面漏损
  const funnelWS = XLSX.utils.json_to_sheet([ // Numbers are fine for charts
    { '环节': '登录税局', '占比': 100 },
    { '环节': '签署授权', '占比': 85 },
  ]);
  XLSX.utils.book_append_sheet(wb, funnelWS, '页面漏损');

  // 5. 企业全景洞察
  const allWS = XLSX.utils.json_to_sheet([
    { '一级行业': '制造业', '二级行业': '通用设备', '数值': 150 },
    { '一级行业': '制造业', '二级行业': '金属加工', '数值': 100 },
    { '一级行业': '批发业', '二级行业': '食品批发', '数值': 200 },
  ]);
  XLSX.utils.book_append_sheet(wb, allWS, '企业全景洞察');

  // 6. 劣质客户洞察
  const poorWS = XLSX.utils.json_to_sheet([
    { '一级行业': '制造业', '二级行业': '通用设备', '数值': 30 },
    { '一级行业': '制造业', '二级行业': '金属加工', '数值': 20 },
    { '一级行业': '批发业', '二级行业': '食品批发', '数值': 50 },
  ]);
  XLSX.utils.book_append_sheet(wb, poorWS, '劣质客户洞察');

  // 7. 优质客户洞察
  const goodWS = XLSX.utils.json_to_sheet([
    { '一级行业': '制造业', '二级行业': '通用设备', '数值': 120 },
    { '一级行业': '制造业', '二级行业': '金属加工', '数值': 80 },
    { '一级行业': '批发业', '二级行业': '食品批发', '数值': 150 },
  ]);
  XLSX.utils.book_append_sheet(wb, goodWS, '优质客户洞察');

  // 9. 风险占比
  const riskPieWS = toSheet([
    { '指标类型': 'invoiceRisk', '标签': '发票高风险记录', '数值': '0.5', '全量大盘数值': '0.3', '描述': '统计近1年有效开票记录中，存在发票高风险的企业占比情况。' },
    { '指标类型': 'highTech', '标签': '高新技术企业', '数值': '5.2', '全量大盘数值': '4.8', '描述': '统计近1年有效开票记录中，被认定为高新技术企业的占比情况。' },
    { '指标类型': 'importExport', '标签': '进出口企业', '数值': '2.1', '全量大盘数值': '1.8', '描述': '统计近1年有效开票记录中，具有进出口资质的企业占比情况。' },
    { '指标类型': 'prepaidTax', '标签': '预缴税款企业', '数值': '15.0', '全量大盘数值': '12.5', '描述': '统计近1年有效开票记录中，存在预缴税款行为的企业占比情况。' },
  ]);
  XLSX.utils.book_append_sheet(wb, riskPieWS, '风险占比');

  // 10. 出口退税分布
  const exportTaxWS = XLSX.utils.json_to_sheet([
    { '指标类型': 'exportFreeTaxRebate', '标签': '出口免抵退税额0到100万', '本机构数值': 71.43, '全量客户数值': 75 },
    { '指标类型': 'exportFreeTaxRebate', '标签': '出口免抵退税额100到500万', '本机构数值': 16.67, '全量客户数值': 18 },
    { '指标类型': 'exportFreeTaxRebate', '标签': '出口免抵退税额500到1000万', '本机构数值': 0, '全量客户数值': 2 },
    { '指标类型': 'exportFreeTaxRebate', '标签': '出口免抵退税额1000万以上', '本机构数值': 11.9, '全量客户数值': 5 },
    { '指标类型': 'exportTaxRebate', '标签': '出口退税额0到100万', '本机构数值': 68.33, '全量客户数值': 70 },
    { '指标类型': 'exportTaxRebate', '标签': '出口退税额100到500万', '本机构数值': 21.67, '全量客户数值': 20 },
    { '指标类型': 'exportTaxRebate', '标签': '出口退税额500到1000万', '本机构数值': 8.33, '全量客户数值': 7 },
    { '指标类型': 'exportTaxRebate', '标签': '出口退税额1000万以上', '本机构数值': 1.67, '全量客户数值': 3 },
  ]);
  XLSX.utils.book_append_sheet(wb, exportTaxWS, '出口退税分布');

  // 11. 关联企业分布
  const associationWS = XLSX.utils.json_to_sheet([
    { '指标类型': 'loginPersonAssociation', '标签': '登录人关联企业数量: 0~3', '本机构数值': 90.06, '全量客户数值': 92 },
    { '指标类型': 'loginPersonAssociation', '标签': '登录人关联企业数量: 4~10', '本机构数值': 8.58, '全量客户数值': 7 },
    { '指标类型': 'loginPersonAssociation', '标签': '登录人关联企业数量: 10+', '本机构数值': 1.36, '全量客户数值': 1 },
    { '指标类型': 'legalPersonAssociation', '标签': '法人代表关联企业数量: 0~3', '本机构数值': 92.91, '全量客户数值': 90 },
    { '指标类型': 'legalPersonAssociation', '标签': '法人代表关联企业数量: 4~10', '本机构数值': 6.49, '全量客户数值': 8 },
    { '指标类型': 'legalPersonAssociation', '标签': '法人代表关联企业数量: 10+', '本机构数值': 0.61, '全量客户数值': 2 },
  ]);
  XLSX.utils.book_append_sheet(wb, associationWS, '关联企业分布');

  // 12. 风险扫描分布
  const riskScanningWS = XLSX.utils.json_to_sheet([
    { '标签': '无风险', '本机构数值': 77.58, '全量客户数值': 75 },
    { '标签': '低风险', '本机构数值': 12.41, '全量客户数值': 13 },
    { '标签': '中风险', '本机构数值': 10.01, '全量客户数值': 9 },
    { '标签': '高风险', '本机构数值': 0, '全量客户数值': 3 },
  ]);
  XLSX.utils.book_append_sheet(wb, riskScanningWS, '风险扫描分布');

  // 13. 图表描述
  const chartDescriptionWS = toSheet([
    { '页面模块': '不同出口免抵退税金额企业分布', '指标类型': 'exportFreeTaxRebate', '描述': '近1年有效开票金额最大月份占比', '填写说明': '请修改“描述”列；“指标类型”请勿修改。' },
    { '页面模块': '不同出口退税金额企业分布', '指标类型': 'exportTaxRebate', '描述': '近1年有效开票金额最大月份占比', '填写说明': '请修改“描述”列；“指标类型”请勿修改。' },
    { '页面模块': '登录人关联企业数量分布', '指标类型': 'loginPersonAssociation', '描述': '近1年有效开票金额最大月份占比', '填写说明': '请修改“描述”列；“指标类型”请勿修改。' },
    { '页面模块': '法定代表人关联企业数量分布', '指标类型': 'legalPersonAssociation', '描述': '近1年有效开票金额最大月份占比', '填写说明': '请修改“描述”列；“指标类型”请勿修改。' },
    { '页面模块': '企业风险扫描结果分布', '指标类型': 'riskScanning', '描述': '近1年有效开票金额最大月份占比', '填写说明': '请修改“描述”列；“指标类型”请勿修改。' },
  ]);
  XLSX.utils.book_append_sheet(wb, chartDescriptionWS, '图表描述');

  XLSX.writeFile(wb, '报告数据导入模板.xlsx');
};
