<?php
/**
 * Comprehensive Functional Test for Review & Rating System
 */

require_once __DIR__ . '/../database/Database.php';
require_once __DIR__ . '/../app/Models/User.php';
require_once __DIR__ . '/../app/Models/Store.php';
require_once __DIR__ . '/../app/Models/Product.php';
require_once __DIR__ . '/../app/Models/Order.php';
require_once __DIR__ . '/../app/Models/Review.php';
require_once __DIR__ . '/../app/Models/ReviewImage.php';
require_once __DIR__ . '/../app/Models/Report.php';
require_once __DIR__ . '/../app/Models/AdminAuditLog.php';
require_once __DIR__ . '/../app/Services/ReviewService.php';
require_once __DIR__ . '/../app/Services/AdminReviewService.php';

$db = Database::getInstance();
$reviewModel = new Review();
$reviewService = new ReviewService();
$adminReviewService = new AdminReviewService();

echo "=== CARGOO REVIEW & RATING SYSTEM FUNCTIONAL TEST ===" . PHP_EOL . PHP_EOL;

// 1. Setup Test Data
echo "[1] Setting up mock completed order..." . PHP_EOL;

// Find or create customer
$customer = $db->query("SELECT id FROM users ORDER BY id ASC LIMIT 1")->fetch();
if (!$customer) {
    $db->query("INSERT INTO users (username, email, password_hash, first_name, last_name, status, created_at, updated_at) VALUES ('testbuyer', 'buyer@cargoo.local', 'hash', 'Test', 'Buyer', 'active', NOW(), NOW())");
    $customerId = (int)$db->lastInsertId();
} else {
    $customerId = (int)$customer['id'];
}

// Find another customer (non-buyer)
$otherCustomer = $db->query("SELECT id FROM users WHERE id != {$customerId} LIMIT 1")->fetch();
$otherCustomerId = $otherCustomer ? (int)$otherCustomer['id'] : $customerId + 999;

// Find store & product
$product = $db->query("SELECT id, store_id, name, price FROM products LIMIT 1")->fetch();
if (!$product) {
    die("Error: No products in database to test with." . PHP_EOL);
}
$productId = (int)$product['id'];
$storeId = (int)$product['store_id'];

