use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};

/// Tushare 原始数据条目
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TushareMetric {
    pub metric_name: String,
    pub period_date: String, // YYYY-MM-DD
    pub value: Option<f64>,
    // source 和 symbol 暂时不用，因为是单只股票的报表
}

/// 格式化后的报表结构
pub struct FormattedReport {
    pub title: String,
    pub blocks: Vec<YearBlock>,
}

/// 年度/时期数据块
pub struct YearBlock {
    pub title: String, // "2024年度" 或 "2020 - 2024"
    pub periods: Vec<String>, // 列头: ["2024-12-31", ...] 或 ["2024", "2023", ...]
    pub sections: Vec<ReportSection>,
}

/// 报表类型
#[derive(Debug, Clone, Copy)]
pub enum ReportType {
    Quarterly,      // 季报模式 (默认)
    Yearly5Year,    // 5年聚合模式
}

/// 报表分段 (如: 资产负债表)
pub struct ReportSection {
    pub title: String,
    pub rows: Vec<FormatRow>,
}

/// 格式化行
pub struct FormatRow {
    pub label: String,
    pub values: Vec<String>, // 已经格式化好的字符串 (e.g. "14.20 亿")
}

/// 单位策略
#[derive(Debug, Clone, Copy)]
pub enum UnitStrategy {
    CurrencyYi,    // 亿 (除以 1e8, 保留2位)
    CurrencyWan,   // 万 (除以 1e4, 保留2位)
    Percent,       // 百分比 (乘 100, 保留2位 + %)
    Integer,       // 整数
    Raw,           // 原始值
    Days,          // 天数 (保留1位)
}

/// 字段元数据
struct MetricMeta {
    display_name: &'static str,
    category: SectionCategory,
    strategy: UnitStrategy,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum SectionCategory {
    Snapshot,
    Income,
    Balance,
    CashFlow,
    Ratios,
    Misc, // 兜底
}

impl SectionCategory {
    fn title(&self) -> &'static str {
        match self {
            SectionCategory::Snapshot => "关键指标",
            SectionCategory::Income => "利润表",
            SectionCategory::Balance => "资产负债表",
            SectionCategory::CashFlow => "现金流量表",
            SectionCategory::Ratios => "运营与比率",
            SectionCategory::Misc => "其他指标",
        }
    }
}

pub struct TushareFormatter {
    meta_map: HashMap<String, MetricMeta>,
}

impl TushareFormatter {
    pub fn new() -> Self {
        let mut meta_map = HashMap::new();
        Self::init_dictionary(&mut meta_map);
        Self { meta_map }
    }

