<?php
// app/Http\Controllers\Api\Customer\ReviewController.php
namespace App\Http\Controllers\Api\Customer;

use App\Http\Controllers\Controller;
use App\Http\Requests\Api\Customer\ReviewRequest;
use App\Http\Requests\Api\Customer\UpdateReviewRequest;
use App\Http\Resources\Api\Customer\ReviewResource;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Review;
use App\Models\Menu;
use App\Traits\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ReviewController extends Controller
{
    use ApiResponse;

    /**
     * Add review for order item
     * POST /api/customer/orders/{order_id}/items/{item_id}/review
     */
    public function store(ReviewRequest $request, $orderId, $itemId): JsonResponse
    {
        DB::beginTransaction();
        
        try {
            $user = $request->user();
            
            $orderItem = OrderItem::whereHas('order', function ($q) use ($user, $orderId) {
                $q->where('customer_id', $user->id)
                  ->where('id', $orderId)
                  ->where('status', 'completed');
            })->find($itemId);

            if (!$orderItem) {
                return $this->errorResponse('Item pesanan tidak ditemukan atau belum selesai', 404);
            }

            if ($orderItem->rating) {
                return $this->errorResponse('Item sudah direview', 400);
            }

            // Add review to order item
            $orderItem->update([
                'rating' => $request->rating,
                'review_comment' => $request->comment,
                'reviewed_at' => now(),
            ]);

            // Create separate review record
            $review = Review::create([
                'order_id' => $orderId,
                'customer_id' => $user->id,
                'menu_id' => $orderItem->menu_id,
                'rating' => $request->rating,
                'comment' => $request->comment,
                'is_approved' => true, // Auto-approve customer reviews
            ]);

            // Update menu average rating
            $this->updateMenuRating($orderItem->menu_id);

            DB::commit();

            return $this->successResponse(
                new ReviewResource($review->load(['menu', 'customer'])),
                '⭐ Review berhasil ditambahkan. Terima kasih atas feedbacknya!',
                201
            );

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->errorResponse('Gagal menambahkan review: ' . $e->getMessage(), 500);
        }
    }

    /**
     * Update review
     * PUT /api/customer/reviews/{id}
     */
    public function update(UpdateReviewRequest $request, $id): JsonResponse
    {
        DB::beginTransaction();
        
        try {
            $user = $request->user();
            
            $review = Review::where('customer_id', $user->id)
                          ->find($id);

            if (!$review) {
                return $this->errorResponse('Review tidak ditemukan', 404);
            }

            // Check if review can be edited (within 24 hours)
            if ($review->created_at->addHours(24)->isPast()) {
                return $this->errorResponse('Review hanya dapat diedit dalam 24 jam pertama', 400);
            }

            $oldRating = $review->rating;
            
            // Update review
            $review->update([
                'rating' => $request->rating ?? $review->rating,
                'comment' => $request->comment ?? $review->comment,
            ]);

            // Update corresponding order item
            $orderItem = OrderItem::where('order_id', $review->order_id)
                                 ->where('menu_id', $review->menu_id)
                                 ->first();
            
            if ($orderItem) {
                $orderItem->update([
                    'rating' => $review->rating,
                    'review_comment' => $review->comment,
                ]);
            }

            // Update menu rating if rating changed
            if ($oldRating != $review->rating) {
                $this->updateMenuRating($review->menu_id);
            }

            DB::commit();

            return $this->successResponse(
                new ReviewResource($review->fresh(['menu', 'customer'])),
                '✅ Review berhasil diperbarui'
            );

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->errorResponse('Gagal memperbarui review: ' . $e->getMessage(), 500);
        }
    }

    /**
     * Delete review
     * DELETE /api/customer/reviews/{id}
     */
    public function destroy(Request $request, $id): JsonResponse
    {
        DB::beginTransaction();
        
        try {
            $user = $request->user();
            
            $review = Review::where('customer_id', $user->id)
                          ->find($id);

            if (!$review) {
                return $this->errorResponse('Review tidak ditemukan', 404);
            }

            // Check if review can be deleted (within 24 hours)
            if ($review->created_at->addHours(24)->isPast()) {
                return $this->errorResponse('Review hanya dapat dihapus dalam 24 jam pertama', 400);
            }

            $menuId = $review->menu_id;
            
            // Remove rating from order item
            $orderItem = OrderItem::where('order_id', $review->order_id)
                                 ->where('menu_id', $review->menu_id)
                                 ->first();
            
            if ($orderItem) {
                $orderItem->update([
                    'rating' => null,
                    'review_comment' => null,
                    'reviewed_at' => null,
                ]);
            }

            // Delete review
            $review->delete();

            // Update menu rating
            $this->updateMenuRating($menuId);

            DB::commit();

            return $this->successResponse(
                null,
                '🗑️ Review berhasil dihapus'
            );

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->errorResponse('Gagal menghapus review: ' . $e->getMessage(), 500);
        }
    }

    /**
     * Get customer reviews
     * GET /api/customer/reviews
     */
    public function index(Request $request): JsonResponse
    {
        $user = $request->user();
        
        $reviews = Review::with(['menu.category', 'order'])
                        ->where('customer_id', $user->id)
                        ->when($request->menu_id, function ($q, $menuId) {
                            return $q->where('menu_id', $menuId);
                        })
                        ->when($request->rating, function ($q, $rating) {
                            return $q->where('rating', $rating);
                        })
                        ->when($request->date_from && $request->date_to, function ($q) use ($request) {
                            return $q->whereBetween('created_at', [
                                $request->date_from . ' 00:00:00',
                                $request->date_to . ' 23:59:59'
                            ]);
                        })
                        ->orderBy('created_at', 'desc')
                        ->paginate($request->per_page ?? 10);

        // Review statistics
        $stats = [
            'total' => Review::where('customer_id', $user->id)->count(),
            'average_rating' => round(Review::where('customer_id', $user->id)->avg('rating') ?? 0, 1),
            'rating_distribution' => [
                '5_stars' => Review::where('customer_id', $user->id)->where('rating', 5)->count(),
                '4_stars' => Review::where('customer_id', $user->id)->where('rating', 4)->count(),
                '3_stars' => Review::where('customer_id', $user->id)->where('rating', 3)->count(),
                '2_stars' => Review::where('customer_id', $user->id)->where('rating', 2)->count(),
                '1_star' => Review::where('customer_id', $user->id)->where('rating', 1)->count(),
            ],
        ];

        return $this->successResponse([
            'reviews' => ReviewResource::collection($reviews),
            'pagination' => [
                'total' => $reviews->total(),
                'per_page' => $reviews->perPage(),
                'current_page' => $reviews->currentPage(),
                'last_page' => $reviews->lastPage(),
                'from' => $reviews->firstItem(),
                'to' => $reviews->lastItem(),
            ],
            'statistics' => $stats,
            'filters' => [
                'menu_id' => $request->menu_id,
                'rating' => $request->rating,
                'date_from' => $request->date_from,
                'date_to' => $request->date_to,
            ]
        ], 'Review berhasil diambil');
    }

    /**
     * Get reviews for a menu (Public)
     * GET /api/customer/menu/{menu_id}/reviews
     */
    public function getMenuReviews(Request $request, $menuId): JsonResponse
    {
        $menu = Menu::find($menuId);
        
        if (!$menu) {
            return $this->errorResponse('Menu tidak ditemukan', 404);
        }

        $reviews = Review::with(['customer:id,name'])
                        ->where('menu_id', $menuId)
                        ->where('is_approved', true)
                        ->when($request->rating, function ($q, $rating) {
                            return $q->where('rating', $rating);
                        })
                        ->orderBy('created_at', 'desc')
                        ->paginate($request->per_page ?? 10);

        // Menu rating statistics
        $totalReviews = Review::where('menu_id', $menuId)->where('is_approved', true)->count();
        $averageRating = round(Review::where('menu_id', $menuId)->where('is_approved', true)->avg('rating') ?? 0, 1);
        
        $ratingDistribution = [];
        for ($i = 5; $i >= 1; $i--) {
            $count = Review::where('menu_id', $menuId)
                          ->where('is_approved', true)
                          ->where('rating', $i)
                          ->count();
            $ratingDistribution[$i . '_stars'] = [
                'count' => $count,
                'percentage' => $totalReviews > 0 ? round(($count / $totalReviews) * 100, 1) : 0,
            ];
        }

        return $this->successResponse([
            'menu' => [
                'id' => $menu->id,
                'name' => $menu->name,
                'image_url' => $menu->image_url,
                'average_rating' => $averageRating,
                'total_reviews' => $totalReviews,
                'rating_distribution' => $ratingDistribution,
            ],
            'reviews' => ReviewResource::collection($reviews),
            'pagination' => [
                'total' => $reviews->total(),
                'per_page' => $reviews->perPage(),
                'current_page' => $reviews->currentPage(),
                'last_page' => $reviews->lastPage(),
                'from' => $reviews->firstItem(),
                'to' => $reviews->lastItem(),
            ],
            'filters' => [
                'rating' => $request->rating,
            ]
        ], 'Review menu berhasil diambil');
    }

    /**
     * Get reviews that can be added (for completed orders)
     * GET /api/customer/reviews/pending
     */
    public function pendingReviews(Request $request): JsonResponse
    {
        $user = $request->user();
        
        // Get completed orders with items that haven't been reviewed
        $pendingReviews = OrderItem::with(['menu', 'order'])
            ->whereHas('order', function ($q) use ($user) {
                $q->where('customer_id', $user->id)
                  ->where('status', 'completed');
            })
            ->whereNull('rating')
            ->where('created_at', '>=', now()->subDays(30)) // Within last 30 days
            ->orderBy('created_at', 'desc')
            ->get()
            ->groupBy('order_id');

        $orders = [];
        foreach ($pendingReviews as $orderId => $items) {
            $order = $items->first()->order;
            $orders[] = [
                'order_id' => $orderId,
                'order_number' => $order->order_number,
                'order_date' => $order->created_at->format('Y-m-d H:i:s'),
                'items' => $items->map(function ($item) {
                    return [
                        'item_id' => $item->id,
                        'menu_id' => $item->menu_id,
                        'menu_name' => $item->menu->name,
                        'menu_image' => $item->menu->image_url,
                        'quantity' => $item->quantity,
                        'can_review' => true,
                    ];
                }),
            ];
        }

        return $this->successResponse([
            'pending_reviews' => $orders,
            'total_pending' => count($orders),
            'total_items' => $pendingReviews->flatten()->count(),
            'message' => count($orders) > 0 
                ? 'Anda memiliki ' . $pendingReviews->flatten()->count() . ' item yang bisa direview'
                : 'Tidak ada item yang perlu direview',
        ], 'Review yang dapat ditambahkan');
    }

    /**
     * Get review summary for customer
     * GET /api/customer/reviews/summary
     */
    public function summary(Request $request): JsonResponse
    {
        $user = $request->user();
        
        $totalReviews = Review::where('customer_id', $user->id)->count();
        $averageRating = round(Review::where('customer_id', $user->id)->avg('rating') ?? 0, 1);
        
        $recentReviews = Review::with('menu')
            ->where('customer_id', $user->id)
            ->latest()
            ->limit(3)
            ->get();

        $mostReviewedMenu = Review::where('customer_id', $user->id)
            ->selectRaw('menu_id, COUNT(*) as review_count, AVG(rating) as avg_rating')
            ->groupBy('menu_id')
            ->orderBy('review_count', 'desc')
            ->with('menu')
            ->first();

        return $this->successResponse([
            'summary' => [
                'total_reviews' => $totalReviews,
                'average_rating' => $averageRating,
                'rating_description' => $this->getRatingDescription($averageRating),
                'review_level' => $this->getReviewLevel($totalReviews),
            ],
            'recent_reviews' => ReviewResource::collection($recentReviews),
            'most_reviewed_menu' => $mostReviewedMenu ? [
                'menu_id' => $mostReviewedMenu->menu_id,
                'menu_name' => $mostReviewedMenu->menu->name,
                'review_count' => $mostReviewedMenu->review_count,
                'average_rating' => round($mostReviewedMenu->avg_rating, 1),
            ] : null,
            'achievements' => $this->getReviewAchievements($user->id),
        ], 'Ringkasan review berhasil diambil');
    }

    // ==================== HELPER METHODS ====================

    /**
     * Update menu average rating
     */
    private function updateMenuRating($menuId): void
    {
        $menu = Menu::find($menuId);
        if (!$menu) return;

        $approvedReviews = Review::where('menu_id', $menuId)
                                ->where('is_approved', true)
                                ->get();

        if ($approvedReviews->count() > 0) {
            $averageRating = $approvedReviews->avg('rating');
            $menu->update([
                // You might want to add average_rating column to menus table
                // 'average_rating' => round($averageRating, 1),
                // 'review_count' => $approvedReviews->count(),
            ]);
        }
    }

    /**
     * Get rating description
     */
    private function getRatingDescription($rating): string
    {
        if ($rating >= 4.5) return '⭐ Sangat Baik';
        if ($rating >= 4.0) return '👍 Baik';
        if ($rating >= 3.0) return '😊 Cukup';
        if ($rating >= 2.0) return '😐 Kurang';
        return '👎 Tidak Baik';
    }

    /**
     * Get review level based on total reviews
     */
    private function getReviewLevel($totalReviews): array
    {
        if ($totalReviews >= 50) return ['level' => 'Expert Reviewer', 'icon' => '🏆'];
        if ($totalReviews >= 25) return ['level' => 'Active Reviewer', 'icon' => '⭐'];
        if ($totalReviews >= 10) return ['level' => 'Regular Reviewer', 'icon' => '👍'];
        if ($totalReviews >= 1) return ['level' => 'Beginner Reviewer', 'icon' => '👶'];
        return ['level' => 'No Reviews Yet', 'icon' => '📝'];
    }

    /**
     * Get review achievements
     */
    private function getReviewAchievements($userId): array
    {
        $achievements = [];

        $reviewCount = Review::where('customer_id', $userId)->count();
        $fiveStarCount = Review::where('customer_id', $userId)->where('rating', 5)->count();
        $variedReviewCount = Review::where('customer_id', $userId)
                                  ->select('menu_id')
                                  ->distinct()
                                  ->count();

        // First review achievement
        if ($reviewCount >= 1) {
            $achievements[] = [
                'name' => 'Review Pertama',
                'description' => 'Memberikan review pertama',
                'icon' => '🥇',
                'unlocked' => true,
                'progress' => 100,
            ];
        }

        // 5-star reviewer
        if ($fiveStarCount >= 10) {
            $achievements[] = [
                'name' => 'Kritikus Handal',
                'description' => 'Memberikan 10 review bintang 5',
                'icon' => '⭐',
                'unlocked' => true,
                'progress' => 100,
            ];
        } elseif ($fiveStarCount > 0) {
            $achievements[] = [
                'name' => 'Kritikus Handal',
                'description' => 'Memberikan 10 review bintang 5',
                'icon' => '⭐',
                'unlocked' => false,
                'progress' => ($fiveStarCount / 10) * 100,
            ];
        }

        // Variety reviewer
        if ($variedReviewCount >= 5) {
            $achievements[] = [
                'name' => 'Pencicip Berpengalaman',
                'description' => 'Review 5 menu berbeda',
                'icon' => '🍽️',
                'unlocked' => true,
                'progress' => 100,
            ];
        } elseif ($variedReviewCount > 0) {
            $achievements[] = [
                'name' => 'Pencicip Berpengalaman',
                'description' => 'Review 5 menu berbeda',
                'icon' => '🍽️',
                'unlocked' => false,
                'progress' => ($variedReviewCount / 5) * 100,
            ];
        }

        return $achievements;
    }

    /**
     * Bulk add reviews for multiple items
     * POST /api/customer/orders/{order_id}/reviews/bulk
     */
    public function bulkStore(Request $request, $orderId): JsonResponse
    {
        $request->validate([
            'reviews' => 'required|array|min:1',
            'reviews.*.item_id' => 'required|integer',
            'reviews.*.rating' => 'required|integer|min:1|max:5',
            'reviews.*.comment' => 'nullable|string|max:500',
        ]);

        $user = $request->user();
        
        $order = Order::where('customer_id', $user->id)
                     ->where('id', $orderId)
                     ->where('status', 'completed')
                     ->first();

        if (!$order) {
            return $this->errorResponse('Pesanan tidak ditemukan atau belum selesai', 404);
        }

        DB::beginTransaction();
        
        try {
            $createdReviews = [];
            
            foreach ($request->reviews as $reviewData) {
                $orderItem = OrderItem::where('order_id', $orderId)
                                     ->where('id', $reviewData['item_id'])
                                     ->first();

                if (!$orderItem || $orderItem->rating) {
                    continue; // Skip if item not found or already reviewed
                }

                // Update order item
                $orderItem->update([
                    'rating' => $reviewData['rating'],
                    'review_comment' => $reviewData['comment'] ?? null,
                    'reviewed_at' => now(),
                ]);

                // Create review record
                $review = Review::create([
                    'order_id' => $orderId,
                    'customer_id' => $user->id,
                    'menu_id' => $orderItem->menu_id,
                    'rating' => $reviewData['rating'],
                    'comment' => $reviewData['comment'] ?? null,
                    'is_approved' => true,
                ]);

                $createdReviews[] = $review;
            }

            // Update menu ratings
            foreach ($createdReviews as $review) {
                $this->updateMenuRating($review->menu_id);
            }

            DB::commit();

            return $this->successResponse(
                ReviewResource::collection(collect($createdReviews)->load(['menu', 'customer'])),
                '✅ ' . count($createdReviews) . ' review berhasil ditambahkan',
                201
            );

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->errorResponse('Gagal menambahkan review: ' . $e->getMessage(), 500);
        }
    }
}