// Create completed test order and order item
$orderNo = 'TEST-REV-' . time();
$db->query("INSERT INTO orders (order_no, customer_id, store_id, total_amount, order_status, payment_status, payment_method, created_at, updated_at) 
            VALUES ('{$orderNo}', {$customerId}, {$storeId}, {$product['price']}, 'completed', 'confirmed', 'PromptPay', NOW(), NOW())");
$orderId = (int)$db->lastInsertId();

$db->query("INSERT INTO order_items (order_id, product_id, product_name, unit_price, quantity, subtotal, created_at)
            VALUES ({$orderId}, {$productId}, '{$product['name']}', {$product['price']}, 1, {$product['price']}, NOW())");
$orderItemId = (int)$db->lastInsertId();

echo "  ✓ Created completed Order #{$orderNo} (ID: {$orderId}, Item ID: {$orderItemId}) for Buyer ID: {$customerId}" . PHP_EOL;

// 2. Test Eligibility
echo PHP_EOL . "[2] Testing Review Eligibility..." . PHP_EOL;

// 2.1 Genuine buyer on completed order -> Should be ELIGIBLE
$checkBuyer = $reviewService->checkEligibility($customerId, $orderItemId);
assert($checkBuyer['eligible'] === true, "Buyer must be eligible");
echo "  ✓ Genuine buyer eligibility: PASS (Eligible = true)" . PHP_EOL;

// 2.2 Non-buyer on same order item -> Should be INELIGIBLE
$checkOther = $reviewService->checkEligibility($otherCustomerId, $orderItemId);
assert($checkOther['eligible'] === false, "Non-buyer must be ineligible");
echo "  ✓ Non-buyer eligibility: PASS (Eligible = false, '{$checkOther['message']}')" . PHP_EOL;

// 2.3 Buyer on pending/non-completed order -> Should be INELIGIBLE
$pendingOrderNo = 'TEST-PEND-' . time();
$db->query("INSERT INTO orders (order_no, customer_id, store_id, total_amount, order_status, payment_status, payment_method, created_at, updated_at) 
            VALUES ('{$pendingOrderNo}', {$customerId}, {$storeId}, {$product['price']}, 'preparing', 'confirmed', 'PromptPay', NOW(), NOW())");
$pendingOrderId = (int)$db->lastInsertId();
$db->query("INSERT INTO order_items (order_id, product_id, product_name, unit_price, quantity, subtotal, created_at)
            VALUES ({$pendingOrderId}, {$productId}, '{$product['name']}', {$product['price']}, 1, {$product['price']}, NOW())");
$pendingItemId = (int)$db->lastInsertId();

$checkPending = $reviewService->checkEligibility($customerId, $pendingItemId);
assert($checkPending['eligible'] === false, "Non-completed order must be ineligible");
echo "  ✓ Non-completed order eligibility: PASS (Eligible = false, '{$checkPending['message']}')" . PHP_EOL;

// 3. Test Review Submission & Duplicate Prevention
echo PHP_EOL . "[3] Testing Review Submission & Duplicate Prevention..." . PHP_EOL;

$submitResult = $reviewService->submitReview(
    $customerId,
    $orderItemId,
    5,
    "สินค้าคุณภาพดีเยี่ยม ตรงปก จัดส่งรวดเร็วมากครับ แนะนำร้านนี้เลย!",
    [],
    false
);
assert($submitResult['success'] === true, "Review submission must succeed");
$reviewId = (int)$submitResult['review_id'];
echo "  ✓ Review submitted successfully! Review ID: {$reviewId}" . PHP_EOL;

// Try to submit duplicate review for same item -> Should FAIL
$dupResult = $reviewService->submitReview(
    $customerId,
    $orderItemId,
    4,
    "พยายามส่งรีวิวซ้ำอีกรอบ"
);
assert($dupResult['success'] === false, "Duplicate review must fail");
echo "  ✓ Duplicate review prevention: PASS (Failed as expected: '{$dupResult['message']}')" . PHP_EOL;

// 4. Test Rating Recalculation
echo PHP_EOL . "[4] Testing Rating Aggregation..." . PHP_EOL;
$productRating = $reviewModel->getProductRatingBreakdown($productId);
assert($productRating['total_reviews'] >= 1, "Product total reviews must be >= 1");
assert($productRating['avg_rating'] > 0, "Product avg rating must be > 0");
echo "  ✓ Product Rating Breakdown: Avg = {$productRating['avg_rating']}★ (Total: {$productRating['total_reviews']} reviews, 5-Star: {$productRating['star_5']})" . PHP_EOL;

$storeRating = $reviewModel->getStoreRatingSummary($storeId);
assert($storeRating['total_reviews'] >= 1, "Store total reviews must be >= 1");
echo "  ✓ Store Rating Summary: Avg = {$storeRating['avg_rating']}★ (Total: {$storeRating['total_reviews']} reviews)" . PHP_EOL;

// 5. Test Review Edit & Update
echo PHP_EOL . "[5] Testing Review Edit & Update..." . PHP_EOL;
$updateResult = $reviewService->updateReview(
    $customerId,
    $reviewId,
    4,
    "แก้ไขข้อความ: สินค้าคุณภาพดี ใช้งานได้ตามปกติ (ปรับเป็น 4 ดาว)",
    [],
    [],
    true // anonymous
);
assert($updateResult['success'] === true, "Review update must succeed");
$updatedRev = $reviewModel->findDetailById($reviewId);
assert((int)$updatedRev['rating'] === 4, "Rating must be updated to 4");
assert((int)$updatedRev['is_anonymous'] === 1, "Is anonymous must be 1");
echo "  ✓ Review updated: Rating = {$updatedRev['rating']}★, Anonymous = {$updatedRev['is_anonymous']}" . PHP_EOL;

// 6. Test Review Reporting
echo PHP_EOL . "[6] Testing Review Reporting System..." . PHP_EOL;
$reportResult = $reviewService->reportReview($otherCustomerId, $reviewId, "มีข้อความไม่เหมาะสม", "ทดสอบการรายงานรีวิว");
assert($reportResult['success'] === true, "Review report must succeed");
echo "  ✓ Review reported successfully! Report ID: {$reportResult['report_id']}" . PHP_EOL;

// 7. Test Admin Moderation (Hide, Restore, Remove) & Audit Log
echo PHP_EOL . "[7] Testing Admin Moderation & Audit Logging..." . PHP_EOL;

$admin = $db->query("SELECT id FROM users ORDER BY id ASC LIMIT 1")->fetch();
$adminId = $admin ? (int)$admin['id'] : 1;

// 7.1 Hide Review
$hideResult = $adminReviewService->moderateReview($adminId, $reviewId, 'hide', 'ข้อความอยู่ระหว่างตรวจสอบความถูกต้อง');
assert($hideResult['success'] === true, "Hide review must succeed");
$hiddenRev = $reviewModel->findById($reviewId);
assert($hiddenRev['status'] === 'hidden', "Review status must be hidden");
echo "  ✓ Admin Hide Review: Status = {$hiddenRev['status']}" . PHP_EOL;

// 7.2 Restore Review
$restoreResult = $adminReviewService->moderateReview($adminId, $reviewId, 'restore', 'ตรวจสอบแล้วผ่านเกณฑ์');
assert($restoreResult['success'] === true, "Restore review must succeed");
$restoredRev = $reviewModel->findById($reviewId);
assert($restoredRev['status'] === 'active', "Review status must be active");
echo "  ✓ Admin Restore Review: Status = {$restoredRev['status']}" . PHP_EOL;

// 7.3 Remove Review
$removeResult = $adminReviewService->moderateReview($adminId, $reviewId, 'remove', 'ละเมิดนโยบายชุมชน');
assert($removeResult['success'] === true, "Remove review must succeed");
$removedRev = $reviewModel->findById($reviewId);
assert($removedRev['status'] === 'removed', "Review status must be removed");
echo "  ✓ Admin Remove Review: Status = {$removedRev['status']}" . PHP_EOL;

// 8. Clean up test order & review
echo PHP_EOL . "[8] Cleaning up test records..." . PHP_EOL;
$db->query("DELETE FROM review_images WHERE review_id = {$reviewId}");
$db->query("DELETE FROM reviews WHERE id = {$reviewId}");
$db->query("DELETE FROM reports WHERE report_type = 'review' AND target_id = {$reviewId}");
$db->query("DELETE FROM order_items WHERE id IN ({$orderItemId}, {$pendingItemId})");
$db->query("DELETE FROM orders WHERE id IN ({$orderId}, {$pendingOrderId})");
$reviewModel->recalculateProductRating($productId);
$reviewModel->recalculateStoreRating($storeId);
echo "  ✓ Cleaned up test orders and temporary review data." . PHP_EOL;

echo PHP_EOL . "🎉 ALL 8 REVIEW & RATING SYSTEM FUNCTIONAL TESTS PASSED PERFECTLY! 🎉" . PHP_EOL;