    /// 初始化数据字典
    fn init_dictionary(map: &mut HashMap<String, MetricMeta>) {
        // 辅助宏
        macro_rules! m {
            ($key:expr, $name:expr, $cat:ident, $strat:ident) => {
                map.insert(
                    $key.to_string(),
                    MetricMeta {
                        display_name: $name,
                        category: SectionCategory::$cat,
                        strategy: UnitStrategy::$strat,
                    },
                );
            };
        }

        // --- Snapshot & Market ---
        m!("total_mv", "总市值", Snapshot, CurrencyYi);
        m!("employees", "员工人数", Snapshot, Integer);
        m!("holder_num", "股东户数", Snapshot, CurrencyWan);
        m!("close", "收盘价", Snapshot, Raw);
        m!("pe", "市盈率(PE)", Snapshot, Raw);
        m!("pb", "市净率(PB)", Snapshot, Raw);

        // --- Income Statement ---
        m!("revenue", "营业收入", Income, CurrencyYi);
        m!("n_income", "净利润", Income, CurrencyYi);
        m!("rd_exp", "研发费用", Income, CurrencyYi);
        m!("sell_exp", "销售费用", Income, CurrencyYi);
        m!("admin_exp", "管理费用", Income, CurrencyYi);
        m!("fin_exp", "财务费用", Income, CurrencyYi);
        m!("total_cogs", "营业成本", Income, CurrencyYi);
        m!("tax_to_ebt", "实际税率", Income, Percent);
        m!("__tax_rate", "所得税率(Est)", Income, Percent);
        m!("income_tax_exp", "所得税费用", Income, CurrencyYi);
        m!("total_profit", "利润总额", Income, CurrencyYi);

        // --- Balance Sheet ---
        m!("total_assets", "总资产", Balance, CurrencyYi);
        m!("fix_assets", "固定资产", Balance, CurrencyYi);
        m!("inventories", "存货", Balance, CurrencyYi);
        m!("accounts_receiv", "应收账款", Balance, CurrencyYi);
        m!("accounts_pay", "应付账款", Balance, CurrencyYi);
        m!("prepayment", "预付款项", Balance, CurrencyYi);
        m!("adv_receipts", "预收款项", Balance, CurrencyYi);
        m!("contract_liab", "合同负债", Balance, CurrencyYi);
        m!("money_cap", "货币资金", Balance, CurrencyYi);
        m!("lt_eqt_invest", "长期股权投资", Balance, CurrencyYi);
        m!("goodwill", "商誉", Balance, CurrencyYi);
        m!("st_borr", "短期借款", Balance, CurrencyYi);
        m!("lt_borr", "长期借款", Balance, CurrencyYi);
        m!("total_liab", "总负债", Balance, CurrencyYi);
        m!("total_hldr_eqy_exc_min_int", "股东权益", Balance, CurrencyYi); // 归母权益

        // --- Cash Flow ---
        m!("n_cashflow_act", "经营净现金流", CashFlow, CurrencyYi);
        m!("c_paid_to_for_empl", "支付职工现金", CashFlow, CurrencyYi);
        m!("c_pay_acq_const_fiolta", "购建资产支付", CashFlow, CurrencyYi);
        m!("dividend_amount", "分红总额", CashFlow, CurrencyYi);
        m!("n_cashflow_inv", "投资净现金流", CashFlow, CurrencyYi);
        m!("n_cashflow_fina", "筹资净现金流", CashFlow, CurrencyYi);

        // --- Ratios ---
        m!("arturn_days", "应收周转天数", Ratios, Days);
        m!("invturn_days", "存货周转天数", Ratios, Days);
        m!("__gross_margin", "毛利率", Ratios, Percent);
        m!("__net_margin", "净利率", Ratios, Percent);
        m!("__money_cap_ratio", "现金占比", Ratios, Percent);
        m!("__fix_assets_ratio", "固定资产占比", Ratios, Percent);
        m!("__lt_invest_ratio", "长投占比", Ratios, Percent);
        m!("__goodwill_ratio", "商誉占比", Ratios, Percent);
        m!("__ar_ratio", "应收占比", Ratios, Percent);
        m!("__ap_ratio", "应付占比", Ratios, Percent);
        m!("__st_borr_ratio", "短贷占比", Ratios, Percent);
        m!("__lt_borr_ratio", "长贷占比", Ratios, Percent);
        m!("__rd_rate", "研发费率", Ratios, Percent);
        m!("__sell_rate", "销售费率", Ratios, Percent);
        m!("__admin_rate", "管理费率", Ratios, Percent);
        m!("roe", "ROE", Ratios, Percent);
        m!("roa", "ROA", Ratios, Percent);
        m!("grossprofit_margin", "毛利率(原始)", Ratios, Percent);
        m!("netprofit_margin", "净利率(原始)", Ratios, Percent);

        // --- Derived/Misc (Previously Misc) ---
        m!("__depr_ratio", "折旧营收比", Ratios, Percent);
        m!("__inventories_ratio", "存货资产比", Ratios, Percent);
        m!("__prepay_ratio", "预付资产比", Ratios, Percent);
        m!("depr_fa_coga_dpba", "资产折旧摊销", CashFlow, CurrencyYi);
    }

    /// 格式化数值 (仅返回数值字符串)
    fn format_value(&self, val: f64, strategy: UnitStrategy) -> String {
        match strategy {
            UnitStrategy::CurrencyYi => format!("{:.2}", val / 1e8),
            UnitStrategy::CurrencyWan => format!("{:.2}", val / 1e4),
            UnitStrategy::Percent => format!("{:.2}", val), 
            UnitStrategy::Integer => format!("{:.0}", val),
            UnitStrategy::Raw => format!("{:.2}", val),
            UnitStrategy::Days => format!("{:.1}", val),
        }
    }

