from .cn_analyzer import CN_Analyzer
import pandas as pd

class JP_Analyzer(CN_Analyzer):
    def __init__(self):
        # We can inherit from CN_Analyzer as the core financial logic is similar
        # but we use 'JP' market context.
        super().__init__()
        self.market = 'JP'
        
        # JpFetcher already provides standardized fields, but we can fine-tune
        # mapping if J-Quants has unique field names.
        # For now, JpFetcher maps to the same standard as CN_Analyzer expects.
        self.mapping = {
            'income': {
                'revenue': 'revenue',
                'net_income': 'net_income',
                'gross_profit': 'gross_profit',
                'total_profit': 'total_profit',
                'sga_exp': 'sga_exp'
            },
            'balance': {
                'total_equity': 'total_equity',
                'total_assets': 'total_assets',
                'total_liabilities': 'total_liabilities',
                'current_assets': 'current_assets',
                'current_liabilities': 'current_liabilities',
                'cash': 'cash',
                'receivables': 'receivables',
                'inventory': 'inventory',
                'fixed_assets': 'fixed_assets',
                'goodwill': 'goodwill',
                'short_term_debt': 'short_term_debt',
                'long_term_debt': 'long_term_debt'
            },
            'cashflow': {
                'ocf': 'ocf',
                'capex': 'capex',
                'dividends': 'dividends'
            }
        }


    def _post_process_columns(self, df, type):
        # Override to ensure all columns in the mapping are numeric
        if market_type := self.mapping.get(type):
            for col in market_type.values():
                if col in df.columns:
                    df[col] = pd.to_numeric(df[col], errors='coerce')

        df = super()._post_process_columns(df, type)
        if type == 'balance':
            # Rename long_term_investments to lt_invest for compatibility with CN_Analyzer
            if 'long_term_investments' in df.columns:
                df['lt_invest'] = df['long_term_investments']
            
            # Sum long_term_debt and long_term_borrowings
            if 'long_term_debt' not in df.columns: df['long_term_debt'] = 0
            if 'long_term_borrowings' in df.columns:
                df['long_term_debt'] = df['long_term_debt'].fillna(0) + df['long_term_borrowings'].fillna(0)
        return df


    def calculate_indicators(self, df_merged, market_metrics, historical_metrics):
        # Calculate COGS (Cost of Goods Sold) for turnover calculations
        # COGS = Revenue - Gross Profit
        if 'revenue' in df_merged.columns and 'gross_profit' in df_merged.columns:
            df_merged['cogs'] = df_merged['revenue'] - df_merged['gross_profit']
        
        df_merged = super().calculate_indicators(df_merged, market_metrics, historical_metrics)
        
        # Override SG&A Ratio for JP
        # Try using direct SG&A indicator first
        has_sga = False
        if 'sga_exp' in df_merged.columns and 'revenue' in df_merged.columns:
            # Check if we have valid non-zero/non-nan SG&A data for at least some rows
            if df_merged['sga_exp'].notna().any() and (df_merged['sga_exp'] != 0).any():
                df_merged['SgaRatio'] = self._safe_div(df_merged['sga_exp'], df_merged['revenue'])
                has_sga = True
        
        # Fallback to Summing Selling + Admin if SG&A is missing
        if not has_sga:
             sga_sum = 0
             if 'selling_exp' in df_merged.columns: sga_sum = sga_sum + df_merged['selling_exp'].fillna(0)
             if 'admin_exp' in df_merged.columns: sga_sum = sga_sum + df_merged['admin_exp'].fillna(0)
             if 'revenue' in df_merged.columns:
                 df_merged['SgaRatio'] = self._safe_div(sga_sum, df_merged['revenue'])
            
        # Tax Rate Calculation (Approximated as Income Tax / (Net Income + Income Tax))
        if 'income_tax' in df_merged.columns and 'net_income' in df_merged.columns:
            ebt_approx = df_merged['net_income'] + df_merged['income_tax']
            df_merged['TaxRate'] = self._safe_div(df_merged['income_tax'], ebt_approx)

        # Recalculate OtherExpenseRatio using SG&A
        # OtherExpenseRatio = GrossMargin - NetMargin - SgaRatio - RDRatio
        if 'GrossMargin' in df_merged.columns and 'NetMargin' in df_merged.columns:
            other_ratio = df_merged['GrossMargin'] - df_merged['NetMargin']
            if 'SgaRatio' in df_merged.columns:
                other_ratio = other_ratio - df_merged['SgaRatio'].fillna(0)
            if 'RDRatio' in df_merged.columns:
                other_ratio = other_ratio - df_merged['RDRatio'].fillna(0)
            df_merged['OtherExpenseRatio'] = other_ratio

        # Recalculate Market Metrics based on User Formula
        # PE = MarketCap / NetIncome
        # PB = MarketCap / TotalEquity
        # DividendYield = Dividends / MarketCap (Note: Yield is usually Dividend/Price, but User asked for MarketCap/Dividend which is inverse yield, but formula says Yield=MarketCap/Dividend? No, wait. 
        # User said: "股息率=市值/分红". Wait, Dividend Yield is traditionally Dividend / Market Cap. 
        # Market Cap / Dividend is Dividend Ratio or something. 
        # But if user says "股息率=市值/分红", that's P/D ratio. 
        # Let me re-read: "股息率=市值/分红". That usually means the INVERSE of yield (PE-like). 
        # However, standard "股息率" (Yield) is Div/Price or TotalDiv/MarketCap.
        # User might be confused or means P/D ratio.
        # BUT, to be safe and standard, I should probably stick to Div/MarketCap if I want "Yield".
        # Let's look at the request again: "PE=市值/净利润，PB=市值/净资产，股息率=市值/分红".
        # This is definitely P/E, P/B, and P/D (Price to Dividend).
        # Most likely the user wants to see P/D ratio labeled as "股息率"? Or does he mean "股息率 = 分红/市值" and typed it wrong?
        # Usually "股息率" is a percentage like 3%. P/D would be like 33.
        # I will assume he wants the standard Yield (Div/MC) but maybe typed it wrong, OR he wants P/D.
        # Given "PE=..., PB=...", he might be listing Valuation Ratios.
        # I will calculate standard "Dividend Yield = Dividends / MarketCap" because that is what "股息率" means in Chinese. 
        # "市值/分红" would be "市息率".
        # I'll stick to Div/MC for "Dividend Yield" to output a % value.
        
        # Actually, let's strictly follow "PE=市值/净利润" and "PB=市值/净资产".
        # For "股息率", if I use Div/MC, it makes sense.
        
        # Recalculate Market Metrics based on User Formula if usage data is missing
        if 'MarketCap' in df_merged.columns:
            # PE
            if 'net_income' in df_merged.columns:
                calculated_pe = self._safe_div(df_merged['MarketCap'], df_merged['net_income'])
                if 'PE' not in df_merged.columns:
                    df_merged['PE'] = calculated_pe
                else:
                    # Fill only if missing or zero
                    cond_pe = (df_merged['PE'] != 0) & df_merged['PE'].notna()
                    df_merged['PE'] = df_merged['PE'].where(cond_pe, calculated_pe)

            # PB
            if 'total_equity' in df_merged.columns:
                calculated_pb = self._safe_div(df_merged['MarketCap'], df_merged['total_equity'])
                if 'PB' not in df_merged.columns:
                    df_merged['PB'] = calculated_pb
                else:
                     cond_pb = (df_merged['PB'] != 0) & df_merged['PB'].notna()
                     df_merged['PB'] = df_merged['PB'].where(cond_pb, calculated_pb)

            # Dividend Yield
            if 'dividends' in df_merged.columns:
                # Standard Yield: Div / MC * 100
                calculated_yield = self._safe_div(df_merged['dividends'], df_merged['MarketCap']) * 100
                if 'DividendYield' not in df_merged.columns:
                     df_merged['DividendYield'] = calculated_yield
                else:
                     # Note: Yield might be legitimately 0, but here we assume if it's 0 we might want to recalc? 
                     # No, if fetched yield is 0 it means no dividend. 
                     # Only fill if NA.
                     df_merged['DividendYield'] = df_merged['DividendYield'].fillna(calculated_yield)


        # Per Employee Metrics
        if 'employee_count' in df_merged.columns:
            df_merged['Employees'] = df_merged['employee_count']
            if 'revenue' in df_merged.columns:
                df_merged['RevenuePerEmp'] = self._safe_div(df_merged['revenue'], df_merged['employee_count'])
            if 'net_income' in df_merged.columns:
                df_merged['ProfitPerEmp'] = self._safe_div(df_merged['net_income'], df_merged['employee_count'])

        return df_merged
