from dataclasses import dataclass

from typing import Literal, Any, Dict

from .typograpyhy import TypographySpec
from .surface import SurfaceSpec

AxesStyle = Literal["modern", "minimal", "dense", "none"]


@dataclass(frozen=True)
class AxesSpec:
    style: AxesStyle = "modern"
    grid: bool = True
    grid_color: str = "#E5E7EB"
    line_color: str = "#E5E7EB"
    tick_color: str = "#D1D5DB"
    zeroline: bool = False
    showline: bool = True
    ticks: str = "outside"
    mirror: bool = False  # mirror axes lines
    showspikes: bool = False
    spikemode: str = "across"
    spikecolor: str = "#CBD5E1"
    spikethickness: int = 1

    def build_axis(self, typography: TypographySpec, surface: SurfaceSpec) -> Dict[str, Any]:
        tick_size = typography.tick_size if typography.tick_size is not None else max(10, typography.size - 2)

        if surface.mode == "dark":
            grid_color = surface.grid_dark
            line_color = surface.axis_line_dark
            tick_color = "#94A3B8"
        else:
            grid_color = self.grid_color
            line_color = self.line_color
            tick_color = self.tick_color

        axis = dict(
            showgrid=self.grid and self.style != "none",
            gridcolor=grid_color,
            zeroline=self.zeroline,
            showline=self.showline and self.style != "none",
            linecolor=line_color,
            ticks=self.ticks,
            tickcolor=tick_color,
            tickfont=dict(size=tick_size),
            mirror=self.mirror,
        )

        if self.showspikes:
            axis.update(
                showspikes=True,
                spikemode=self.spikemode,
                spikecolor=self.spikecolor,
                spikethickness=self.spikethickness,
            )

        # Minimal style reduces grid emphasis
        if self.style == "minimal":
            axis["showgrid"] = True
            axis["gridcolor"] = "#F1F5F9" if surface.mode != "dark" else surface.grid_dark
            axis["linecolor"] = "#E5E7EB" if surface.mode != "dark" else surface.axis_line_dark

        # Dense style reduces margins in combination with layout density
        return axis