<?php

namespace App\Models;

use App\Core\Model;

class Review extends Model
{
    protected string $table = 'reviews';
    protected string $primaryKey = 'review_id';

    /**
     * Create a new review
     */
    public function createReview(array $data): ?int
    {
        // Check if user already reviewed this product
        $existing = $this->getByUser($data['user_id'], $data['product_id']);
        if ($existing) {
            return null; // User already reviewed this product
        }

        return $this->create([
            'product_id' => $data['product_id'],
            'user_id' => $data['user_id'],
            'rating' => $data['rating'],
            'comment' => $data['comment'] ?? null,
            'is_approved' => $data['is_approved'] ?? true
        ]);
    }

    /**
     * Get all reviews for a product
     */
    public function getByProduct(int $productId, bool $approvedOnly = true): array
    {
        $sql = "SELECT r.*, u.full_name, u.email
                FROM {$this->table} r
                INNER JOIN users u ON r.user_id = u.user_id";
        
        if ($approvedOnly) {
            $sql .= " WHERE r.product_id = ? AND r.is_approved = TRUE";
        } else {
            $sql .= " WHERE r.product_id = ?";
        }
        
        $sql .= " ORDER BY r.created_at DESC";
        
        return $this->query($sql, [$productId]);
    }

    /**
     * Get review by specific user for a product
     */
    public function getByUser(int $userId, int $productId): ?array
    {
        $sql = "SELECT * FROM {$this->table} 
                WHERE user_id = ? AND product_id = ?";
        return $this->queryOne($sql, [$userId, $productId]);
    }

    /**
     * Get review with user details
     */
    public function findWithUser(int $reviewId): ?array
    {
        $sql = "SELECT r.*, u.full_name, u.email
                FROM {$this->table} r
                INNER JOIN users u ON r.user_id = u.user_id
                WHERE r.review_id = ?";
        return $this->queryOne($sql, [$reviewId]);
    }

    /**
     * Update a review
     */
    public function updateReview(int $reviewId, array $data): bool
    {
        $updateData = [];
        
        if (isset($data['rating'])) {
            $updateData['rating'] = $data['rating'];
        }
        if (isset($data['comment'])) {
            $updateData['comment'] = $data['comment'];
        }
        if (isset($data['is_approved'])) {
            $updateData['is_approved'] = $data['is_approved'];
        }
        
        if (empty($updateData)) {
            return false;
        }

        return $this->update($reviewId, $updateData);
    }

    /**
     * Delete a review
     */
    public function deleteReview(int $reviewId): bool
    {
        return $this->delete($reviewId);
    }

    /**
     * Get average rating for a product
     */
    public function getAverageRating(int $productId): float
    {
        $sql = "SELECT COALESCE(AVG(rating), 0.00) as avg_rating
                FROM {$this->table}
                WHERE product_id = ? AND is_approved = TRUE";
        $result = $this->queryOne($sql, [$productId]);
        return round((float)$result['avg_rating'], 2);
    }

    /**
     * Get review count for a product
     */
    public function getReviewCount(int $productId): int
    {
        return $this->count([
            'product_id' => $productId,
            'is_approved' => true
        ]);
    }

    /**
     * Update product's rating and review count
     * This is called automatically by database triggers,
     * but can also be called manually if needed
     */
    public function updateProductRating(int $productId): void
    {
        // Call the PostgreSQL function
        $sql = "SELECT update_product_rating(?)";
        $this->execute($sql, [$productId]);
    }

    /**
     * Get rating distribution for a product (useful for charts)
     */
    public function getRatingDistribution(int $productId): array
    {
        $sql = "SELECT rating, COUNT(*) as count
                FROM {$this->table}
                WHERE product_id = ? AND is_approved = TRUE
                GROUP BY rating
                ORDER BY rating DESC";
        
        $results = $this->query($sql, [$productId]);
        
        // Initialize all ratings with 0
        $distribution = [
            5 => 0,
            4 => 0,
            3 => 0,
            2 => 0,
            1 => 0
        ];
        
        // Fill in actual counts
        foreach ($results as $row) {
            $distribution[$row['rating']] = (int)$row['count'];
        }
        
        return $distribution;
    }

    /**
     * Get recent reviews across all products (for admin dashboard)
     */
    public function getRecent(int $limit = 10, bool $approvedOnly = false): array
    {
        $sql = "SELECT r.*, u.full_name, u.email, p.name as product_name
                FROM {$this->table} r
                INNER JOIN users u ON r.user_id = u.user_id
                INNER JOIN products p ON r.product_id = p.product_id";
        
        if ($approvedOnly) {
            $sql .= " WHERE r.is_approved = TRUE";
        }
        
        $sql .= " ORDER BY r.created_at DESC LIMIT ?";
        
        return $this->query($sql, [$limit]);
    }

    /**
     * Check if user can review (has purchased the product)
     * This is optional - you might want to allow reviews only from buyers
     */
    public function userCanReview(int $userId, int $productId): bool
    {
        // Check if user already reviewed
        $existing = $this->getByUser($userId, $productId);
        if ($existing) {
            return false;
        }

        // Optional: Check if user has purchased this product
        // For now, we'll allow any authenticated user to review
        return true;
        
        /* Uncomment this to require purchase before review:
        $sql = "SELECT COUNT(*) as count 
                FROM order_items oi
                INNER JOIN orders o ON oi.order_id = o.order_id
                WHERE o.user_id = ? AND oi.product_id = ? AND o.status = 'completed'";
        $result = $this->queryOne($sql, [$userId, $productId]);
        return $result && $result['count'] > 0;
        */
    }

    /**
     * Toggle review approval status (admin function)
     */
    public function toggleApproval(int $reviewId): bool
    {
        $review = $this->find($reviewId);
        if (!$review) {
            return false;
        }

        return $this->update($reviewId, [
            'is_approved' => !$review['is_approved']
        ]);
    }

    /**
     * Get all reviews by a specific user
     */
    public function getUserReviews(int $userId, int $limit = 50): array
    {
        $sql = "SELECT r.*, p.name as product_name, p.image_url as product_image
                FROM {$this->table} r
                INNER JOIN products p ON r.product_id = p.product_id
                WHERE r.user_id = ?
                ORDER BY r.created_at DESC
                LIMIT ?";
        
        return $this->query($sql, [$userId, $limit]);
    }
}

