from .base_generator import BaseReporter
import pandas as pd
import datetime
import os
import markdown

class VN_ReportGenerator(BaseReporter):
    def __init__(self):
        super().__init__()
        self.indicators = {
            "主要指标": [
                ('ROE', 'ROE', 'percent'),
                ('ROA', 'ROA', 'percent'),
                ('ROIC', 'ROCE/ROIC', 'percent'),
                ('GrossMargin', '毛利率', 'percent'),
                ('NetMargin', '净利润率', 'percent'),
                ('revenue', '收入(亿 CNY)', 'currency_yi'),
                ('RevenueGrowth', '收入增速', 'percent_color'),
                ('net_income', '净利润(亿 CNY)', 'currency_yi'),
                ('NetIncomeGrowth', '净利润增速', 'percent_color'),
                ('ocf', '经营净现金流(亿 CNY)', 'currency_yi_color'),
                ('Capex', '资本开支(亿 CNY)', 'currency_yi'),
                ('FCF', '自由现金流(亿 CNY)', 'currency_yi_compare'),
                ('dividends', '分红(亿 CNY)', 'currency_yi'),
                ('repurchases', '回购(亿 CNY)', 'currency_yi'),
                ('total_assets', '总资产(亿 CNY)', 'currency_yi'),
                ('total_equity', '净资产(亿 CNY)', 'currency_yi'),
                ('goodwill', '商誉(亿 CNY)', 'currency_yi')
            ],
            "费用指标": [
                ('SellingRatio', '销售费用率', 'percent'),
                ('AdminRatio', '管理费用率', 'percent'),
                ('SgaRatio', 'SG&A比例', 'percent'),
                ('RDRatio', '研发费用率', 'percent'),
                ('OtherExpenseRatio', '其他费用率', 'percent'),
                ('DepreciationRatio', '折旧费用占比', 'percent'),
                ('TaxRate', '所得税率', 'percent'),
            ],
            "资产占比": [
                ('CashRatio', '现金占比', 'percent_alert_30'),
                ('InventoryRatio', '库存占比', 'percent'),
                ('ReceivablesRatio', '应收款占比', 'percent'),
                ('PrepaymentRatio', '预付款占比', 'percent'),
                ('FixedAssetsRatio', '固定资产占比', 'percent'),
                ('LongTermInvestmentRatio', '长期投资占比', 'percent'),
                ('GoodwillRatio', '商誉占比', 'percent'),
                ('OtherAssetsRatio', '其他资产占比', 'percent'),
                ('PayablesRatio', '应付款占比', 'percent'),
                ('AdvanceReceiptsRatio', '预收款占比', 'percent'),
                ('ShortTermDebtRatio', '短期借款占比', 'percent'),
                ('LongTermDebtRatio', '长期借款占比', 'percent'),
                ('OperatingAssetsRatio', '运营资产占比', 'percent'),
                ('InterestBearingDebtRatio', '有息负债率', 'percent'),
            ],
            "周转能力": [
                ('InventoryDays', '存货周转天数', 'int'),
                ('ReceivablesDays', '应收款周转天数', 'int_alert_90'),
                ('PayablesDays', '应付款周转天数', 'int'),
                ('FixedAssetsTurnover', '固定资产周转率', 'float'),
                ('TotalAssetTurnover', '总资产周转率', 'float'),
            ],
            "人均效率": [
                ('Employees', '员工人数', 'int'),
                ('RevenuePerEmp', '人均创收(万 CNY)', 'currency_wan'),
                ('ProfitPerEmp', '人均创利(万 CNY)', 'currency_wan'),
                ('AvgWage', '人均薪酬(万 CNY)', 'currency_wan'),
            ],
            "市场表现": [
                ('Price', '股价 (CNY)', 'float'),
                ('MarketCap', '市值(亿 CNY)', 'currency_yi_market'),
                ('PE', 'PE', 'float'),
                ('PB', 'PB', 'float'),
                ('Shareholders', '股东户数', 'int'),
            ]
        }

    def _preprocess_data(self, df, market):
        df = super()._preprocess_data(df, market)
        if not df.empty:
            dates = pd.to_datetime(df['date_str'], format='%Y%m%d')
            latest_year = dates.dt.year.max()
            is_dec = dates.dt.month == 12
            is_latest = df.index == df.index[0] 
            df = df[is_dec | is_latest]
        return df

    def _format_period_label(self, date_value):
        if pd.isna(date_value):
            return "-"
        date_str = str(date_value)
        if len(date_str) != 8:
            return date_str
        year = date_str[:4]
        try:
            return f"{year}A"
        except ValueError:
            return f"{year}A"

    def _get_headers(self, df):
        return [self._format_period_label(date_value) for date_value in df['date_str']]

    def _generate_md_company_info(self, symbol, metrics, market):
        today_str = datetime.date.today().strftime("%Y-%m-%d")
        name = metrics.get('name', '')
        raw_list_date = metrics.get('list_date', '')
        if isinstance(raw_list_date, str) and len(raw_list_date) == 8:
            list_date = f"{raw_list_date[:4]}-{raw_list_date[4:6]}-{raw_list_date[6:]}"
        else:
            list_date = raw_list_date
        pe = metrics.get('pe', 0) or 0
        pb = metrics.get('pb', 0) or 0
        div = metrics.get('dividend_yield', 0) or 0        
        md = []
        md.append(f"# {name} ({symbol}) - Financial Report")
        md.append(f"*Report generated on: {today_str}*\n")
        md.append("| 代码 | 简称 | 上市日期 | PE | PB | 股息率(%) |")
        md.append("|:---|:---|:---|:---|:---|:---|")
        md.append(f"| {symbol} | {name} | {list_date} | {pe:.2f} | {pb:.2f} | {div:.2f}% |")
        return "\n".join(md)

    def generate_report(self, df_analysis, symbol, market, metrics, output_dir):
        md_content = self._generate_markdown_content(df_analysis, market, symbol, metrics)
        os.makedirs(output_dir, exist_ok=True)
        md_path = os.path.join(output_dir, "report.md")
        with open(md_path, "w", encoding='utf-8') as f:
            f.write(md_content)
        
        df_for_html = df_analysis.copy() if isinstance(df_analysis, pd.DataFrame) else pd.DataFrame()
        if not df_for_html.empty:
            df_for_html = self._preprocess_data(df_for_html, market)
            headers = self._get_headers(df_for_html)
        else:
            headers = []
        html_content = self._build_html_content(symbol, metrics, headers, df_for_html)
        final_html = self.to_html(symbol, html_content)
        
        html_path = os.path.join(output_dir, "report.html")
        with open(html_path, "w", encoding='utf-8') as f:
            f.write(final_html)

    def _build_html_content(self, symbol, metrics, headers, df):
        today_str = datetime.date.today().strftime("%Y-%m-%d")
        name = metrics.get('name') or symbol
        raw_list_date = metrics.get('list_date', '')
        if isinstance(raw_list_date, str) and len(raw_list_date) == 8:
            list_date = f"{raw_list_date[:4]}-{raw_list_date[4:6]}-{raw_list_date[6:]}"
        else:
            list_date = raw_list_date or "-"
        pe = metrics.get('pe', 0) or 0
        pb = metrics.get('pb', 0) or 0
        div = metrics.get('dividend_yield', 0) or 0

        company_table = f"""
        <table class="company-table">
            <thead>
                <tr>
                    <th>代码</th>
                    <th>简称</th>
                    <th>上市日期</th>
                    <th>PE</th>
                    <th>PB</th>
                    <th>股息率(%)</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>{symbol}</td>
                    <td>{name}</td>
                    <td>{list_date}</td>
                    <td>{pe:.2f}</td>
                    <td>{pb:.2f}</td>
                    <td>{div:.2f}%</td>
                </tr>
            </tbody>
        </table>
        """

        if df is None or df.empty or not headers:
            metrics_table = "<p class=\"no-data\">暂无可用财务指标</p>"
        else:
            header_cells = "".join([f"<th>{header}</th>" for header in headers])
            data_column_count = max(len(headers), 1)
            rows_html = []
            for group_name, items in self.indicators.items():
                rows_html.append(
                    f"<tr class=\"section-row\">"
                    f"<td class=\"section-label\">{group_name}</td>"
                    f"<td class=\"section-spacer\" colspan=\"{data_column_count}\"></td>"
                    "</tr>"
                )
                for key, label, fmt_type in items:
                    value_cells = [f"<td class=\"metric-name\">{label}</td>"]
                    for _, row_series in df.iterrows():
                        value_cells.append(f"<td>{self._format_value(row_series.get(key), fmt_type)}</td>")
                    row_class = "other-assets-row" if key == 'OtherAssetsRatio' else ""
                    if row_class:
                        rows_html.append(f"<tr class=\"{row_class}\">{''.join(value_cells)}</tr>")
                    else:
                        rows_html.append(f"<tr>{''.join(value_cells)}</tr>")
            rows_markup = "\n".join(rows_html)
            metrics_table = f"""
            <table class="metrics-table" data-table="metrics" data-scrollable="true">
                <thead>
                    <tr>
                        <th>指标</th>
                        {header_cells}
                    </tr>
                </thead>
                <tbody>
                    {rows_markup}
                </tbody>
            </table>
            """

        html_sections = [
            f"<h1>{name} ({symbol}) - Financial Report</h1>",
            f"<p><em>Report generated on: {today_str}</em></p>",
            company_table,
            '<div class="table-gap"></div>',
            metrics_table
        ]
        return "\n".join(html_sections)

    def to_html(self, symbol, html_content):
        styled_html = '''
        <html>
            <head>
                <meta charset="utf-8" />
                <meta name="viewport" content="width=device-width, initial-scale=1" />
                <title>{symbol} Financial Report</title>
                <style>
                    :root {
                        --bg: #f5f6fa;
                        --card-bg: #ffffff;
                        --header-bg: #f7f8fb;
                        --section-bg: #f0f2f5;
                        --border: #e5e7eb;
                        --text-primary: #111827;
                        --text-secondary: #6b7280;
                    }

                    * {
                        box-sizing: border-box;
                    }

                    body {
                        margin: 0;
                        padding: 32px;
                        background: var(--bg);
                        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
                        color: var(--text-primary);
                        line-height: 1.6;
                    }

                    .report-container {
                        max-width: 1280px;
                        margin: 0 auto;
                        background: var(--card-bg);
                        border-radius: 24px;
                        padding: 32px 40px;
                        box-shadow: 0 24px 60px rgba(15, 23, 42, 0.08);
                    }

                    h1 {
                        margin: 0 0 8px;
                        font-size: 28px;
                        font-weight: 600;
                        color: var(--text-primary);
                    }

                    p {
                        margin: 0 0 24px;
                        color: var(--text-secondary);
                        font-size: 0.95rem;
                    }

                    table {
                        width: 100%;
                        border-collapse: collapse;
                        background: var(--card-bg);
                    }

                    th,
                    td {
                        font-size: 0.95rem;
                        padding: 12px 16px;
                        border-bottom: 1px solid var(--border);
                    }

                    th {
                        font-weight: 600;
                        color: var(--text-secondary);
                        text-align: right;
                        background: var(--header-bg);
                    }

                    th:first-child,
                    td:first-child {
                        text-align: left;
                    }

                    .company-table th,
                    .company-table td {
                        text-align: left;
                    }

                    .metrics-table thead {
                        position: sticky;
                        top: 0;
                        z-index: 3;
                    }

                    .metrics-table thead th {
                        position: sticky;
                        top: 0;
                        z-index: 3;
                        background: var(--card-bg);
                        box-shadow: 0 10px 20px rgba(15, 23, 42, 0.08);
                    }

                    .metrics-table thead th:first-child {
                        left: 0;
                        z-index: 4;
                        box-shadow: 16px 0 24px rgba(15, 23, 42, 0.08);
                    }

                    .metrics-table th:first-child,
                    .metrics-table td:first-child {
                        width: 180px;
                        min-width: 180px;
                    }

                    .metrics-table tbody td:first-child {
                        position: sticky;
                        left: 0;
                        background: var(--card-bg);
                        font-weight: 600;
                        box-shadow: 16px 0 24px rgba(15, 23, 42, 0.04);
                        z-index: 2;
                        text-align: left;
                    }

                    .metrics-table tbody td:not(:first-child) {
                        text-align: right;
                    }

                    .metrics-table tr.other-assets-row td {
                        background: #fff7e0;
                    }

                    .metrics-table tr.other-assets-row td:first-child {
                        background: #fff7e0;
                    }

                    .metrics-table tbody tr:hover td {
                        background: #f4efff;
                    }

                    .section-row td {
                        background: #eef1f6;
                        font-weight: 600;
                        text-align: left;
                        border-bottom: 1px solid var(--border);
                    }

                    .metrics-table .section-row td:first-child {
                        position: sticky;
                        left: 0;
                        z-index: 2;
                        box-shadow: 16px 0 24px rgba(15, 23, 42, 0.08);
                        background: #eef1f6 !important;
                    }

                    .metrics-table .section-label {
                        color: var(--text-primary);
                        background: #eef1f6 !important;
                    }

                    .section-spacer {
                        background: #eef1f6;
                    }

                    .metric-name {
                        color: var(--text-secondary);
                    }

                    .table-container {
                        overflow-x: auto;
                        border: 1px solid var(--border);
                        border-radius: 16px;
                        margin-bottom: 24px;
                    }

                    .table-container table {
                        margin-bottom: 0;
                        min-width: 960px;
                    }

                    .table-gap {
                        height: 24px;
                    }

                    .no-data {
                        margin-top: 24px;
                        padding: 32px;
                        text-align: center;
                        border: 1px dashed var(--border);
                        border-radius: 16px;
                        color: var(--text-secondary);
                        font-size: 0.95rem;
                    }

                    .bg-green { background-color: #e6f7eb !important; }
                    .bg-red { background-color: #ffeef0 !important; }
                    .font-red { color: #d32f2f !important; }
                    .font-green { color: #1b873f !important; }
                    .font-blue { color: #2563eb !important; }
                    .italic { font-style: italic !important; }

                    @media (max-width: 768px) {
                        body { padding: 16px; }
                        .report-container { padding: 24px; }
                        table { font-size: 0.85rem; }
                        th,
                        td { padding: 10px 12px; }
                    }
                </style>
            </head>
            <body>
                <div class="report-container">
                    {html_content}
                </div>
                <script>
                document.addEventListener('DOMContentLoaded', function() {
                    const scrollableTables = document.querySelectorAll('table[data-scrollable="true"]');
                    scrollableTables.forEach(table => {
                        const container = document.createElement('div');
                        container.className = 'table-container';
                        table.parentNode.insertBefore(container, table);
                        container.appendChild(table);
                    });

                    const parseValue = (text) => {
                        if (!text || text.trim() === '-') return null;
                        return parseFloat(text.replace(/%|,/g, ''));
                    };

                    const highlightIfOverThirtyPercent = (cell) => {
                        const value = parseValue(cell.textContent);
                        if (value !== null && value > 30) {
                            cell.classList.add('bg-red', 'font-red');
                        }
                    };

                    const styleRules = {
                        'ROE': (cell) => {
                            const value = parseValue(cell.textContent);
                            if (value !== null && value > 15) cell.classList.add('bg-green');
                        },
                        'ROA': (cell) => {
                            const value = parseValue(cell.textContent);
                            if (value !== null && value > 10) cell.classList.add('bg-green');
                        },
                        '毛利率': (cell) => {
                            const value = parseValue(cell.textContent);
                            if (value !== null && value > 50) cell.classList.add('bg-green');
                        },
                        '净利润率': (cell) => {
                            const value = parseValue(cell.textContent);
                            if (value !== null) {
                                if (value > 20) {
                                    cell.classList.add('bg-green');
                                } else if (value < 0) {
                                    cell.classList.add('bg-red', 'font-red');
                                }
                            }
                        },
                        '收入增速': (cell) => {
                            cell.classList.add('italic');
                            const value = parseValue(cell.textContent);
                            if (value !== null) {
                                if (value > 15) {
                                    cell.classList.add('bg-green', 'font-green');
                                } else if (value < 0) {
                                    cell.classList.add('bg-red', 'font-red');
                                } else {
                                    cell.classList.add('font-blue');
                                }
                            }
                        },
                        '净利润增速': (cell) => {
                            cell.classList.add('italic');
                            const value = parseValue(cell.textContent);
                            if (value !== null) {
                                if (value > 15) {
                                    cell.classList.add('bg-green', 'font-green');
                                } else if (value < 0) {
                                    cell.classList.add('bg-red', 'font-red');
                                } else {
                                    cell.classList.add('font-blue');
                                }
                            }
                        },
                        '经营净现金流(亿)': (cell) => {
                            const value = parseValue(cell.textContent);
                            if (value !== null && value < 0) cell.classList.add('bg-red', 'font-red');
                        },
                        '应收款周转天数': (cell) => {
                            const value = parseValue(cell.textContent);
                            if (value !== null && value > 90) {
                                    cell.classList.add('bg-red', 'font-red');
                            }
                        },
                        '现金占比': highlightIfOverThirtyPercent,
                        '库存占比': highlightIfOverThirtyPercent,
                        '应收款占比': highlightIfOverThirtyPercent,
                        '预付款占比': highlightIfOverThirtyPercent,
                        '固定资产占比': highlightIfOverThirtyPercent,
                        '长期投资占比': highlightIfOverThirtyPercent,
                        '商誉占比': highlightIfOverThirtyPercent,
                        '其他资产占比': highlightIfOverThirtyPercent
                    };

                    const metricsTables = document.querySelectorAll('table[data-table="metrics"]');
                    metricsTables.forEach(table => {
                        let netProfitValues = [];
                        let fcfRow = null;
                        const rows = table.querySelectorAll('tbody tr');
                        rows.forEach(row => {
                            if (row.classList.contains('section-row')) return;
                            const metricCell = row.querySelector('td:first-child');
                            if (!metricCell) return;
                            const metricName = metricCell.textContent.trim();
                            if (metricName === '净利润(亿)') {
                                row.querySelectorAll('td:not(:first-child)').forEach(cell => {
                                    netProfitValues.push(parseValue(cell.textContent));
                                });
                            } else if (metricName === '自由现金流(亿)') {
                                fcfRow = row;
                            }
                        });

                        rows.forEach(row => {
                            if (row.classList.contains('section-row')) return;
                            const metricCell = row.querySelector('td:first-child');
                            if (!metricCell) return;
                            const metricName = metricCell.textContent.trim();
                            const cells = row.querySelectorAll('td:not(:first-child)');
                            if (styleRules[metricName]) {
                                cells.forEach(cell => {
                                    styleRules[metricName](cell);
                                });
                            }
                            if (row === fcfRow && netProfitValues.length > 0) {
                                cells.forEach((cell, index) => {
                                    const fcfValue = parseValue(cell.textContent);
                                    const netProfitValue = netProfitValues[index];
                                    if (fcfValue !== null) {
                                        if (fcfValue < 0) {
                                            cell.classList.add('bg-red', 'font-red');
                                        } else if (netProfitValue !== null && fcfValue > netProfitValue) {
                                            cell.classList.add('bg-green', 'font-green');
                                        }
                                    }
                                });
                            }
                        });
                    });
                });
                </script>
            </body>
        </html>
        '''
        final_html = styled_html.replace('{symbol}', symbol).replace('{html_content}', html_content)
        return final_html
