import uuid
from datetime import datetime

from sqlalchemy import String, Integer, Float, Boolean, Text, DateTime, ForeignKey, Uuid, func
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.database import Base


class VoteSession(Base):
    __tablename__ = "vote_sessions"

    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    decision_id: Mapped[uuid.UUID | None] = mapped_column(ForeignKey("decisions.id"))
    item_version_id: Mapped[uuid.UUID | None] = mapped_column(ForeignKey("item_versions.id"))
    voting_protocol_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("voting_protocols.id"), nullable=False)

    # Snapshot at session start
    wot_size: Mapped[int] = mapped_column(Integer, default=0)
    smith_size: Mapped[int] = mapped_column(Integer, default=0)
    techcomm_size: Mapped[int] = mapped_column(Integer, default=0)

    # Dates
    starts_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    ends_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)

    # Status
    status: Mapped[str] = mapped_column(String(32), default="open")  # open, closed, tallied

    # Tallies
    votes_for: Mapped[int] = mapped_column(Integer, default=0)
    votes_against: Mapped[int] = mapped_column(Integer, default=0)
    votes_total: Mapped[int] = mapped_column(Integer, default=0)
    smith_votes_for: Mapped[int] = mapped_column(Integer, default=0)
    techcomm_votes_for: Mapped[int] = mapped_column(Integer, default=0)
    threshold_required: Mapped[float] = mapped_column(Float, default=0.0)
    result: Mapped[str | None] = mapped_column(String(32))  # adopted, rejected, null

    # Chain recording
    chain_recorded: Mapped[bool] = mapped_column(Boolean, default=False)
    chain_tx_hash: Mapped[str | None] = mapped_column(String(128))

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

    votes: Mapped[list["Vote"]] = relationship(back_populates="session", cascade="all, delete-orphan")


class Vote(Base):
    __tablename__ = "votes"

    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    session_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("vote_sessions.id"), nullable=False)
    voter_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("duniter_identities.id"), nullable=False)
    vote_value: Mapped[str] = mapped_column(String(32), nullable=False)  # for, against, or nuanced levels
    nuanced_level: Mapped[int | None] = mapped_column(Integer)  # 0-5 for nuanced votes
    comment: Mapped[str | None] = mapped_column(Text)

    # Cryptographic proof
    signature: Mapped[str] = mapped_column(Text, nullable=False)
    signed_payload: Mapped[str] = mapped_column(Text, nullable=False)

    # Voter status snapshot
    voter_wot_status: Mapped[str] = mapped_column(String(32), default="member")
    voter_is_smith: Mapped[bool] = mapped_column(Boolean, default=False)
    voter_is_techcomm: Mapped[bool] = mapped_column(Boolean, default=False)
    is_active: Mapped[bool] = mapped_column(Boolean, default=True)

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

    session: Mapped["VoteSession"] = relationship(back_populates="votes")
