from .base_analyzer import BaseAnalyzer
import pandas as pd
import numpy as np

class CN_Analyzer(BaseAnalyzer):
    def __init__(self):
        super().__init__('CN')
        self.mapping = {
            'income': {
                'total_revenue': 'revenue', 'oper_cost': 'cogs', 'total_cogs': 'total_costs',
                'sell_exp': 'selling_exp', 'admin_exp': 'admin_exp', 'fin_exp': 'fin_exp', 'rd_exp': 'rd_exp',
                'total_profit': 'total_profit', 'income_tax': 'income_tax', 'n_income_attr_p': 'net_income', 'net_profit_attr_p': 'net_income',
            },
            'balance': {
                'money_cap': 'cash', 'accounts_receiv': 'receivables', 'inventories': 'inventory',
                'fix_assets': 'fixed_assets', 'total_assets': 'total_assets', 'goodwill': 'goodwill',
                'prepayment': 'prepayment', 'lt_eqt_invest': 'lt_invest', 'oth_assets': 'other_assets', 'trad_asset': 'trading_assets',
                'st_borr': 'short_term_debt', 'non_cur_liab_due_1y': 'short_term_debt_part',
                'lt_borr': 'long_term_debt', 'bonds_payable': 'long_term_debt_bonds',
                'total_liab': 'total_liabilities', 'total_hldr_eqy_exc_min_int': 'total_equity', 'total_share_holder_equity': 'total_equity',
                'adv_receipts': 'adv_receipts', 'contract_liab': 'contract_liab',
                'acct_payable': 'accounts_payable',
            },
            'cashflow': {
                'net_cash_flow': 'ocf', 'n_cashflow_act': 'ocf', 'c_pay_acq_const_fiolta': 'capex', 'c_paid_div_prof_int': 'dividends',
                'c_paid_to_for_empl': 'cash_paid_for_employees'
            }
        }

    def _post_process_columns(self, df, type):
        if type == 'balance':
            if 'short_term_debt' not in df.columns: df['short_term_debt'] = 0
            if 'short_term_debt_part' in df.columns:
                df['short_term_debt'] = df['short_term_debt'].fillna(0) + df['short_term_debt_part'].fillna(0)
            
            if 'long_term_debt' not in df.columns: df['long_term_debt'] = 0
            if 'long_term_debt_bonds' in df.columns:
                df['long_term_debt'] = df['long_term_debt'].fillna(0) + df['long_term_debt_bonds'].fillna(0)
        
        if type == 'income':
            if 'gross_profit' not in df.columns and 'revenue' in df.columns and 'cogs' in df.columns:
                df['gross_profit'] = df['revenue'] - df['cogs']

            if 'ebit' not in df.columns and 'total_profit' in df.columns and 'fin_exp' in df.columns:
                df['ebit'] = df['total_profit'] + df['fin_exp']
        return df

    def calculate_indicators(self, df_merged, market_metrics, historical_metrics):
        
        def calc_yoy_growth(df, col):
            growths = []
            for idx, row in df.iterrows():
                try:
                    curr_date = str(row['date_str'])
                    target_date = str(int(curr_date) - 10000)
                    
                    match = df[df['date_str'] == target_date]
                    if not match.empty and col in row and pd.notna(row[col]):
                        prev_val = match.iloc[0].get(col)
                        curr_val = row[col]
                        if prev_val and prev_val != 0:
                            growths.append((curr_val - prev_val) / abs(prev_val))
                        else:
                            growths.append(np.nan)
                    else:
                        growths.append(np.nan)
                except:
                    growths.append(np.nan)
            return growths

        if 'revenue' in df_merged.columns:
            df_merged['RevenueGrowth'] = calc_yoy_growth(df_merged, 'revenue')
        if 'net_income' in df_merged.columns:
            df_merged['NetIncomeGrowth'] = calc_yoy_growth(df_merged, 'net_income')
        
        # Margins & Returns
        if 'gross_profit' in df_merged.columns:
            df_merged['GrossMargin'] = self._safe_div(df_merged['gross_profit'], df_merged['revenue'])
        if 'net_income' in df_merged.columns:
            df_merged['NetMargin'] = self._safe_div(df_merged['net_income'], df_merged['revenue'])
            if 'total_equity' in df_merged.columns:
                df_merged['ROE'] = self._safe_div(df_merged['net_income'], df_merged['total_equity'])
            if 'total_assets' in df_merged.columns:
                df_merged['ROA'] = self._safe_div(df_merged['net_income'], df_merged['total_assets'])

        # ROIC
        if 'short_term_debt' in df_merged.columns and 'long_term_debt' in df_merged.columns:
            df_merged['InterestBearingDebt'] = df_merged['short_term_debt'].fillna(0) + df_merged['long_term_debt'].fillna(0)
            if 'total_equity' in df_merged.columns:
                df_merged['InvestedCapital'] = df_merged['total_equity'] + df_merged['InterestBearingDebt']
                if 'ebit' in df_merged.columns:
                    df_merged['ROIC'] = self._safe_div(df_merged['ebit'], df_merged['InvestedCapital'])
        
        # Cash Flow
        if 'capex' in df_merged.columns:
            df_merged['Capex'] = df_merged['capex'].abs()
            if 'ocf' in df_merged.columns:
                df_merged['FCF'] = df_merged['ocf'] - df_merged['Capex']

        # Expenses
        if 'selling_exp' in df_merged.columns:
            df_merged['SellingRatio'] = self._safe_div(df_merged['selling_exp'], df_merged['revenue'])
        if 'admin_exp' in df_merged.columns:
            df_merged['AdminRatio'] = self._safe_div(df_merged['admin_exp'], df_merged['revenue'])
        if 'rd_exp' in df_merged.columns:
            df_merged['RDRatio'] = self._safe_div(df_merged['rd_exp'], df_merged['revenue'])
        df_merged['SgaRatio'] = (df_merged.get('SellingRatio', 0)) + (df_merged.get('AdminRatio', 0))
        if 'income_tax' in df_merged.columns and 'total_profit' in df_merged.columns:
            df_merged['TaxRate'] = self._safe_div(df_merged['income_tax'], df_merged['total_profit'])

        # Other Expense Ratio (GrossMargin - Selling - Admin - RD - NetMargin)
        if 'GrossMargin' in df_merged.columns and 'NetMargin' in df_merged.columns:
            other_ratio = df_merged['GrossMargin'] - df_merged['NetMargin']
            if 'SellingRatio' in df_merged.columns: other_ratio = other_ratio - df_merged['SellingRatio'].fillna(0)
            if 'AdminRatio' in df_merged.columns: other_ratio = other_ratio - df_merged['AdminRatio'].fillna(0)
            if 'RDRatio' in df_merged.columns: other_ratio = other_ratio - df_merged['RDRatio'].fillna(0)
            df_merged['OtherExpenseRatio'] = other_ratio

        # Depreciation Expense Ratio
        if 'depreciation' in df_merged.columns and 'revenue' in df_merged.columns:
            df_merged['DepreciationRatio'] = self._safe_div(df_merged['depreciation'].abs(), df_merged['revenue'])
        
        if 'total_assets' in df_merged.columns:
            assets = df_merged['total_assets']

            def series_or_zero(column_name: str) -> pd.Series:
                if column_name in df_merged.columns:
                    return pd.to_numeric(df_merged[column_name], errors='coerce').fillna(0)
                return pd.Series(0, index=df_merged.index, dtype='float64')

            # Asset Ratios
            if 'cash' in df_merged.columns: df_merged['CashRatio'] = self._safe_div(df_merged['cash'], assets)
            if 'inventory' in df_merged.columns: df_merged['InventoryRatio'] = self._safe_div(df_merged['inventory'], assets)
            if 'receivables' in df_merged.columns: df_merged['ReceivablesRatio'] = self._safe_div(df_merged['receivables'], assets)
            if 'accounts_payable' in df_merged.columns: df_merged['PayablesRatio'] = self._safe_div(df_merged['accounts_payable'], assets)
            if 'prepayment' in df_merged.columns: df_merged['PrepaymentRatio'] = self._safe_div(df_merged['prepayment'], assets)
            if 'fixed_assets' in df_merged.columns: df_merged['FixedAssetsRatio'] = self._safe_div(df_merged['fixed_assets'], assets)
            if 'lt_invest' in df_merged.columns: df_merged['LongTermInvestmentRatio'] = self._safe_div(df_merged['lt_invest'], assets)
            if 'goodwill' in df_merged.columns: df_merged['GoodwillRatio'] = self._safe_div(df_merged['goodwill'], assets)

            known_assets_ratio = (series_or_zero('CashRatio') + series_or_zero('InventoryRatio') + series_or_zero('ReceivablesRatio') +
                                series_or_zero('PrepaymentRatio') + series_or_zero('FixedAssetsRatio') + series_or_zero('LongTermInvestmentRatio') +
                                series_or_zero('GoodwillRatio'))
            df_merged['OtherAssetsRatio'] = 1 - known_assets_ratio

            adv = series_or_zero('adv_receipts') + series_or_zero('contract_liab')
            df_merged['AdvanceReceiptsRatio'] = self._safe_div(adv, assets)

            st_debt = series_or_zero('short_term_debt')
            lt_debt = series_or_zero('long_term_debt')

            df_merged['ShortTermDebtRatio'] = self._safe_div(st_debt, assets)
            df_merged['LongTermDebtRatio'] = self._safe_div(lt_debt, assets)
            df_merged['InterestBearingDebtRatio'] = self._safe_div(st_debt + lt_debt, assets)

            inv_ratio = series_or_zero('InventoryRatio')
            rec_ratio = series_or_zero('ReceivablesRatio')
            prep_ratio = series_or_zero('PrepaymentRatio')
            pay_ratio = series_or_zero('PayablesRatio')
            adv_ratio = series_or_zero('AdvanceReceiptsRatio')
            df_merged['OperatingAssetsRatio'] = inv_ratio + rec_ratio + prep_ratio - pay_ratio - adv_ratio

        # Turnover Days
        if 'cogs' in df_merged.columns:
            if 'inventory' in df_merged.columns: 
                df_merged['InventoryDays'] = self._safe_div(df_merged['inventory'] * 365, df_merged['cogs'])
            if 'accounts_payable' in df_merged.columns:
                df_merged['PayablesDays'] = self._safe_div(df_merged['accounts_payable'] * 365, df_merged['cogs'])
        if 'revenue' in df_merged.columns:
            if 'receivables' in df_merged.columns:
                df_merged['ReceivablesDays'] = self._safe_div(df_merged['receivables'] * 365, df_merged['revenue'])
            if 'fixed_assets' in df_merged.columns:
                df_merged['FixedAssetsTurnover'] = self._safe_div(df_merged['revenue'], df_merged['fixed_assets'])
            if 'total_assets' in df_merged.columns:
                df_merged['TotalAssetTurnover'] = self._safe_div(df_merged['revenue'], df_merged['total_assets'])

        # Market Metrics
        if historical_metrics is not None and not historical_metrics.empty:
            if historical_metrics.index.name != 'date_str':
                historical_metrics.set_index('date_str', inplace=True)
            
            for index, row in df_merged.iterrows():
                date_str = str(row['date_str'])
                if date_str in historical_metrics.index:
                    hist_row = historical_metrics.loc[date_str]
                    for m_col in ['Price', 'MarketCap', 'PE', 'PB', 'Shareholders']:
                        if m_col in hist_row:
                            df_merged.loc[index, m_col] = hist_row.get(m_col)

            # Fill latest values from market_metrics for the most recent entry if provided
            if not df_merged.empty:
                latest_date_idx = df_merged.index[0]
                for m_key, m_col in [('price', 'Price'), ('market_cap', 'MarketCap'), 
                                     ('pe', 'PE'), ('pb', 'PB'), ('total_share_holders', 'Shareholders')]:
                    if market_metrics.get(m_key):
                        df_merged.loc[latest_date_idx, m_col] = market_metrics.get(m_key)
        elif not df_merged.empty:
            for m_key, m_col in [('price', 'Price'), ('market_cap', 'MarketCap'), 
                                 ('pe', 'PE'), ('pb', 'PB'), ('total_share_holders', 'Shareholders')]:
                if market_metrics.get(m_key):
                    df_merged.loc[df_merged.index[0], m_col] = market_metrics.get(m_key)
        
        # Employees & Per-Employee Metrics
        if not df_merged.empty:
             annual_mask = df_merged['date_str'].str.endswith('1231')
             annual_idxs = df_merged.index[annual_mask]
             if len(annual_idxs) > 0:
                 target_idx = annual_idxs[0]
                 emps = market_metrics.get('employee_count', 0)
                 if emps > 0:
                     df_merged.loc[target_idx, 'Employees'] = emps
                     if 'revenue' in df_merged.columns:
                         df_merged.loc[target_idx, 'RevenuePerEmp'] = df_merged.loc[target_idx, 'revenue'] / emps
                     if 'net_income' in df_merged.columns:
                         df_merged.loc[target_idx, 'ProfitPerEmp'] = df_merged.loc[target_idx, 'net_income'] / emps
                     if 'cash_paid_for_employees' in df_merged.columns:
                         df_merged.loc[target_idx, 'AvgWage'] = df_merged.loc[target_idx, 'cash_paid_for_employees'] / emps
        
        return df_merged
