from prefect import get_run_logger
from nemo_library_etl.adapter._utils.enums import ETLAdapter, ETLStep
from nemo_library_etl.adapter._utils.file_handler import ETLFileHandler
from nemo_library_etl.adapter._utils.sentiment_analyzer import SentimentAnalyzer
from nemo_library_etl.adapter.gedys.config_models import PipelineGedys
from nemo_library_etl.adapter.gedys.enums import GedysTransformStep
from nemo_library_etl.adapter._utils.recursive_json_flattener import RecursiveJsonFlattener
from nemo_library.core import NemoLibrary


class GedysTransform:

    def __init__(self, cfg: PipelineGedys):

        nl = NemoLibrary()
        self.config = nl.config
        self.logger = get_run_logger()
        self.cfg = cfg

        super().__init__()

    def transform(self) -> None:
        self.logger.info("Transforming all Gedys objects")

        if self.cfg.transform.sentiment_analysis:
            self._sentiment_analysis()
        if self.cfg.transform.flatten:
            self._flatten()
        if self.cfg.transform.join:
            self._join()

    def _sentiment_analysis(self) -> None:
        self.logger.info("Performing sentiment analysis for Gedys objects")

        fh = ETLFileHandler()
        sentiment_analyzer = SentimentAnalyzer()

        for table, model in self.cfg.extract.tables.items():
            if model.active is False:
                self.logger.info(f"Skipping inactive table: {table}")
                continue

            data = fh.readJSON(
                adapter=ETLAdapter.GEDYS,
                step=ETLStep.EXTRACT,
                entity=table,
                ignore_nonexistent=True,  # Ignore if file does not exist
            )
            if not data:
                self.logger.warning(
                    f"No data found for entity {table}. Skipping sentiment analysis."
                )
                continue

            if model.sentiment_analysis_fields:
                self.logger.info(f"Performing sentiment analysis for entity {table}")
                data = sentiment_analyzer.analyze_sentiment(
                    data=data,
                    sentiment_analysis_fields=model.sentiment_analysis_fields,
                )

            fh.writeJSON(
                adapter=ETLAdapter.GEDYS,
                step=ETLStep.TRANSFORM,
                substep=GedysTransformStep.SENTIMENT,
                data=data,
                entity=table,
            )

    def _flatten(self) -> None:
        self.logger.info("Flattening Gedys objects")

        fh = ETLFileHandler()
        flattener = RecursiveJsonFlattener()

        for table, model in self.cfg.extract.tables.items():
            if model.active is False:
                self.logger.info(f"Skipping inactive table: {table}")
                continue

            data = fh.readJSON(
                adapter=ETLAdapter.GEDYS,
                step=ETLStep.TRANSFORM,
                substep=GedysTransformStep.SENTIMENT,
                entity=table,
                ignore_nonexistent=True,  # Ignore if file does not exist
            )
            if not data:
                self.logger.warning(
                    f"No data found for entity {table}. Skipping flattener"
                )
                continue

            self.logger.info(f"Flattening data for entity {table}")
            flattened_data = flattener.flatten(data)

            fh.writeJSON(
                adapter=ETLAdapter.GEDYS,
                step=ETLStep.TRANSFORM,
                substep=GedysTransformStep.FLATTEN,
                data=flattened_data,
                entity=table,
            )

    def _join(self) -> None:
        self.logger.info("Joining Gedys objects")

        fh = ETLFileHandler()
        flattener = RecursiveJsonFlattener()

        # Load base data from GEDYS
        companies = fh.readJSON(
            adapter=ETLAdapter.GEDYS,
            step=ETLStep.TRANSFORM,
            substep=GedysTransformStep.FLATTEN,
            entity="Company",
        )
        if not companies:
            raise ValueError("No company data found for joining with opportunities.")

        contacts = fh.readJSON(
            adapter=ETLAdapter.GEDYS,
            step=ETLStep.TRANSFORM,
            substep=GedysTransformStep.FLATTEN,
            entity="Contact",
        )
        if not contacts:
            raise ValueError("No contact data found for joining with opportunities.")

        opportunities = fh.readJSON(
            adapter=ETLAdapter.GEDYS,
            step=ETLStep.TRANSFORM,
            substep=GedysTransformStep.FLATTEN,
            entity="Opportunity",
        )

        # data model
        # Comp -> Contact -> Opportunity
        # or Comp -> Opportunity

        # start with joining contacts to companies
        for company in companies:
            company["contact_join"] = [
                contact
                for contact in contacts
                if contact.get("RelatedMainParents.Oid", "") == company["Oid"]
                or contact.get("RelatedParents.Oid", "") == company["Oid"]
            ]

        # flatten this structure
        companies_with_contacts = flattener.flatten(companies)

        # now join opportunities with this flattened structure
        for company in companies_with_contacts:
            company["opportunity_join"] = [
                opportunity
                for opportunity in opportunities
                if opportunity.get("RelatedMainParents.Oid", "") == company["Oid"]
                or opportunity.get("RelatedParents.Oid", "") == company["Oid"]
                or opportunity.get("RelatedMainParents.Oid", "")
                == company.get("contact_join.Oid","---") # --- to ensure no match
                or opportunity.get("RelatedParents.Oid", "")
                == company.get("contact_join.Oid","---")
            ]

        # finally flatten the whole structure again
        companies_with_contacts_and_opportunities = flattener.flatten(
            companies_with_contacts
        )

        # save the transformed data finally
        fh.writeJSON(
            adapter=ETLAdapter.GEDYS,
            step=ETLStep.TRANSFORM,
            substep=GedysTransformStep.JOIN,
            data=companies_with_contacts_and_opportunities,
            entity="Company Joined",
        )
