"""Review model (Trust System — Phase 2: Reviews & Ratings).

A :class:`Review` is one participant's rating (and optional comment) of the other
party in a finalised sale. It is anchored to a :class:`CompletedTransaction`, so
a review can only ever exist for a real, completed exchange — the trustworthy
foundation Phase 1 established.

Integrity is enforced at the database level:

* one review **per reviewer per transaction** (unique constraint);
* ``rating`` constrained to 1–5 (check constraint);
* reviewer and reviewee must differ (check constraint);
* foreign keys to the transaction and both users.

The model has a stable ``public_id`` and clean relationships so future phases
(reputation, badges, seller statistics, review moderation) can reference it
without reshaping this table.
"""

from __future__ import annotations

from app.extensions import db
from app.models.base import BaseModel, BigIntegerType
from app.models.mixins import PublicIdMixin, TimestampMixin

MAX_COMMENT_LENGTH = 1000
MIN_RATING = 1
MAX_RATING = 5


class Review(BaseModel, PublicIdMixin, TimestampMixin):
    """One participant's rating of the other party in a completed transaction."""

    __tablename__ = "reviews"
    __table_args__ = (
        # One review per reviewer per transaction (buyer and seller each get one).
        db.UniqueConstraint("transaction_id", "reviewer_id", name="uq_reviews_transaction_reviewer"),
        db.CheckConstraint(
            f"rating >= {MIN_RATING} AND rating <= {MAX_RATING}", name="ck_reviews_rating_range"
        ),
        db.CheckConstraint("reviewer_id <> reviewee_id", name="ck_reviews_distinct_users"),
        # Reputation / "reviews received" lookups filter by reviewee.
        db.Index("ix_reviews_reviewee_id", "reviewee_id"),
        db.Index("ix_reviews_transaction_id", "transaction_id"),
    )

    transaction_id = db.Column(
        BigIntegerType, db.ForeignKey("completed_transactions.id"), nullable=False
    )
    reviewer_id = db.Column(BigIntegerType, db.ForeignKey("users.id"), nullable=False)
    reviewee_id = db.Column(BigIntegerType, db.ForeignKey("users.id"), nullable=False)
    rating = db.Column(db.SmallInteger, nullable=False)
    comment = db.Column(db.String(MAX_COMMENT_LENGTH), nullable=True)

    transaction = db.relationship("CompletedTransaction", foreign_keys=[transaction_id])
    reviewer = db.relationship("User", foreign_keys=[reviewer_id])
    reviewee = db.relationship("User", foreign_keys=[reviewee_id])

    def __repr__(self) -> str:
        return f"<Review id={self.id} transaction_id={self.transaction_id} rating={self.rating}>"
