package db

import (
	"context"
	"time"

	"github.com/jackc/pgx/v5/pgtype"
)

const createReview = `-- name: CreateReview :one
INSERT INTO reviews (
  submitted_by,
  comments,
  score,
  is_from_critic,
  is_hided,
  location_id
) VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, submitted_by, comments, score, is_from_critic, is_hided, location_id, created_at, updated_at
`

type CreateReviewParams struct {
	SubmittedBy  int32  `json:"submitted_by"`
	Comments     string `json:"comments"`
	Score        int16  `json:"score"`
	IsFromCritic bool   `json:"is_from_critic"`
	IsHided      bool   `json:"is_hided"`
	LocationID   int32  `json:"location_id"`
}

func (q *Queries) CreateReview(ctx context.Context, arg CreateReviewParams) (Review, error) {
	row := q.db.QueryRow(ctx, createReview,
		arg.SubmittedBy,
		arg.Comments,
		arg.Score,
		arg.IsFromCritic,
		arg.IsHided,
		arg.LocationID,
	)
	var i Review
	err := row.Scan(
		&i.ID,
		&i.SubmittedBy,
		&i.Comments,
		&i.Score,
		&i.IsFromCritic,
		&i.IsHided,
		&i.LocationID,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

type GetListLocationReviewsParams struct {
	LocationID int32 `json:"location_id"`
	Limit      int8  `json:"limit"`
	Offset     int8  `json:"offset"`
	IsCritics  bool  `json:"is_critics"`
}

type GetListLocationReviewsRow struct {
	ID         int32       `json:"id"`
	Score      int8        `json:"score"`
	Comment    string      `json:"comments"`
	UserID     int32       `json:"user_id"`
	Username   string      `json:"username"`
	UserAvatar pgtype.Text `json:"user_avatar"`
	CreatedAt  time.Time   `json:"created_at"`
	UpdatedAt  time.Time   `json:"updated_at"`
}

const getListLocationReviews = `
SELECT
  re.id as id,
  re.score as score,
  re.comments as comments,
  u.id as user_id,
  u.username as username,
  u.avatar_picture as user_avatar,
  re.created_at as created_at,
  re.updated_at as updated_at
FROM REVIEWS re
JOIN users u on re.submitted_by = u.id
WHERE re.location_id = $1 AND re.is_from_critic = $2
LIMIT $3
OFFSET $4;
`

func (q *Queries) GetListLocationReviews(ctx context.Context, arg GetListLocationReviewsParams) ([]GetListLocationReviewsRow, error) {
	rows, err := q.db.Query(ctx, getListLocationReviews, arg.LocationID, arg.IsCritics, arg.Limit, arg.Offset)
	if err != nil {
		return nil, err
	}

	defer rows.Close()

	items := []GetListLocationReviewsRow{}

	for rows.Next() {
		var i GetListLocationReviewsRow
		if err := rows.Scan(
			&i.ID,
			&i.Score,
			&i.Comment,
			&i.UserID,
			&i.Username,
			&i.UserAvatar,
			&i.CreatedAt,
			&i.UpdatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	rows.Close()
	if err := rows.Err(); err != nil {
		return nil, err
	}

	return items, nil
}