<?php
class Review {
    private $conn;
    private $table_name = "reviews";

    public $id;
    public $user_id;
    public $product_id;
    public $service_id;
    public $rating;
    public $comment;
    public $is_approved;
    public $is_visible;

    public function __construct($db) {
        $this->conn = $db;
    }

    public function create() {
        $query = "INSERT INTO " . $this->table_name . "
                SET user_id=:user_id, product_id=:product_id, service_id=:service_id, rating=:rating, comment=:comment, is_approved=:is_approved, is_visible=:is_visible";

        $stmt = $this->conn->prepare($query);

        $this->user_id = htmlspecialchars(strip_tags($this->user_id ?? ''));
        $this->rating = htmlspecialchars(strip_tags($this->rating ?? ''));
        $this->comment = htmlspecialchars(strip_tags($this->comment ?? ''));
        $this->is_approved = $this->is_approved ?? 1;
        $this->is_visible = $this->is_visible ?? 1;

        // Handle nullable fields correctly
        $this->product_id = !empty($this->product_id) ? htmlspecialchars(strip_tags($this->product_id)) : null;
        $this->service_id = !empty($this->service_id) ? htmlspecialchars(strip_tags($this->service_id)) : null;


        $stmt->bindParam(":user_id", $this->user_id);
        $stmt->bindParam(":product_id", $this->product_id);
        $stmt->bindParam(":service_id", $this->service_id);
        $stmt->bindParam(":rating", $this->rating);
        $stmt->bindParam(":comment", $this->comment);
        $stmt->bindParam(":is_approved", $this->is_approved);
        $stmt->bindParam(":is_visible", $this->is_visible);

        if($stmt->execute()) {
            $this->id = $this->conn->lastInsertId();
            return true;
        }

        return false;
    }

    public function getReviewsByProduct($product_id) {
        $query = "SELECT r.*, u.name as user_name
                  FROM " . $this->table_name . " r
                  LEFT JOIN users u ON r.user_id = u.id
                  WHERE r.product_id = ? AND r.is_approved = 1 AND r.is_visible = 1
                  ORDER BY r.created_at DESC";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(1, $product_id);
        $stmt->execute();

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function getReviewsByService($service_id) {
        $query = "SELECT r.*, u.name as user_name
                  FROM " . $this->table_name . " r
                  LEFT JOIN users u ON r.user_id = u.id
                  WHERE r.service_id = ? AND r.is_approved = 1 AND r.is_visible = 1
                  ORDER BY r.created_at DESC";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(1, $service_id);
        $stmt->execute();

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function getAverageRating($product_id) {
        $query = "SELECT AVG(rating) as average_rating, COUNT(*) as total_reviews
                  FROM " . $this->table_name . "
                  WHERE product_id = ? AND is_approved = 1 AND is_visible = 1";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(1, $product_id);
        $stmt->execute();

        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    public function getAverageRatingByService($service_id) {
        $query = "SELECT AVG(rating) as average_rating, COUNT(*) as total_reviews
                  FROM " . $this->table_name . "
                  WHERE service_id = ? AND is_approved = 1 AND is_visible = 1";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(1, $service_id);
        $stmt->execute();

        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    public function getAllReviews($limit = null, $offset = 0, $include_hidden = true) {
        $query = "SELECT r.*, u.name as user_name, p.name as product_name
                  FROM " . $this->table_name . " r
                  LEFT JOIN users u ON r.user_id = u.id
                  LEFT JOIN products p ON r.product_id = p.id";

        if (!$include_hidden) {
            $query .= " WHERE r.is_visible = 1 AND r.is_approved = 1";
        }

        $query .= " ORDER BY r.created_at DESC";

        if ($limit !== null) {
            $query .= " LIMIT " . (int)$limit . " OFFSET " . (int)$offset;
        }

        $stmt = $this->conn->prepare($query);
        $stmt->execute();

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function userHasReviewed($user_id, $product_id) {
        $query = "SELECT id FROM " . $this->table_name . "
                  WHERE user_id = ? AND product_id = ? LIMIT 0,1";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(1, $user_id);
        $stmt->bindParam(2, $product_id);
        $stmt->execute();

        return $stmt->rowCount() > 0;
    }

    public function userHasReviewedService($user_id, $service_id) {
        $query = "SELECT id FROM " . $this->table_name . "
                  WHERE user_id = ? AND service_id = ? LIMIT 0,1";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(1, $user_id);
        $stmt->bindParam(2, $service_id);
        $stmt->execute();

        return $stmt->rowCount() > 0;
    }

    public function update() {
        $query = "UPDATE " . $this->table_name . "
                SET rating=:rating, comment=:comment, updated_at=CURRENT_TIMESTAMP
                WHERE id=:id AND user_id=:user_id";

        $stmt = $this->conn->prepare($query);

        $this->rating = htmlspecialchars(strip_tags($this->rating ?? ''));
        $this->comment = htmlspecialchars(strip_tags($this->comment ?? ''));

        $stmt->bindParam(":rating", $this->rating);
        $stmt->bindParam(":comment", $this->comment);
        $stmt->bindParam(":id", $this->id);
        $stmt->bindParam(":user_id", $this->user_id);

        if($stmt->execute()) {
            return true;
        }

        return false;
    }

    public function delete() {
        $query = "DELETE FROM " . $this->table_name . "
                  WHERE id = ? AND user_id = ?";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(1, $this->id);
        $stmt->bindParam(2, $this->user_id);

        if($stmt->execute()) {
            return true;
        }

        return false;
    }

    public function approveReview($review_id) {
        $query = "UPDATE " . $this->table_name . "
                  SET is_approved = 1, is_visible = 1
                  WHERE id = ?";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(1, $review_id);

        if($stmt->execute()) {
            return true;
        }

        return false;
    }

    public function hideReview($review_id) {
        $query = "UPDATE " . $this->table_name . "
                  SET is_visible = 0
                  WHERE id = ?";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(1, $review_id);

        if($stmt->execute()) {
            return true;
        }

        return false;
    }

    public function showReview($review_id) {
        $query = "UPDATE " . $this->table_name . "
                  SET is_visible = 1
                  WHERE id = ?";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(1, $review_id);

        if($stmt->execute()) {
            return true;
        }

        return false;
    }

    public function deleteReview($review_id) {
        $query = "DELETE FROM " . $this->table_name . " WHERE id = ?";

        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(1, $review_id);

        if($stmt->execute()) {
            return true;
        }

        return false;
    }

    public function updateReview($review_id, $data) {
        $set_parts = [];
        $bind_values = [];

        foreach ($data as $column => $value) {
            $set_parts[] = $column . " = ?";
            $bind_values[] = $value;
        }

        if (empty($set_parts)) {
            return false;
        }

        $query = "UPDATE " . $this->table_name . "
                  SET " . implode(", ", $set_parts) . "
                  WHERE id = ?";
        $bind_values[] = $review_id;

        $stmt = $this->conn->prepare($query);

        for ($i = 0; $i < count($bind_values); $i++) {
            $stmt->bindParam($i + 1, $bind_values[$i]);
        }

        if($stmt->execute()) {
            return true;
        }

        return false;
    }
}
?>