from datetime import datetime
from enum import Enum
from typing import Optional

from sqlalchemy import UniqueConstraint
from sqlmodel import Field, SQLModel


class PollStatus(str, Enum):
    draft = "draft"
    open = "open"
    closed = "closed"


class Room(SQLModel, table=True):
    id: str = Field(primary_key=True)
    name: str = ""
    created_at: datetime = Field(default_factory=datetime.utcnow)


class Poll(SQLModel, table=True):
    id: str = Field(primary_key=True)
    room_id: str = Field(foreign_key="room.id", index=True)
    title: str
    options_json: str = Field(default="[]")  # JSON array of strings for SQLite simplicity
    status: PollStatus = Field(default=PollStatus.draft)
    winner_option: Optional[str] = None
    winner_source: str = ""
    deadline_at: Optional[datetime] = None
    config_json: str = Field(default="{}")
    runtime_json: str = Field(default="{}")
    created_at: datetime = Field(default_factory=datetime.utcnow)


class Vote(SQLModel, table=True):
    __table_args__ = (UniqueConstraint("poll_id", "voter_id", name="uq_vote_poll_voter"),)

    id: Optional[int] = Field(default=None, primary_key=True)
    poll_id: str = Field(foreign_key="poll.id", index=True)
    voter_id: str = Field(index=True)
    choice: str
    created_at: datetime = Field(default_factory=datetime.utcnow)


class LineEventRecord(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    event_id: str = Field(unique=True, index=True)
    event_type: str = ""
    raw_preview: str = ""
    raw_json: str = ""
    room_id: str = Field(default="", index=True)
    participant_id: str = Field(default="", index=True)
    line_user_id_hash: str = Field(default="", index=True)
    reply_status: str = ""
    reply_error: str = ""
    created_at: datetime = Field(default_factory=datetime.utcnow)


class Participant(SQLModel, table=True):
    __table_args__ = (UniqueConstraint("room_id", "line_user_id_hash", name="uq_participant_room_line"),)

    id: str = Field(primary_key=True)
    room_id: str = Field(foreign_key="room.id", index=True)
    line_user_id_hash: str = Field(default="", index=True)
    source: str = ""
    display_name: str = ""
    joined_at: datetime = Field(default_factory=datetime.utcnow)
    last_seen_at: datetime = Field(default_factory=datetime.utcnow)


class AudienceSession(SQLModel, table=True):
    session_id: str = Field(primary_key=True)
    participant_id: str = Field(foreign_key="participant.id", index=True)
    room_id: str = Field(foreign_key="room.id", index=True)
    line_user_id_hash: str = Field(default="", index=True)
    source: str = ""
    created_at: datetime = Field(default_factory=datetime.utcnow)
    last_seen_at: datetime = Field(default_factory=datetime.utcnow)
    expires_at: datetime


class JoinToken(SQLModel, table=True):
    token: str = Field(primary_key=True)
    participant_id: str = Field(foreign_key="participant.id", index=True)
    room_id: str = Field(foreign_key="room.id", index=True)
    line_user_id_hash: str = Field(default="", index=True)
    source: str = ""
    event_id: str = Field(default="", index=True)
    metadata_json: str = Field(default="{}")
    created_at: datetime = Field(default_factory=datetime.utcnow)
    expires_at: datetime
    last_used_at: Optional[datetime] = None
    use_count: int = 0