#!/usr/bin/env python3
"""
个股深度分析 纯文字摘要生成器
从 JSON 数据文件读取分析结果，输出结构化纯文字总结。
产出物：.txt 文件，可直接阅读或粘贴到聊天/邮件/文档中使用。
"""

import json
import argparse
import os
from datetime import datetime


def load_data(data_file):
    with open(data_file, 'r', encoding='utf-8') as f:
        return json.load(f)


def safe_get(d, *keys, default='--'):
    """安全取值，多层嵌套兜底"""
    for k in keys:
        if isinstance(d, dict):
            d = d.get(k, {})
        else:
            return default
    return d if d != {} else default


def fmt_pct(v):
    """格式化百分比（保留 1 位小数）"""
    if v is None or v == '':
        return '--'
    try:
        return f'{float(v):.1f}%'
    except (ValueError, TypeError):
        return str(v)


def fmt_num_cn(v):
    """格式化数字为中文可读形式"""
    if v is None or v == '':
        return '--'
    try:
        v = float(v)
        if abs(v) >= 1e8:
            return f'{v/1e8:.2f}亿'
        elif abs(v) >= 1e4:
            return f'{v/1e4:.2f}万'
        else:
            return f'{v:.2f}'
    except (ValueError, TypeError):
        return str(v)


def fmt_yn(val):
    """是/否格式化"""
    if val is None:
        return '无数据'
    return '是' if val else '否'


