from enum import Enum
from fpdf import FPDF
from fpdf.fonts import FontFace
from fpdf.enums import TableCellFillMode
import time


class PDF_ORIENTATION(Enum):
    Portrait = "P"
    Landscape = "L"


class TablePDF(FPDF):
    title: str = "No Title"

    header_name: list = None
    header_size: list = None
    header_align: list = None

    row_values: list = None

    line_width: float = 0.3

    style_mappings: dict = {
        "N": {"color": (255, 0, 0), "style": "B"},
        "W": {"color": (255, 165, 0), "style": "B"},
        "": {"color": (0, 0, 0), "style": ""},
    }

    def doc_title(self, title: str = "No Title") -> None:
        """
        Specify the title or the PDF, display on the header parts

        :param title: Title of the document
        :type  title: str
        """
        self.title = title

    def doc_font(self, family="helvetica", style="", size=10, fontpath=None):
        if fontpath:
            self.add_font(family, style, fontpath)

        self.set_font(family, style, size=size)

    def doc_line_width(self, line_with: float = 0.3) -> None:
        """
        Specify the line width by default

        :param line_width: Value of the line width
        :type  line_width: float
        """
        self.line_width = line_with

    def grid_header(self, headers=[]):
        """
        Header is a list of tuples, with Column name, size and align

        :param headers:
        """
        self.header_name = []
        self.header_size = []
        self.header_align = []
        for h in headers:
            self.header_name.append(h[0])
            self.header_size.append(self.epw * h[1] / 100)
            self.header_align.append(h[2])

    def grid_rows(self, rows=[]):
        """
        Rows is a list of list with values

        :param rows: list of element to print
        :type  rows: list
        """
        if len(rows[0]) > len(self.header_name) + 1:
            raise ValueError("Number of rows exceeds number of headers + 1 for conditional styling")

        self.row_values = rows

    def doc_save(self, destination=None):
        """
        Specify the path of the file, can be a str or a stream

        :param destination: path of the file
        """
        self._draw_table()
        if destination is not None:
            self.output(destination)

    def _draw_table(self):
        self.add_page()
        self.set_draw_color(71, 156, 177)
        self.set_line_width(self.line_width)
        headings_style = FontFace(emphasis="BOLD", color=255, fill_color=(71, 156, 177))

        with self.table(
            borders_layout="NO_HORIZONTAL_LINES",
            cell_fill_color=(224, 235, 255),
            cell_fill_mode=TableCellFillMode.ROWS,
            col_widths=tuple(self.header_size),
            headings_style=headings_style,
            line_height=6,
            text_align=tuple(self.header_align),
            width=self.epw - self.l_margin - self.r_margin,
        ) as table:
            # Add header information
            row = table.row()
            for head in self.header_name:
                row.cell(head, align="C")
            # Add lines
            for data_row in self.row_values:
                row = table.row()
                for i, datum in enumerate(data_row):
                    hasCondition = len(data_row) > len(self.header_name)

                    if hasCondition:
                        valueCondition = data_row[-1]
                        # Apply style based on condition value
                        if valueCondition in self.style_mappings:
                            style = self.style_mappings[valueCondition]
                            self.set_text_color(*style["color"])
                            self.set_font(None, style["style"], None)
                        else:
                            # Default style
                            self.set_text_color(0, 0, 0)
                            self.set_font(None, "", None)
                    else:
                        # No condition, use default style
                        self.set_text_color(0, 0, 0)
                        self.set_font(None, "", None)

                    if i < len(self.header_name):
                        row.cell(str(datum))
                    else:
                        # Conditional column, do not create a cell for it
                        break

    def header(self):
        # Rendering logo:
        # self.image("../docs/fpdf2-logo.png", 10, 8, 33)
        # Setting font: helvetica bold 15
        self.set_font("helvetica", "B", 15)
        # Moving cursor to the right:
        self.cell(80)
        # Printing title:
        self.cell(30, 10, self.title, border=0, align="C")
        # Performing a line break:
        self.ln(20)

    def footer(self):
        # Position cursor at 1.5 cm from bottom:
        self.set_y(-15)
        # Setting font: helvetica italic 8
        self.set_font("helvetica", "I", 8)
        # Printing page number:
        self.cell(0, 10, "Date %s" % time.strftime("%Y-%m-%d"), align="L")
        self.cell(0, 10, f"Page {self.page_no()}/{{nb}}", align="R")

    # def grid(self, size)
