" Slide layout for the pptx file "
import logging

from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from pptx.util import Inches

from services.ppt_generator.configs.standard_configs import (DefaultSettings,
                                                             SlideWorkArea)
from services.ppt_generator.slide_creator import SlideCreator
from services.stock_info.public_comparable import PublicComparables
from services.stock_info.public_comparable_format_table import \
    format_for_table as pc_format_for_table
from utils.url_parser import parsed_url


class SideBySide:
    "Defining layout A and B"

    def __init__(
        self,
        ppt_slide_object,
        work_area: SlideWorkArea,
        slide_content: dict,
        project,
        slide,
        conduct_research_flag=True,
        client_config=None,
        research: str = None,
    ) -> None:

        self.ppt_slide_object = ppt_slide_object
        self.work_area = work_area
        self.left_side_content = slide_content["left_hand_side"]
        self.right_side_content = slide_content["right_hand_side"]
        self.client_config = client_config

        self.spacing = Inches(0.25)
        self.make_slide = SlideCreator(
            project,
            slide,
            conduct_research_flag=conduct_research_flag,
            client=self.client_config,
            prs_slide_obj=self.ppt_slide_object,
            research=research,
        )

    def left_side(self):
        "Add left side content"
        # create a text box with
        slide_function = self.make_slide.item_to_function_mapping[
            self.left_side_content
        ]
        slide_function(
            self.ppt_slide_object,
            self.work_area.top,
            self.work_area.left,
            (self.work_area.width - self.spacing) / 2,
            self.work_area.height,
        )

    def right_side(self):
        "Add right side content"
        # create a text box with
        slide_function = self.make_slide.item_to_function_mapping[
            self.right_side_content
        ]
        slide_function(
            self.ppt_slide_object,
            self.work_area.top,
            self.work_area.left + (self.work_area.width + self.spacing) / 2,
            (self.work_area.width - self.spacing) / 2,
            self.work_area.height,
        )


class TopBottom:
    "Defining layout C"

    def __init__(
        self,
        ppt_slide_object,
        work_area: SlideWorkArea,
        slide_content: dict,
        project,
        slide,
        conduct_research_flag=True,
        client_config=None,
        research: str = None,
    ) -> None:

        self.ppt_slide_object = ppt_slide_object
        self.work_area = work_area
        self.top_half_content = slide_content["top_half"]
        self.bottom_half_content = slide_content["bottom_half"]
        self.client_config = client_config

        self.spacing = Inches(0.25)
        self.make_slide = SlideCreator(
            project,
            slide,
            conduct_research_flag=conduct_research_flag,
            client=self.client_config,
            prs_slide_obj=self.ppt_slide_object,
            research=research,
        )

    def top_half(self):
        "Add left side content"
        # create a text box with
        slide_function = self.make_slide.item_to_function_mapping[self.top_half_content]
        slide_function(
            self.ppt_slide_object,
            self.work_area.top,
            self.work_area.left,
            self.work_area.width,
            (self.work_area.height - self.spacing) / 2,
        )

    def bottom_half(self):
        "Add right side content"
        # create a text box with
        slide_function = self.make_slide.item_to_function_mapping[
            self.bottom_half_content
        ]
        slide_function(
            self.ppt_slide_object,
            self.work_area.top + (self.work_area.height + self.spacing) / 2,
            self.work_area.left,
            self.work_area.width,
            (self.work_area.height - self.spacing) / 2,
        )


class FullPage:
    "Defining layout D"

    def __init__(
        self,
        ppt_slide_object,
        work_area: SlideWorkArea,
        slide_content: dict,
        project,
        slide,
        conduct_research_flag=True,
        client_config=None,
        research: str = None,
    ) -> None:

        self.ppt_slide_object = ppt_slide_object
        self.work_area = work_area
        self.content = slide_content
        self.client_config = client_config

        self.make_slide = SlideCreator(
            project,
            slide,
            conduct_research_flag=conduct_research_flag,
            client=self.client_config,
            prs_slide_obj=self.ppt_slide_object,
            research=research,
        )

    def add_content(self):
        "Add content to the slide"
        # create a text box with
        try:
            slide_function = self.make_slide.item_to_function_mapping[
                self.content["full_page"]
            ]
            slide_function(
                self.ppt_slide_object,
                self.work_area.top,
                self.work_area.left,
                self.work_area.width,
                self.work_area.height,
            )
        except KeyError:
            print("Layout not found")
            logging.error("Layout not found")
            # raise ValueError("Layout not found")


class CompsTable:
    "Defining layout D"

    def __init__(
        self,
        ppt_slide_object,
        work_area: SlideWorkArea,
        public_comps: PublicComparables,
    ) -> None:

        self.ppt_slide_object = ppt_slide_object
        self.work_area = work_area
        self.table_content = self.format_to_table(public_comps)
        self.make_table(self.table_content)

    def format_to_table(self, data: PublicComparables, headers: list[str] = None):
        "Take the public comps data and format it to a table that can used in the ppt"
        table_data = pc_format_for_table(data.data)
        return table_data

    def make_table(self, table_data):
        "Make a table from the data"
        # Add a table shape to the slide
        if isinstance(table_data, dict):
            table_data = table_data["data"]

        col_width = int(self.work_area.width / len(table_data[0]))
        rows = len(table_data) + 1  # Add 1 for header row
        cols = len(table_data[0])
        table = self.ppt_slide_object.shapes.add_table(
            rows,
            cols,
            left=self.work_area.left,
            top=self.work_area.top,
            width=self.work_area.width,
            height=self.work_area.height,
        ).table

        # Merge the first row for the header
        for col_index, header_text in enumerate(table_data[0]):
            if header_text != "":
                table.columns[col_index].width = col_width
            else:
                table.columns[col_index].width = Inches(0.1)

            cell = table.cell(0, col_index)
            cell.text = header_text
            cell.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER

        # Populate the table with data
        for row_index, row_data in enumerate(table_data[1:], start=2):
            for col_index, cell_value in enumerate(row_data):
                table.cell(row_index, col_index).text = str(
                    self.format_string(cell_value)
                )

        # for each ticker, create a row of data.

    def format_string(self, _input: str):
        "Format the string to fit the table"
        if _input is None:
            return ""
        try:
            _input = float(_input)
            # convert the number to #,##0.0 format
            return "{:,.1f}".format(_input)

        except ValueError:
            return _input


class CompanyProfile:
    "Defining the company profile layout"

    def __init__(
        self,
        ppt_slide_object,
        work_area: SlideWorkArea,
        company_url: str,
        default_settings: DefaultSettings,
    ) -> None:

        if default_settings is None:
            default_settings = DefaultSettings()

        if company_url is None:
            raise ValueError("Company URL is required")

        self.ppt_slide_object = ppt_slide_object
        self.work_area = work_area

        self.parsed_url = parsed_url(company_url)
        self.company_url = self.parsed_url.url
