from datetime import datetime
import time
from typing import Optional
from sqlmodel import Field, Relationship, SQLModel


class AppAdmin(SQLModel, table=True):
    name: str = Field(primary_key=True, unique=True)
    password_hash: str = Field()
    role: str = Field()
    locations: list["Location"] = Relationship(back_populates="assigned_admin")
    capture_tokens: list["CaptureTokenInfo"] = Relationship(
        back_populates="admin"
    )


class Country(SQLModel, table=True):
    name: str = Field(primary_key=True, unique=True)
    code: str = Field(index=True, unique=True)
    locations: list["Location"] = Relationship(
        back_populates="country", cascade_delete=True
    )


class Location(SQLModel, table=True):
    name: str = Field(primary_key=True, unique=True)
    country_name: Optional[str] = Field(
        foreign_key="country.name", default=None
    )
    country: Country = Relationship(back_populates="locations")
    lat: float = Field()
    long: float = Field()
    assigned_admin_name: Optional[str] = Field(
        foreign_key="appadmin.name", default=None
    )
    assigned_admin: AppAdmin = Relationship(back_populates="locations")
    tokens: list["CaptureTokenInfo"] = Relationship(
        back_populates="location", cascade_delete=True
    )
    enabled: bool = Field(default=False)


class TokenInfoBase(SQLModel):
    nonce: str = Field(primary_key=True)
    expires_at: int = Field(default=int(time.time() + 900))
    token_type: str = Field()

    @property
    def expired(self):
        return int(time.time()) >= self.expires_at


class TokenInfo(TokenInfoBase, table=True):
    pass


class CaptureTokenInfo(TokenInfoBase, table=True):
    admin_name: Optional[str] = Field(
        foreign_key="appadmin.name", default=None
    )
    admin: AppAdmin = Relationship(back_populates="capture_tokens")
    location_name: Optional[str] = Field(
        foreign_key="location.name", default=None
    )
    location: Location = Relationship(back_populates="tokens")


class AppUser(SQLModel, table=True):
    hashid: str = Field(primary_key=True)
    encrypted_key: bytes = Field()
    encrypted_email: bytes = Field()


class Recipient(SQLModel, table=True):
    hashid: str = Field(primary_key=True)


class Video(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    raw: str = Field()
    overlay: str | None = Field(default=None)
    user_hashid: str = Field(foreign_key="appuser.hashid")
    length: float = Field(default=0.0)
    location_name: str = Field(foreign_key="location.name")


class CardContent(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    from_enc: bytes = Field()
    to_enc: bytes = Field()
    msg_enc: bytes = Field()
    video_id: int = Field(foreign_key="video.id", unique=True)


class TrustedDevice(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    location_name: str = Field(
        foreign_key="location.name", unique=True, index=True
    )
    user_agent: str = Field()
    last_used: datetime = Field()
