from __future__ import annotations

from dataclasses import dataclass
from typing import Any

from openpyxl.worksheet.worksheet import Worksheet

from xllayout.core.canvas import Anchor, Box
from xllayout.core.theme import Theme
from xllayout.core.utils import apply_range_style


@dataclass
class KpiCard:
    label: str
    value: Any
    value_format: str | None = None
    span_cols: int = 3
    height_rows: int = 3

    def measure(self, anchor: Anchor, span_rows: int | None = None, span_cols: int | None = None) -> Box:
        width = span_cols if span_cols is not None else self.span_cols
        height = span_rows if span_rows is not None else self.height_rows
        if width <= 0 or height <= 0:
            raise ValueError("KpiCard width/height must be > 0")

        return Box(anchor.row, anchor.col, anchor.row + height - 1, anchor.col + width - 1)

    def draw(self, ws: Worksheet, box: Box, theme: Theme) -> None:
        apply_range_style(ws, box, fill=theme.fills.card_bg, border=theme.borders.thin)

        ws.merge_cells(start_row=box.r1, start_column=box.c1, end_row=box.r1, end_column=box.c2)
        label_cell = ws.cell(row=box.r1, column=box.c1, value=self.label)
        label_cell.font = theme.fonts.kpi_label
        label_cell.alignment = theme.alignments.left

        value_row = min(box.r1 + 1, box.r2)
        ws.merge_cells(start_row=value_row, start_column=box.c1, end_row=value_row, end_column=box.c2)
        value_cell = ws.cell(row=value_row, column=box.c1, value=self.value)
        value_cell.font = theme.fonts.kpi_value
        value_cell.alignment = theme.alignments.right

        if self.value_format:
            value_cell.number_format = self.value_format
        elif isinstance(self.value, int):
            value_cell.number_format = theme.number_formats.integer
