import pandas as pd
import numpy as np

class BaseAnalyzer:
    def __init__(self, market):
        self.market = market
        self.mapping = {}

    def process_data(self, df_inc: pd.DataFrame, df_bal: pd.DataFrame, df_cf: pd.DataFrame, market_metrics: dict, historical_metrics: pd.DataFrame = None, df_div: pd.DataFrame = None, df_rep: pd.DataFrame = None, df_emp: pd.DataFrame = None) -> pd.DataFrame:
        df_inc = self._map_columns(df_inc, 'income')
        df_bal = self._map_columns(df_bal, 'balance')
        df_cf = self._map_columns(df_cf, 'cashflow')

        for df in [df_inc, df_bal, df_cf]:
            if not df.empty and 'date' in df.columns:
                df['date_str'] = df['date'].astype(str).str.replace('-', '')

        if df_inc.empty:
            return pd.DataFrame()

        df_merged = df_inc
        if not df_bal.empty and 'date_str' in df_bal.columns:
            df_merged = pd.merge(df_merged, df_bal, on='date_str', how='outer', suffixes=('', '_bal'))
        if not df_cf.empty and 'date_str' in df_cf.columns:
            df_merged = pd.merge(df_merged, df_cf, on='date_str', how='outer', suffixes=('', '_cf'))
        
        if df_div is not None and not df_div.empty and 'date_str' in df_div.columns:
            df_merged = pd.merge(df_merged, df_div, on='date_str', how='left', suffixes=('', '_div'))

        if df_rep is not None and not df_rep.empty and 'date_str' in df_rep.columns:
            df_merged = pd.merge(df_merged, df_rep, on='date_str', how='left', suffixes=('', '_rep'))

        if df_emp is not None and not df_emp.empty and 'date_str' in df_emp.columns:
            df_merged = pd.merge(df_merged, df_emp, on='date_str', how='left', suffixes=('', '_emp'))

        if df_merged.empty:
            return pd.DataFrame()

        df_merged = df_merged.sort_values('date_str', ascending=False)
        
        df_merged = self.calculate_indicators(df_merged, market_metrics, historical_metrics)

        return df_merged

    def calculate_indicators(self, df_merged, market_metrics, historical_metrics):
        # This method will be implemented by subclasses
        return df_merged

    def _map_columns(self, df: pd.DataFrame, type: str) -> pd.DataFrame:
        df = df.copy()
        if df.empty: return df
        cols = df.columns
        
        market_mapping = self.mapping.get(type, {})
        actual_map = {k: v for k, v in market_mapping.items() if k in cols}
        df = df.rename(columns=actual_map)
        
        df = df.loc[:, ~df.columns.duplicated()]
        
        df = self._post_process_columns(df, type)

        return df

    def _post_process_columns(self, df, type):
        # To be implemented in subclasses for specific post-processing
        return df

    def _safe_div(self, a, b):
        return a / b.replace(0, np.nan)