    /// 获取单位后缀
    fn get_unit_suffix(&self, strategy: UnitStrategy) -> &'static str {
        match strategy {
            UnitStrategy::CurrencyYi => "(亿)",
            UnitStrategy::CurrencyWan => "(万)",
            UnitStrategy::Percent => "(%)",
            UnitStrategy::Integer => "",
            UnitStrategy::Raw => "",
            UnitStrategy::Days => "(天)",
        }
    }

    /// 主入口: 将扁平的 Tushare 数据转换为 Markdown 字符串
    pub fn format_to_markdown(&self, symbol: &str, metrics: Vec<TushareMetric>) -> Result<String> {
        let report_type = self.detect_report_type(&metrics);
        let report = match report_type {
            ReportType::Yearly5Year => self.pivot_data_yearly(symbol, metrics)?,
            ReportType::Quarterly => self.pivot_data_quarterly(symbol, metrics)?,
        };
        self.render_markdown(&report)
    }

    /// 检测报表类型策略
    fn detect_report_type(&self, metrics: &[TushareMetric]) -> ReportType {
        // 策略：检查关键财务指标（如净利润 n_income）的日期分布
        // 如果 80% 以上的数据都是 12-31 结尾，则认为是年报优先模式
        let target_metric = "n_income";
        let mut total_count = 0;
        let mut year_end_count = 0;

        for m in metrics {
            if m.metric_name == target_metric {
                total_count += 1;
                if m.period_date.ends_with("-12-31") {
                    year_end_count += 1;
                }
            }
        }

        // 如果没有净利润数据，退回到检查所有数据
        if total_count == 0 {
            for m in metrics {
                total_count += 1;
                if m.period_date.ends_with("-12-31") {
                    year_end_count += 1;
                }
            }
        }

        if total_count > 0 {
            let ratio = year_end_count as f64 / total_count as f64;
            // 如果年报数据占比超过 80%，或者总数据量很少且都是年报
            if ratio > 0.8 {
                return ReportType::Yearly5Year;
            }
        }
        
        // 默认季报模式（原逻辑）
        ReportType::Quarterly
    }

    /// 模式 A: 5年聚合年报模式 (Yearly 5-Year Aggregation)
    /// 结构：Block = 5年 (e.g., 2020-2024), Columns = [2024, 2023, 2022, 2021, 2020]
    /// 注意：对于每一年，选取该年内最新的报告期数据作为代表（通常是年报 12-31，如果是当年则是最新季报）
    fn pivot_data_yearly(&self, symbol: &str, metrics: Vec<TushareMetric>) -> Result<FormattedReport> {
        // 1. 按年份分组，找出每一年最新的 period_date
        // Map<Year, MaxDate>
        let mut year_max_date: HashMap<String, String> = HashMap::new();
        
        for m in &metrics {
            let year = m.period_date.split('-').next().unwrap_or("").to_string();
            if year.is_empty() { continue; }

            year_max_date.entry(year)
                .and_modify(|curr| {
                    if m.period_date > *curr {
                        *curr = m.period_date.clone();
                    }
                })
                .or_insert(m.period_date.clone());
        }

        // 2. 收集数据，只保留对应年份最大日期的数据
        // Map<Year, Map<Metric, Value>>
        let mut data_map: HashMap<String, HashMap<String, f64>> = HashMap::new();
        let mut all_years: Vec<String> = Vec::new();

        for m in metrics {
            if let Some(val) = m.value {
                let year = m.period_date.split('-').next().unwrap_or("").to_string();
                if let Some(max_date) = year_max_date.get(&year) {
                    // 只有当这条数据的日期匹配该年最大日期时才采纳
                    // 注意：不同指标的最大日期可能理论上不同（数据缺失），但通常财务报表是整齐的
                    // 这里简化逻辑：只要该指标的日期等于该年的最大日期（基于所有指标的最大值？还是基于该指标？）
                    // 严格来说应该是：对于特定年份，我们选定一个“主报告期”（该年所有数据中日期的最大值）。
                    if m.period_date == *max_date {
                        data_map
                            .entry(year.clone())
                            .or_default()
                            .insert(m.metric_name, val);
                        
                        if !all_years.contains(&year) {
                            all_years.push(year);
                        }
                    }
                }
            }
        }

        // 排序年份 (倒序: 2024, 2023...)
        all_years.sort_by(|a, b| b.cmp(a));

        // 3. 按 5 年分块
        let chunks = all_years.chunks(5);
        let mut blocks = Vec::new();

        for chunk in chunks {
            if chunk.is_empty() { continue; }
            
            let start_year = chunk.last().unwrap();
            let end_year = chunk.first().unwrap();
            
            // 标题显示范围
            let block_title = format!("{} - {}", start_year, end_year);
            let periods = chunk.to_vec(); // ["2024", "2023", ...]

            // 构建 Sections
            let sections = self.build_sections(&periods, &|year| data_map.get(year));

            blocks.push(YearBlock {
                title: block_title,
                periods,
                sections,
            });
        }

        Ok(FormattedReport {
            title: format!("{} 财务年报 (5年聚合)", symbol),
            blocks,
        })
    }

    /// 模式 B: 季报模式 (Quarterly) - 原逻辑
    /// 结构：Block = 1年 (e.g., 2024), Columns = [2024-12-31, 2024-09-30, ...]
    fn pivot_data_quarterly(&self, symbol: &str, metrics: Vec<TushareMetric>) -> Result<FormattedReport> {
        // Map<Year, Map<Date, Map<Metric, Value>>>
        let mut year_map: BTreeMap<String, BTreeMap<String, HashMap<String, f64>>> = BTreeMap::new();

        for m in metrics {
            if let Some(val) = m.value {
                let year = m.period_date.split('-').next().unwrap_or("Unknown").to_string();
                year_map
                    .entry(year)
                    .or_default()
                    .entry(m.period_date.clone())
                    .or_default()
                    .insert(m.metric_name, val);
            }
        }

        let mut blocks = Vec::new();

        // 倒序遍历年份
        for (year, date_map) in year_map.iter().rev() {
            let mut periods: Vec<String> = date_map.keys().cloned().collect();
            periods.sort_by(|a, b| b.cmp(a)); // 倒序日期

            // 构建 Sections
            // 适配器闭包：给定 period (日期), 返回 MetricMap
            let sections = self.build_sections(&periods, &|period| date_map.get(period));

            blocks.push(YearBlock {
                title: format!("{}年度", year),
                periods,
                sections,
            });
        }

        Ok(FormattedReport {
            title: format!("{} 财务数据明细 (季报视图)", symbol),
            blocks,
        })
    }

    /// 通用 Section 构建器
    /// periods: 列头列表 (可能是年份 "2024" 也可能是日期 "2024-12-31")
    /// data_provider: 闭包，根据 period 获取该列的数据 Map<Metric, Value>
    fn build_sections<'a, F>(
        &self, 
        periods: &[String], 
        data_provider: &F
    ) -> Vec<ReportSection>
    where F: Fn(&str) -> Option<&'a HashMap<String, f64>>
    {
        // 1. 收集该 Block 下所有出现的 metric keys
        let mut all_metric_keys = std::collections::HashSet::new();
        for p in periods {
            if let Some(map) = data_provider(p) {
                for k in map.keys() {
                    all_metric_keys.insert(k.clone());
                }
            }
        }

        // 2. 分类
        let mut cat_metrics: BTreeMap<SectionCategory, Vec<String>> = BTreeMap::new();
        for key in all_metric_keys {
            if let Some(meta) = self.meta_map.get(&key) {
                cat_metrics.entry(meta.category).or_default().push(key);
            } else {
                cat_metrics.entry(SectionCategory::Misc).or_default().push(key);
            }
        }

        // 3. 生成 Sections
        let mut sections = Vec::new();
        let categories = vec![
            SectionCategory::Snapshot,
            SectionCategory::Income,
            SectionCategory::Balance,
            SectionCategory::CashFlow,
            SectionCategory::Ratios,
            SectionCategory::Misc,
        ];

        for cat in categories {
            if let Some(keys) = cat_metrics.get(&cat) {
                let mut sorted_keys = keys.clone();
                // 按照预定义的顺序或者字母序排序？目前简单用字母序，理想情况应该有 weight
                sorted_keys.sort(); 

                let mut rows = Vec::new();
                for key in sorted_keys {
                    let (label, strategy) = if let Some(meta) = self.meta_map.get(&key) {
                        (meta.display_name.to_string(), meta.strategy)
                    } else {
                        (key.clone(), UnitStrategy::Raw)
                    };

                    // Append unit suffix to label
                    let label_with_unit = format!("{}{}", label, self.get_unit_suffix(strategy));

                    let mut row_vals = Vec::new();
                    for p in periods {
                        let val_opt = data_provider(p).and_then(|m| m.get(&key));
                        if let Some(val) = val_opt {
                            row_vals.push(self.format_value(*val, strategy));
                        } else {
                            row_vals.push("-".to_string());
                        }
                    }
                    rows.push(FormatRow { label: label_with_unit, values: row_vals });
                }

                sections.push(ReportSection {
                    title: cat.title().to_string(),
                    rows,
                });
            }
        }
        sections
    }

    fn render_markdown(&self, report: &FormattedReport) -> Result<String> {
        let mut md = String::new();
        md.push_str(&format!("# {}\n\n", report.title));

        for block in &report.blocks {
            md.push_str(&format!("## {}\n\n", block.title));

            for section in &block.sections {
                if section.rows.is_empty() { continue; }

                md.push_str(&format!("### {}\n", section.title));
                
                // Table Header
                md.push_str("| 指标 |");
                for p in &block.periods {
                    md.push_str(&format!(" {} |", p));
                }
                md.push('\n');

                // Separator
                md.push_str("| :--- |");
                for _ in &block.periods {
                    md.push_str(" :--- |");
                }
                md.push('\n');

                // Rows
                for row in &section.rows {
                    md.push_str(&format!("| **{}** |", row.label));
                    for v in &row.values {
                        md.push_str(&format!(" {} |", v));
                    }
                    md.push('\n');
                }
                md.push('\n');
            }
        }

        Ok(md)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs;
    use std::path::PathBuf;

    #[test]
    fn test_format_tushare_real_data() {
        // Try to locate the assets file relative to the crate root
        let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        path.push("../../assets/tushare.json");

        if !path.exists() {
            println!("SKIPPED: Test data not found at {:?}", path);
            return;
        }

        println!("Loading test data from: {:?}", path);
        let json_content = fs::read_to_string(path).expect("Failed to read tushare.json");
        
        let metrics: Vec<TushareMetric> = serde_json::from_str(&json_content).expect("Failed to parse JSON");
        println!("Loaded {} metrics", metrics.len());

        let formatter = TushareFormatter::new();
        let md = formatter.format_to_markdown("600521.SS", metrics).expect("Format markdown");
        
        println!("\n=== GENERATED MARKDOWN REPORT START ===\n");
        println!("{}", md);
        println!("\n=== GENERATED MARKDOWN REPORT END ===\n");
        
        // Assertions
        // Title adapts to report type (e.g. "财务年报 (5年聚合)")
        assert!(md.contains("# 600521.SS 财务"));
        
        // Verify structure: Should have year ranges in 5-year mode
        // "2021 - 2025"
        assert!(md.contains("## 2021 - 2025"));
        assert!(md.contains("## 2016 - 2020"));

        // Verify content density
        // Ensure we have specific sections populated
        assert!(md.contains("### 利润表"));
        assert!(md.contains("### 资产负债表"));
        
        // Check for specific data point formatting (based on sample)
        // "money_cap": 1420023169.52 (2025-09-30) -> 14.20 亿
        // Updated assertion: Value should be "14.20", unit is in label "货币资金(亿)"
        assert!(md.contains("14.20"));
        assert!(md.contains("货币资金(亿)"));
    }
}