def generate_text_summary(data):
    stock = data.get('stock', {})
    name = stock.get('name', '--')
    code = stock.get('code', '--')
    industry = f"{stock.get('industry_l1', '--')} - {stock.get('industry_l2', '--')}"
    market_cap = stock.get('market_cap')
    today = datetime.now().strftime('%Y-%m-%d')
    source = data.get('source', '通联数据 MCP + 华泰智研 MCP')

    summary = data.get('summary', {})
    grading = data.get('grading', {})
    industry_analysis = data.get('industry_analysis', {})
    advantages = data.get('advantages', '--')
    growth_analysis = data.get('growth_analysis', '--')
    moat = data.get('moat', {})
    finance = data.get('finance', {})
    valuation = data.get('valuation', {})
    technical = data.get('technical', {})
    capital = data.get('capital', {})
    catalysts = data.get('catalysts', [])
    risk = data.get('risk', {})
    opinion = data.get('opinion', {})
    operation = data.get('operation', {})
    tracking = data.get('tracking', [])
    quant_factors = data.get('quant_factors', {})
    peers = data.get('peers', [])
    framework_insights = data.get('framework_insights', {})

    lines = []
    sep = '=' * 78

    # ---- 头部 ----
    lines.append(sep)
    lines.append(f'  {name}（{code}）深度分析摘要')
    lines.append(f'  行业：{industry}')
    if market_cap:
        lines.append(f'  总市值：{fmt_num_cn(market_cap)}元')
    lines.append(f'  数据截止：{today} | 数据来源：{source}')
    lines.append(sep)
    lines.append('')

    # ---- 一、核心结论 ----
    lines.append('一、核心结论')
    lines.append('─' * 40)
    conclusion = summary.get('conclusion', '--')
    overall_score = grading.get('overall_score', '--')
    overall_grade = grading.get('overall_grade', '--')
    grade_desc = grading.get('grade_desc', '')
    highlights = summary.get('highlights', [])
    main_risk = summary.get('main_risk', '')

    lines.append(f'定性判断：{conclusion}')
    lines.append(f'六维综合评分：{overall_score}/10 | 评级：{overall_grade}（{grade_desc}）' if grade_desc else f'六维综合评分：{overall_score}/10 | 评级：{overall_grade}')

    if highlights:
        lines.append(f'核心亮点：{"；".join(highlights)}')
    if main_risk:
        lines.append(f'主要风险：{main_risk}')

    # 六维明细
    dims = grading.get('dimensions', {})
    if dims:
        dim_labels = {
            'business_model': '商业模式',
            'financial_quality': '财务质量',
            'moat': '护城河',
            'valuation': '估值水平',
            'catalyst': '催化剂',
            'risk': '风险因素'
        }
        dim_parts = []
        for key, label in dim_labels.items():
            d = dims.get(key, {})
            score = d.get('score', '--')
            dim_parts.append(f'{label}={score}')
        lines.append(f'六维明细：{", ".join(dim_parts)}')

    veto_flags = grading.get('veto_flags', [])
    if veto_flags:
        lines.append(f'一票否决：{"；".join(veto_flags)}')

    lines.append('')

    # ---- 二、行业与竞争 ----
    lines.append('二、行业定位与竞争优势')
    lines.append('─' * 40)
    if isinstance(industry_analysis, dict):
        sector_pos = industry_analysis.get('sector_position', '')
        space = industry_analysis.get('space', '')
        trend = industry_analysis.get('trend', '')
        competition = industry_analysis.get('competition', '')
        cycle = industry_analysis.get('cycle', '')
        if sector_pos:
            lines.append(f'产业链位置：{sector_pos}')
        if space:
            lines.append(f'行业空间：{space}')
        if trend:
            lines.append(f'行业趋势：{trend}')
        if competition:
            lines.append(f'竞争格局：{competition}')
        if cycle:
            lines.append(f'周期位置：{cycle}')
    elif isinstance(industry_analysis, str) and industry_analysis:
        lines.append(industry_analysis)

    # 护城河
    if isinstance(moat, dict):
        categories = moat.get('categories', [])
        depth_map = {'deep': '深', 'moderate': '中等', 'shallow': '浅'}
        depth_raw = moat.get('depth', '')
        depth = depth_map.get(depth_raw, depth_raw)
        sustainability = moat.get('sustainability', '')
        desc = moat.get('description', '')
        if categories:
            lines.append(f'护城河类型：{"、".join(categories)}（深度：{depth}，持续性：{sustainability}）')
        if desc:
            lines.append(f'护城河分析：{desc}')

    # 竞争优势
    if advantages and advantages != '--':
        lines.append(f'核心优势：{advantages}')

    # 成长逻辑
    if growth_analysis and growth_analysis != '--':
        lines.append(f'成长逻辑：{growth_analysis}')

    lines.append('')

    # ---- 三、财务质量 ----
    lines.append('三、财务质量')
    lines.append('─' * 40)

    # 核心财务指标
    revenue_list = finance.get('revenue', [])
    net_profit_list = finance.get('net_profit', [])
    gross_margin_list = finance.get('gross_margin', [])
    roe_list = finance.get('roe', [])
    debt_ratio_list = finance.get('debt_ratio', [])
    fcff_list = finance.get('fcff', [])

    rev_strs = [f"{r.get('period','?')}:{fmt_num_cn(r.get('value'))}" for r in revenue_list]
    if rev_strs:
        lines.append(f'营业收入：{", ".join(rev_strs)}')

    np_strs = [f"{r.get('period','?')}:{fmt_num_cn(r.get('value'))}" for r in net_profit_list]
    if np_strs:
        lines.append(f'归母净利润：{", ".join(np_strs)}')

    gm_strs = [f"{r.get('period','?')}:{fmt_pct(r.get('value'))}" for r in gross_margin_list]
    if gm_strs:
        lines.append(f'毛利率：{", ".join(gm_strs)}')

    roe_strs = [f"{r.get('period','?')}:{fmt_pct(r.get('value'))}" for r in roe_list]
    if roe_strs:
        lines.append(f'ROE：{", ".join(roe_strs)}')

    dr_strs = [f"{r.get('period','?')}:{fmt_pct(r.get('value'))}" for r in debt_ratio_list]
    if dr_strs:
        lines.append(f'资产负债率：{", ".join(dr_strs)}')

    fcff_strs = [f"{r.get('period','?')}:{fmt_num_cn(r.get('value'))}" for r in fcff_list] if fcff_list else []
    if fcff_strs:
        lines.append(f'自由现金流：{", ".join(fcff_strs)}')

    # 杜邦分析
    dupont = finance.get('dupont', {})
    if dupont:
        nm = fmt_pct(dupont.get('net_margin'))
        at = dupont.get('asset_turnover', '--')
        lev = dupont.get('leverage', '--')
        lines.append(f'ROE 杜邦拆解：净利率 {nm} × 周转率 {at} × 杠杆 {lev}')

    # 财务评级与造假排查
    fin_rating = finance.get('rating', '')
    fraud_flags = finance.get('fraud_flags', {})
    if fin_rating:
        lines.append(f'财务评级：{fin_rating}')
    if fraud_flags:
        m_score = fraud_flags.get('m_score', '--')
        flags = fraud_flags.get('flags', [])
        lines.append(f'M-Score 造假排查：{m_score}（{"; ".join(flags) if flags else "未发现明显异常"}）')

    lines.append('')

    # ---- 四、估值分析 ----
    lines.append('四、估值水平')
    lines.append('─' * 40)

    pe = valuation.get('pe_ttm')
    pb = valuation.get('pb')
    ps = valuation.get('ps_ttm')
    pe_pct = valuation.get('pe_percentile_5y')
    peg = valuation.get('peg')
    preferred = valuation.get('preferred_method', '')
    safety = valuation.get('safety_margin', '')
    fair_range = valuation.get('fair_value_range', '')
    dcf_ref = valuation.get('dcf_reference', {})

    if pe is not None:
        lines.append(f'PE-TTM：{pe}x')
    if pb is not None:
        lines.append(f'PB：{pb}x')
    if ps is not None:
        lines.append(f'PS-TTM：{ps}x')
    if pe_pct is not None:
        lines.append(f'PE 历史分位（5年）：{fmt_pct(pe_pct)}')
    if peg is not None:
        lines.append(f'PEG：{peg}')
    if preferred:
        lines.append(f'推荐估值方法：{preferred}')
    # DCF
    dcf_ref_val = valuation.get('dcf_reference') or {}
    if safe_get(dcf_ref_val, 'fair_value'):
        wacc_raw = dcf_ref_val.get('wacc')
        growth_raw = dcf_ref_val.get('growth_rate')
        wacc_str = f'{float(wacc_raw)*100:.1f}%' if wacc_raw is not None else '--'
        growth_str = f'{float(growth_raw)*100:.1f}%' if growth_raw is not None else '--'
        lines.append(f'DCF 参考合理价：{safe_get(dcf_ref_val, "fair_value")}元（WACC={wacc_str}，永续增速={growth_str}）')
    if safety:
        lines.append(f'安全边际：{safety}')
    if fair_range:
        lines.append(f'合理估值区间：{fair_range}')

    # 同行对比
    if peers:
        lines.append('')
        lines.append('同行业对比：')
        lines.append(f'{"名称":<10s} {"PE":>6s} {"ROE":>8s} {"营收增速":>10s}')
        lines.append('-' * 36)
        for p in peers:
            pname = p.get('name', '--')[:8]
            ppe = p.get('pe', '--')
            proe = fmt_pct(p.get('roe'))
            pgrowth = fmt_pct(p.get('revenue_growth'))
            lines.append(f'{pname:<10s} {str(ppe):>6s} {proe:>8s} {pgrowth:>10s}')

    lines.append('')

    # ---- 五、技术面 ----
    lines.append('五、技术走势')
    lines.append('─' * 40)
    trend = technical.get('trend', '--')
    support = technical.get('support')
    resistance = technical.get('resistance')
    ma5 = technical.get('ma5')
    ma20 = technical.get('ma20')
    vol_trend = technical.get('volume_trend', '--')

    lines.append(f'趋势判断：{trend}')
    if support:
        lines.append(f'支撑位：{support}')
    if resistance:
        lines.append(f'压力位：{resistance}')
    if ma5 and ma20:
        lines.append(f'MA5：{ma5} | MA20：{ma20}')
    lines.append(f'量能状态：{vol_trend}')
    lines.append('')

    # ---- 六、量化因子（如有） ----
    qfactors = quant_factors.get('factors', [])
    if qfactors:
        lines.append('六、量化因子仪表盘')
        lines.append('─' * 40)
        for qf in qfactors:
            qname = qf.get('name', '--')
            qval = qf.get('value', '--')
            qrank = qf.get('rank_pct')
            qind = qf.get('industry_rank_pct')
            note = qf.get('note', '')
            rank_str = f'全市场优于{fmt_pct(qrank)}标的' if qrank is not None else '--'
            ind_str = f'，行业优于{fmt_pct(qind)}标的' if qind is not None else ''
            note_str = f'（{note}）' if note else ''
            lines.append(f'  {qname}：值={qval}，{rank_str}{ind_str}{note_str}')

        highlights_qf = quant_factors.get('highlights', [])
        warnings_qf = quant_factors.get('warnings', [])
        if highlights_qf:
            lines.append(f'高亮因子：{"；".join(highlights_qf)}')
        if warnings_qf:
            lines.append(f'警示因子：{"；".join(warnings_qf)}')
        lines.append('')

        # Adjust section numbers
        next_section_num = 7
    else:
        next_section_num = 6

    # ---- 七、资金面与催化 ----
    lines.append(f'{["六","七"][next_section_num-6]}、资金面与筹码')
    lines.append('─' * 40)

    main_flow = capital.get('main_flow', '--')
    north_flow = capital.get('north_flow', '--')
    margin_bal = capital.get('margin_balance', '--')
    shareholders = capital.get('shareholders_change', '--')
    inst_holding = capital.get('institution_holding', '--')
    major_signals = capital.get('major_holder_signals', {})

    if main_flow:
        lines.append(f'主力资金：{main_flow}')
    if north_flow:
        lines.append(f'北向资金：{north_flow}')
    if margin_bal:
        lines.append(f'融资余额：{margin_bal}')
    if shareholders:
        lines.append(f'股东户数变化：{shareholders}')
    if inst_holding:
        lines.append(f'机构持仓：{inst_holding}')

    # 大股东信号
    if major_signals:
        sig_parts = []
        if isinstance(major_signals, dict):
            for k, v in major_signals.items():
                if '质押' in str(k):
                    sig_parts.append(f'质押比例={v}')
                elif v is True:
                    sig_parts.append(f'{k}')
        if sig_parts:
            lines.append(f'大股东信号：{"，".join(sig_parts)}')

    lines.append('')

    # ---- 催化剂 ----
    lines.append(f'{["七","八"][next_section_num-6]}、近期催化因素')
    lines.append('─' * 40)
    if catalysts:
        for cat in catalysts:
            ctype = cat.get('type', '')
            cevent = cat.get('event', '--')
            cimpact = cat.get('impact', '--')
            cduration = cat.get('duration', '--')
            lines.append(f'  [{ctype}] {cevent}（影响：{cimpact}，周期：{cduration}）')
    else:
        lines.append('  暂无明确催化剂。')
    lines.append('')

    # ---- 风险因素 ----
    lines.append(f'{["八","九"][next_section_num-6]}、风险因素')
    lines.append('─' * 40)

    risk_matrix = risk.get('risk_matrix', {})
    fatal = risk_matrix.get('fatal', [])
    major = risk_matrix.get('major', [])
    manageable = risk_matrix.get('manageable', [])

    if fatal:
        lines.append('致命风险：')
        for r in fatal:
            lines.append(f'  — {r.get("name","")}: {r.get("desc","")}（概率={r.get("probability","")}，影响={r.get("impact","")}）')

    if major:
        lines.append('重大风险：')
        for r in major:
            lines.append(f'  — {r.get("name","")}: {r.get("desc","")}（概率={r.get("probability","")}，影响={r.get("impact","")}）')

    if manageable:
        lines.append('可管理风险：')
        for r in manageable:
            lines.append(f'  — {r.get("name","")}: {r.get("desc","")}（概率={r.get("probability","")}，影响={r.get("impact","")}）')

    if not fatal and not major and not manageable:
        lines.append('  无明确风险记录。')

    # 预警指标
    warning_thresholds = risk.get('warning_thresholds', {})
    if warning_thresholds:
        lines.append('财务预警指标：')
        for k, v in warning_thresholds.items():
            lines.append(f'  - {k}: {v}')

    lines.append('')

    # ---- 投资观点 ----
    lines.append(f'{["九","十"][next_section_num-6]}、投资观点')
    lines.append('─' * 40)
    short_view = opinion.get('short', '--')
    mid_view = opinion.get('mid', '--')
    long_view = opinion.get('long', '--')
    principal_view = opinion.get('principal_asset_view', '')

    if summary.get('rating_short'):
        lines.append(f'短期（1周-1月）：{summary.get("rating_short")}')
    if short_view:
        lines.append(f'短期观点：{short_view}')
    if summary.get('rating_mid'):
        lines.append(f'中期（1-6月）：{summary.get("rating_mid")}')
    if mid_view:
        lines.append(f'中期观点：{mid_view}')
    if summary.get('rating_long'):
        lines.append(f'长期（6月+）：{summary.get("rating_long")}')
    if long_view:
        lines.append(f'长期观点：{long_view}')
    if principal_view:
        lines.append(f'首席策略参考：{principal_view}')

    # 框架洞察
    if framework_insights:
        fi_industry = framework_insights.get('industry_position', '')
        fi_emotion = framework_insights.get('market_emotion', '')
        fi_capital = framework_insights.get('capital_flow_context', '')
        fi_rotation = framework_insights.get('rotation_context', '')
        if fi_industry:
            lines.append(f'行业定位：{fi_industry}')
        if fi_emotion:
            lines.append(f'市场情绪：{fi_emotion}')
        if fi_capital:
            lines.append(f'资金面背景：{fi_capital}')
        if fi_rotation:
            lines.append(f'轮动环境：{fi_rotation}')

    lines.append('')

    # ---- 操作参考 ----
    lines.append(f'{["十","十一"][next_section_num-6]}、操作参考')
    lines.append('─' * 40)
    buy_zone = operation.get('buy_zone', '--')
    add_cond = operation.get('add_condition', '--')
    stop_loss = operation.get('stop_loss', '--')
    target = operation.get('target', '--')
    veto_triggers = operation.get('veto_triggers', [])

    lines.append(f'买入区间：{buy_zone}')
    lines.append(f'加仓条件：{add_cond}')
    lines.append(f'止损位：{stop_loss}')
    lines.append(f'目标价：{target}')
    if veto_triggers:
        lines.append(f'一票否决触发条件：{"；".join(veto_triggers)}')

    lines.append('')

    # ---- 跟踪指标 ----
    if tracking:
        lines.append(f'{["十一","十二"][next_section_num-6]}、后续跟踪指标')
        lines.append('─' * 40)
        for i, t in enumerate(tracking, 1):
            lines.append(f'  {i}. {t}')
        lines.append('')

    # ---- 免责声明 ----
    lines.append(sep)
    lines.append('免责声明')
    lines.append('─' * 40)
    lines.append('以上内容仅作为研究分析和投资参考，不构成任何保证收益或直接买卖建议。')
    lines.append('市场有风险，投资需谨慎。具体操作应结合个人风险承受能力、仓位情况和')
    lines.append('实时市场变化。过往业绩不代表未来表现，投资决策应基于独立判断。')
    lines.append('')
    lines.append('华泰智研声明：以上内容由 AI 基于华泰证券研究报告及其附属成果总结')
    lines.append('生成，可能省略完整报告中的重要信息、市场风险、业绩不及预期等风险，')
    lines.append('请务必阅读完整原始报告。有关数据、观点、评级等具有时效性，请自行')
    lines.append('核实最新信息。')
    lines.append(sep)

    return '\n'.join(lines)


def main():
    parser = argparse.ArgumentParser(description='个股深度分析 纯文字摘要生成器')
    parser.add_argument('--data-file', required=True, help='JSON 数据文件路径')
    parser.add_argument('--name', default='', help='股票名称（输出文件名用）')
    parser.add_argument('--code', default='', help='股票代码（输出文件名用）')
    parser.add_argument('--output', '-o', default=None, help='输出文件路径')

    args = parser.parse_args()

    data = load_data(args.data_file)

    if args.name:
        data.setdefault('stock', {})['name'] = args.name
    if args.code:
        data.setdefault('stock', {})['code'] = args.code

    text = generate_text_summary(data)

    # 确定输出路径
    if args.output:
        out_path = args.output
    else:
        stock_code = args.code or data.get('stock', {}).get('code', '000000')
        today = datetime.now().strftime('%Y-%m-%d')
        script_dir = os.path.dirname(os.path.abspath(__file__))
        skill_dir = os.path.dirname(script_dir)
        out_path = os.path.join(skill_dir, f'stock_analysis_{stock_code}_{today}.txt')

    with open(out_path, 'w', encoding='utf-8') as f:
        f.write(text)

    print(f'FILE:{os.path.abspath(out_path)}')


if __name__ == '__main__':
    main()
