import enum
from typing import Iterator

from django.conf import settings
from wbcore.contrib.dataloader.dataloaders import Dataloader

from wbfdm.dataloaders.protocols import ESGProtocol
from wbfdm.dataloaders.types import ESGDataDict
from wbfdm.enums import ESG

from ..client import MSCIClient


class MSCIESG(enum.Enum):
    CARBON_EMISSIONS_SCOPE_1 = "CARBON_EMISSIONS_SCOPE_1"
    CARBON_EMISSIONS_SCOPE_1_KEY = "CARBON_EMISSIONS_SCOPE_1_KEY"
    CARBON_EMISSIONS_SCOPE_2 = "CARBON_EMISSIONS_SCOPE_2"
    CARBON_EMISSIONS_SCOPE_2_KEY = "CARBON_EMISSIONS_SCOPE_2_KEY"
    CARBON_EMISSIONS_SCOPE_3_TOTAL = "CARBON_EMISSIONS_SCOPE_3_TOTAL"
    CARBON_EMISSIONS_SCOPE_3_YEAR = "CARBON_EMISSIONS_SCOPE_3_ESTIMATES_YEAR"
    CARBON_EMISSIONS_SCOPE123 = "CARBON_EMISSIONS_SCOPE123"
    CARBON_EMISSIONS_SCOPE123_KEY = "CARBON_EMISSIONS_SCOPE123_KEY"
    CARBON_EMISSIONS_SALES_EUR_SCOPE_ALL = "CARBON_EMISSIONS_SALES_EUR_SCOPE123_INTEN"
    CARBON_EMISSIONS_SCOPE123_EVIC_EUR = "CARBON_EMISSIONS_EVIC_EUR_SCOPE123_INTEN"
    CARBON_EMISSIONS_SOURCE = "CARBON_EMISSIONS_SOURCE"
    CARBON_EMISSIONS_YEAR = "CARBON_EMISSIONS_YEAR"
    ACTIVE_FF_SECTOR_EXPOSURE = "ACTIVE_FF_SECTOR_EXPOSURE"
    ACTIVE_FF_SECTOR_EXPOSURE_SOURCE = "ACTIVE_FF_SECTOR_EXPOSURE_SOURCE"
    ACTIVE_FF_SECTOR_EXPOSURE_YEAR = "ACTIVE_FF_SECTOR_EXPOSURE_YEAR"
    PCT_NON_RENEW_CONSUMPTION_PRODUCTION = "PCT_NONRENEW_CONSUMP_PROD"
    PCT_TOTAL_NON_RENEW_CONSUMPTION = "PCT_TOTL_ERGY_CONSUMP_NONRENEW"
    PCT_TOTAL_NON_RENEW_PRODUCTION = "PCT_TOTL_ERGY_PRODUCT_NONRENEW"
    TOTAL_RENEW_ENERGY_CONSUMPTION = "TOTL_ERGY_CONSUMP_RENEW_GWH"
    TOTAL_RENEW_ENERGY_CONSUMPTION_SOURCE = "TOTL_ERGY_CONSUMP_RENEW_GWH_SOURCE"
    TOTAL_RENEW_ENERGY_CONSUMPTION_YEAR = "TOTL_ERGY_CONSUMP_RENEW_GWH_YEAR"
    TOTAL_NON_RENEW_ENERGY_CONSUMPTION = "TOTL_ERGY_CONSUMP_NONRENEW_GWH"
    TOTAL_NON_RENEW_ENERGY_CONSUMPTION_SOURCE = "TOTL_ERGY_CONSUMP_NONRENEW_GWH_SOURCE"
    TOTAL_NON_RENEW_ENERGY_CONSUMPTION_YEAR = "TOTL_ERGY_CONSUMP_NONRENEW_GWH_YEAR"
    TOTAL_NON_RENEW_ENERGY_CONSUMPTION_PRODUCTION = "TOTL_ERGY_CONSUMP_PRODUCT_NONRENEW_GWH"
    TOTAL_NON_RENEW_ENERGY_CONSUMPTION_PRODUCTION_SOURCE = "TOTL_ERGY_CONSUMP_PRODUCT_NONRENEW_GWH_SOURCE"
    TOTAL_NON_RENEW_ENERGY_CONSUMPTION_PRODUCTION_YEAR = "TOTL_ERGY_CONSUMP_PRODUCT_NONRENEW_GWH_YEAR"
    ENERGY_CONSUMPTION_INTENSITY_EUR = "ENERGY_CONSUMP_INTEN_EUR"
    ENERGY_CONSUMPTION_INTENSITY_EUR_SOURCE = "ENERGY_CONSUMP_INTEN_EUR_SOURCE"
    ENERGY_CONSUMPTION_INTENSITY_EUR_YEAR = "ENERGY_CONSUMP_INTEN_EUR_YEAR"
    TOTAL_ENERGY_CONSUMPTION = "TOTL_ERGY_CONSUMP_GWH"
    TOTAL_ENERGY_CONSUMPTION_SOURCE = "TOTL_ERGY_CONSUMP_GWH_SOURCE"
    TOTAL_ENERGY_CONSUMPTION_YEAR = "TOTL_ENRGY_CONSUMP_YEAR"
    OPS_BIODIV_CONTROVERSITIES = "OPS_PROT_BIODIV_CONTROVS"
    OPS_BIODIV_AREAS = "OPS_PROT_BIODIV_AREAS"
    WATER_EMISSIONS = "WATER_EM_EFF_METRIC_TONS"
    WATER_EMISSIONS_YEAR = "WATER_EM_EFF_METRIC_TONS_YEAR"
    WATER_EMISSIONS_SOURCE = "WATER_EM_EFF_METRIC_TONS_SOURCE"
    HAZARD_WASTE = "HAZARD_WASTE_METRIC_TON"
    HAZARD_WASTE_YEAR = "HAZARD_WASTE_METRIC_TON_YEAR"
    HAZARD_WASTE_SOURCE = "HAZARD_WASTE_METRIC_TON_SOURCE"
    OECD_ALIGNMENT = "OECD_ALIGNMENT"
    LABOR_DDP = "LABOR_DDIL_POL_ILO"
    COMPLIANCE_GLOBAL_IMPACT = "MECH_UN_GLOBAL_COMPACT"
    GENDER_PAY_GAP_RATIO = "GENDER_PAY_GAP_RATIO"
    GENDER_PAY_GAP_RATIO_YEAR = "GENDER_PAY_GAP_YEAR"
    GENDER_PAY_GAP_RATIO_SOURCE = "GENDER_PAY_GAP_RATIO_SOURCE"
    PCT_FEMALE_DIRECTORS = "FEMALE_DIRECTORS_PCT"
    CONTROVERSIAL_WEAPONS = "CONTRO_WEAP_CBLMBW_ANYTIE"
    CONTROVERSIAL_WEAPONS_SOURCE = "CONTRO_WEAP_CBLMBW_ANYTIE_SOURCE"
    CVI_FACTOR = "CVI_FACTOR"
    EVIC_EUR = "EVIC_EUR"
    NACE_SECTION_CODE = "NACE_SECTION_CODE"


class MSCIESGDataloader(ESGProtocol, Dataloader):
    CACHE_IDENTIFIER_KEY: str = "instrument_id"
    CACHE_SYMBOL_KEY: str = "factor_code"
    CACHE_VALUE_KEY: str = "value"

    def esg(self, values: list[ESG]) -> Iterator[ESGDataDict]:
        msci_client_id = getattr(settings, "MSCI_CLIENT_ID", None)
        msci_client_secret = getattr(settings, "MSCI_CLIENT_SECRET", None)
        if msci_client_id and msci_client_secret:
            client = MSCIClient(msci_client_id, msci_client_secret)
            lookup = {k: v for k, v in self.entities.values_list("dl_parameters__esg__parameters", "id")}
            for row in client.esg(list(lookup.keys()), [MSCIESG[value.name].value for value in values]):
                if instrument_id := lookup.get(row["ISSUER_ISIN"], None):
                    for value in values:
                        yield ESGDataDict(
                            instrument_id=instrument_id,
                            factor_code=value.value,
                            value=row.get(MSCIESG[value.name].value, None),
                        )
