import uuid
import enum
from datetime import datetime
from typing import TYPE_CHECKING

from sqlalchemy import DateTime, Enum, ForeignKey, Integer, String, Text, func
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.core.database import Base

if TYPE_CHECKING:
    from app.models.company import Company
    from app.models.user import User


class KioskAuthMethod(str, enum.Enum):
    PIN = "pin"
    NFC = "nfc"
    QR = "qr"
    LIST = "list"  # Mitarbeiter-Liste


class KioskDeviceStatus(str, enum.Enum):
    PENDING = "pending"    # Wartet auf Admin-Freigabe
    APPROVED = "approved"  # Aktiv, darf stempeln
    REVOKED = "revoked"    # Gesperrt / neu enrollen erforderlich


class KioskDevice(Base):
    __tablename__ = "kiosk_devices"

    id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    company_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True), ForeignKey("companies.id", ondelete="CASCADE"),
        nullable=False, index=True
    )
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    location: Mapped[str | None] = mapped_column(String(255))

    # ── Ed25519-Auth (löst token_hash + is_active ab) ─────────────────────────
    status: Mapped[KioskDeviceStatus] = mapped_column(
        Enum(KioskDeviceStatus, name="kioskdevicestatus", values_callable=lambda x: [e.value for e in x]),
        nullable=False,
        default=KioskDeviceStatus.REVOKED,
    )
    public_key: Mapped[str | None] = mapped_column(Text)           # Ed25519 PEM/OpenSSH
    key_algorithm: Mapped[str] = mapped_column(String(20), nullable=False, default="ed25519")

    # ── Enrollment (einmaliger Setup-Flow) ────────────────────────────────────
    enrollment_token_hash: Mapped[str | None] = mapped_column(String(64))
    enrollment_expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))

    # ── Heartbeat & Liveness ──────────────────────────────────────────────────
    last_heartbeat_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    client_version: Mapped[str | None] = mapped_column(String(50))
    offline_queue_size: Mapped[int] = mapped_column(Integer, nullable=False, default=0)

    # ── DSGVO: aktuell eingestempelter User (per Firma deaktivierbar) ─────────
    current_user_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True
    )

    # ── Sicherheit ────────────────────────────────────────────────────────────
    ip_whitelist: Mapped[str | None] = mapped_column(Text)  # CIDR-Liste, z.B. "10.0.0.0/24,192.168.1.0/24"

    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())

    # ── Relationships ─────────────────────────────────────────────────────────
    company: Mapped["Company"] = relationship("Company", lazy="noload")
    current_user: Mapped["User | None"] = relationship(
        "User", foreign_keys=[current_user_id], lazy="noload"
    )

    def __repr__(self) -> str:
        return f"<KioskDevice {self.name} status={self.status.value} ({self.company_id})>"
