"""Spreadsheet domain value objects."""

from __future__ import annotations

import re
from dataclasses import dataclass

from .exceptions import InvalidCellAddressError, InvalidSheetError

_CELL_ADDRESS_PATTERN = re.compile(r"^([A-Z]+)([1-9]\d*)$")


def _column_to_index(column: str) -> int:
    index = 0
    for char in column:
        index = index * 26 + (ord(char) - 64)
    return index


@dataclass(frozen=True)
class SheetName:
    value: str

    def __post_init__(self) -> None:
        if not isinstance(self.value, str):
            raise InvalidSheetError("sheet name must be a string")
        name = self.value.strip()
        if not name:
            raise InvalidSheetError("sheet name cannot be empty")
        object.__setattr__(self, "value", name)


@dataclass(frozen=True)
class CellAddress:
    value: str

    def __post_init__(self) -> None:
        if not isinstance(self.value, str):
            raise InvalidCellAddressError("cell address must be a string")
        address = self.value.strip().upper()
        match = _CELL_ADDRESS_PATTERN.fullmatch(address)
        if match is None:
            raise InvalidCellAddressError("cell address must use A1 notation")
        object.__setattr__(self, "value", address)

    @property
    def column(self) -> str:
        return _CELL_ADDRESS_PATTERN.fullmatch(self.value).group(1)  # type: ignore[union-attr]

    @property
    def row(self) -> int:
        return int(_CELL_ADDRESS_PATTERN.fullmatch(self.value).group(2))  # type: ignore[union-attr]

    @property
    def column_index(self) -> int:
        return _column_to_index(self.column)

