from __future__ import annotations
from dataclasses import dataclass
from typing import Any, TYPE_CHECKING

from zempy.zosapi.editors.solve.enums.solve_type import SolveType
from zempy.zosapi.editors.solve.enums.solve_status import SolveStatus

if TYPE_CHECKING:
    from zempy.zosapi.system.protocols.IOpticalSystem import IOpticalSystem


@dataclass(frozen=True, slots=True)
class Field:
    system: IOpticalSystem
    _ifield: Any  # ZOSAPI.SystemData.IField

    @property
    def is_active(self) -> bool:
        return bool(self._ifield.IsActive)

    @property
    def field_number(self) -> int:
        return int(self._ifield.FieldNumber)

    @property
    def x(self) -> float:
        return float(self._ifield.X)

    @x.setter
    def x(self, value: float) -> None:
        self._ifield.X = float(value)

    @property
    def y(self) -> float:
        return float(self._ifield.Y)

    @y.setter
    def y(self, value: float) -> None:
        self._ifield.Y = float(value)

    def set_xy(self, x: float, y: float) -> None:
        self._ifield.X = float(x)
        self._ifield.Y = float(y)

    @property
    def weight(self) -> float:
        return float(self._ifield.Weight)

    @weight.setter
    def weight(self, value: float) -> None:
        self._ifield.Weight = float(value)

    @property
    def vdx(self) -> float:
        return float(self._ifield.VDX)

    @vdx.setter
    def vdx(self, value: float) -> None:
        self._ifield.VDX = float(value)

    @property
    def vdy(self) -> float:
        return float(self._ifield.VDY)

    @vdy.setter
    def vdy(self, value: float) -> None:
        self._ifield.VDY = float(value)

    @property
    def vcx(self) -> float:
        return float(self._ifield.VCX)

    @vcx.setter
    def vcx(self, value: float) -> None:
        self._ifield.VCX = float(value)

    @property
    def vcy(self) -> float:
        return float(self._ifield.VCY)

    @vcy.setter
    def vcy(self, value: float) -> None:
        self._ifield.VCY = float(value)

    @property
    def van(self) -> float:
        return float(self._ifield.VAN)

    @van.setter
    def van(self, value: float) -> None:
        self._ifield.VAN = float(value)

    @property
    def tan(self) -> float:
        return float(self._ifield.TAN)

    @tan.setter
    def tan(self, value: float) -> None:
        self._ifield.TAN = float(value)

    @property
    def comment(self) -> str:
        return str(self._ifield.Comment or "")

    @comment.setter
    def comment(self, value: str) -> None:
        self._ifield.Comment = str(value)

    @property
    def ignore(self) -> bool:
        return bool(self._ifield.Ignore)

    @ignore.setter
    def ignore(self, value: bool) -> None:
        self._ifield.Ignore = bool(value)

    # ---- SolveType getters use classmethod from the enum (Option A) ----
    @property
    def x_solve(self) -> SolveType:
        return SolveType.from_native(self.zs, self._ifield.XSolve)

    @property
    def y_solve(self) -> SolveType:
        return SolveType.from_native(self.zs, self._ifield.YSolve)

    # ---- ISolveData getters (native objects) ----
    def get_x_solve_data(self) -> Any:
        return self._ifield.GetXSolveData()

    def get_y_solve_data(self) -> Any:
        return self._ifield.GetYSolveData()

    def get_solve_data(self, column: Any) -> Any:
        return self._ifield.GetSolveData(column)

    # ---- Pickup/Fixed mutators now return your Python SolveStatus ----
    def set_x_pickup(
        self,
        from_field: int,
        from_column: Any,
        scale: float = 1.0,
        offset: float = 0.0,
    ) -> SolveStatus:
        native = self._ifield.SetXPickup(int(from_field), from_column, float(scale), float(offset))
        return SolveStatus.from_native(native, self.system.zosapi)

    def set_x_fixed(self) -> SolveStatus:
        native = self._ifield.SetXFixed()
        return SolveStatus.from_native(native, self.system.zosapi)

    def set_y_pickup(
        self,
        from_field: int,
        from_column: Any,
        scale: float = 1.0,
        offset: float = 0.0,
    ) -> SolveStatus:
        native = self._ifield.SetYPickup(int(from_field), from_column, float(scale), float(offset))
        return SolveStatus.from_native(native, self.system.zosapi)

    def set_y_fixed(self) -> SolveStatus:
        native = self._ifield.SetYFixed()
        return SolveStatus.from_native(native, self.system.zosapi)

    def set_pickup(
        self,
        column: Any,
        from_field: int,
        from_column: Any,
        scale: float = 1.0,
        offset: float = 0.0,
    ) -> SolveStatus:
        native = self._ifield.SetPickup(column, int(from_field), from_column, float(scale), float(offset))
        return SolveStatus.from_native(native, self.system.zosapi)

    def set_fixed(self, column: Any) -> SolveStatus:
        native = self._ifield.SetFixed(column)
        return SolveStatus.from_native(native, self.system.zosapi)
