"""Pydantic schemas for the API."""

from enum import Enum

from pydantic import BaseModel, ConfigDict, Field


class UserRole(str, Enum):
    """Enum of user roles."""

    GUEST = "guest"
    DM = "dm"
    ANALYST = "analyst"


class UserPrivileges(str, Enum):
    """Enum of user privileges."""

    CREATE_PROBLEMS = "Create problems"
    CREATE_USERS = "Create users"
    ACCESS_ALL_PROBLEMS = "Access all problems"
    EDIT_USERS = "Change user privileges, roles, groups, etc."


class ProblemKind(str, Enum):
    """Enum of problem kinds."""

    CONTINUOUS = "continuous"
    DISCRETE = "discrete"
    MIXED = "mixed"
    BINARY = "binary"


class ObjectiveKind(str, Enum):
    """Enum of objective kinds."""

    ANALYTICAL = "analytical"
    DATABASED = "databased"
    SIMULATED = "simulated"
    SURROGATE = "surrogate"


class Methods(str, Enum):
    """Enum of methods."""

    NIMBUS = "nimbus"
    NAUTILUS = "nautilus"
    NAUT_NAVIGATOR = "NAUTILUS navigator"
    NAUTILUSII = "nautilusII"
    EMO = "EMO"


class MethodProperties(str, Enum):
    """Enum of method properties."""

    INTERACTIVE = "interactive"
    REFERENCE_POINT = "reference_point"
    CLASSIFICATION = "classification"
    BOUNDS = "bounds"
    PREFERRED_SOLUTIONS = "preferred_solutions"
    NON_PREFERRED_SOLUTIONS = "non_preferred_solutions"
    # TODO: Add more properties as needed.


class User(BaseModel):
    """Model for a user. Temporary."""

    username: str = Field(description="Username of the user.")
    index: int | None = Field(
        description=(
            "Index of the user in the database. "
            "Supposed to be automatically generated by the database. "
            "So the programmer should not have to worry about it."
        )
    )
    password_hash: str = Field(description="SHA256 Hash of the user's password.")
    role: UserRole = Field(description="Role of the user.")
    privileges: list[UserPrivileges] = Field(
        description="List of privileges the user has."
    )
    user_group: str = Field(
        description="User group of the user. Used for group decision making."
    )
    # To allows for User to be initialized from database instead of just dicts.
    model_config = ConfigDict(from_attributes=True)


class Solvers(Enum):
    """Enum of available solvers."""

    # These should match available_solvers in desdeo.tools.utils

    SCIPY_MIN = "scipy_minimize"
    SCIPY_DE = "scipy_de"
    PROXIMAL = "proximal"
    NEVERGRAD = "nevergrad"
    PYOMO_BONMIN = "pyomo_bonmin"
    PYOMO_IPOPT = "pyomo_ipopt"
    PYOMO_GUROBI = "pyomo_gurobi"
    GUROBIPY = "gurobipy"
