"""Domain enumerations. Stored as native PostgreSQL enum types."""
import enum

from sqlalchemy import Enum as SAEnum


class StrEnum(str, enum.Enum):
    """String-valued enum whose value is used both in the DB and the API."""

    def __str__(self) -> str:  # pragma: no cover - convenience
        return self.value


def pg_enum(enum_cls: type[enum.Enum], name: str, *, create_type: bool = True) -> SAEnum:
    """Native PG enum whose labels are the member *values* (lowercase), not names.

    Without values_callable SQLAlchemy emits member names ('PENDING'), which then
    mismatch the lowercase server_default / API payloads.
    """
    return SAEnum(
        enum_cls,
        name=name,
        native_enum=True,
        create_type=create_type,
        validate_strings=True,
        values_callable=lambda e: [m.value for m in e],
    )


class UserRole(StrEnum):
    ADMIN = "admin"
    MANAGER = "manager"
    FIELD_STAFF = "field_staff"
    READ_ONLY = "read_only"
    SYSTEM_DEVELOPER = "system_developer"


class ApplicationStatus(StrEnum):
    PENDING = "pending"
    SURVEY = "survey"
    APPROVED = "approved"
    INSTALLED = "installed"
    REJECTED = "rejected"


class ConnectionType(StrEnum):
    ONU_OFFICE = "onu_office"
    ONU_CLIENT = "onu_client"
    PACKAGE_ROUTER = "package_router"


class DocumentType(StrEnum):
    NID = "nid"
    PHOTO = "photo"
    AGREEMENT = "agreement"
    SURVEY_REPORT = "survey_report"
    OTHER = "other"


class ConnectionStatus(StrEnum):
    ACTIVE = "active"
    SUSPENDED = "suspended"
    TERMINATED = "terminated"


class LocationType(StrEnum):
    WAREHOUSE = "warehouse"
    OFFICE = "office"


class EquipmentCondition(StrEnum):
    NEW = "new"
    USED = "used"
    FAULTY = "faulty"


class HolderType(StrEnum):
    WAREHOUSE = "warehouse"
    TECHNICIAN = "technician"
    CUSTOMER = "customer"


class EquipmentItemStatus(StrEnum):
    IN_STOCK = "in_stock"
    ISSUED = "issued"
    RETURNED = "returned"
    WRITTEN_OFF = "written_off"


class DistributionStatus(StrEnum):
    ISSUED = "issued"
    PARTIALLY_RETURNED = "partially_returned"
    RETURNED = "returned"
    WRITTEN_OFF = "written_off"


class StockMovementType(StrEnum):
    INBOUND = "inbound"
    ISSUE = "issue"
    RETURN = "return"
    ADJUSTMENT = "adjustment"
    WRITE_OFF = "write_off"


class ComplaintType(StrEnum):
    NO_INTERNET = "no_internet"
    SLOW_SPEED = "slow_speed"
    BILLING = "billing"
    EQUIPMENT_FAULT = "equipment_fault"
    OTHER = "other"
    ONU_RED_LIGHT = "onu_red_light"
    ROUTER_CONFIGURE = "router_configure"
    FIBER_FAULT = "fiber_fault"


class ComplaintPriority(StrEnum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"


class ComplaintStatus(StrEnum):
    OPEN = "open"
    IN_PROGRESS = "in_progress"
    RESOLVED = "resolved"
    CLOSED = "closed"


class RequisitionStatus(StrEnum):
    PENDING = "pending"
    APPROVED = "approved"
    REJECTED = "rejected"
    COMPLETED = "completed"


# --- Allowed state transitions (enforced in the service layer) ---

APPLICATION_TRANSITIONS: dict[ApplicationStatus, set[ApplicationStatus]] = {
    ApplicationStatus.PENDING: {ApplicationStatus.SURVEY, ApplicationStatus.APPROVED, ApplicationStatus.REJECTED},
    ApplicationStatus.SURVEY: {ApplicationStatus.APPROVED, ApplicationStatus.REJECTED, ApplicationStatus.PENDING},
    ApplicationStatus.APPROVED: {ApplicationStatus.INSTALLED, ApplicationStatus.REJECTED},
    ApplicationStatus.INSTALLED: set(),
    ApplicationStatus.REJECTED: {ApplicationStatus.PENDING},
}

COMPLAINT_TRANSITIONS: dict[ComplaintStatus, set[ComplaintStatus]] = {
    ComplaintStatus.OPEN: {ComplaintStatus.IN_PROGRESS, ComplaintStatus.RESOLVED, ComplaintStatus.CLOSED},
    ComplaintStatus.IN_PROGRESS: {ComplaintStatus.RESOLVED, ComplaintStatus.CLOSED, ComplaintStatus.OPEN},
    ComplaintStatus.RESOLVED: {ComplaintStatus.CLOSED, ComplaintStatus.IN_PROGRESS},
    ComplaintStatus.CLOSED: {ComplaintStatus.IN_PROGRESS},
}

#: Purchase requisition flow: staff/manager request, admin decides, the order is
#: completed once the goods arrive. A rejected request may be re-submitted.
REQUISITION_TRANSITIONS: dict[RequisitionStatus, set[RequisitionStatus]] = {
    RequisitionStatus.PENDING: {RequisitionStatus.APPROVED, RequisitionStatus.REJECTED},
    RequisitionStatus.REJECTED: {RequisitionStatus.PENDING},
    RequisitionStatus.APPROVED: {RequisitionStatus.COMPLETED},
    RequisitionStatus.COMPLETED: set(),
}
