<?php

namespace App\Http\Controllers\Admin;

use App\Events\ReviewApproved;
use App\Events\ReviewDeleted;
use App\Http\Controllers\Controller;
use App\Models\Product;
use App\Models\ProductReview;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\StreamedResponse;

class ReviewController extends Controller
{
    /**
     * Display a listing of reviews.
     */
    public function index(Request $request): View
    {
        $query = ProductReview::with(['product:id,name,slug', 'user:id,name,email', 'order:id']);

        // Filter by product
        if ($request->filled('product_id')) {
            $query->where('product_id', $request->product_id);
        }

        // Filter by user
        if ($request->filled('user_id')) {
            $query->where('user_id', $request->user_id);
        }

        // Filter by approval status
        if ($request->filled('is_approved')) {
            $isApproved = filter_var($request->is_approved, FILTER_VALIDATE_BOOLEAN);
            $query->where('is_approved', $isApproved);
        } else {
            // Default: show pending reviews first
            $query->orderBy('is_approved', 'asc');
        }

        // Filter by rating
        if ($request->filled('rating')) {
            $query->where('rating', $request->rating);
        }

        // Search
        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('title', 'like', "%{$search}%")
                  ->orWhere('body', 'like', "%{$search}%")
                  ->orWhereHas('product', function ($q) use ($search) {
                      $q->where('name', 'like', "%{$search}%");
                  })
                  ->orWhereHas('user', function ($q) use ($search) {
                      $q->where('name', 'like', "%{$search}%")
                        ->orWhere('email', 'like', "%{$search}%");
                  });
            });
        }

        // Sorting
        $sortBy = $request->get('sort', 'created_at');
        $sortOrder = $request->get('order', 'desc');
        $sortOrder = in_array(strtolower($sortOrder), ['asc', 'desc']) ? strtolower($sortOrder) : 'desc';

        switch ($sortBy) {
            case 'rating':
                $query->orderBy('rating', $sortOrder);
                break;
            case 'product':
                $query->orderBy('product_id', $sortOrder);
                break;
            case 'user':
                $query->orderBy('user_id', $sortOrder);
                break;
            default:
                $query->orderBy('created_at', 'desc');
                break;
        }

        $reviews = $query->paginate(20)->withQueryString();
        $products = Product::select('id', 'name')->orderBy('name')->get();

        // Statistics
        $totalReviews = ProductReview::count();
        $approvedReviews = ProductReview::where('is_approved', true)->count();
        $pendingReviews = ProductReview::where('is_approved', false)->count();
        $avgRating = ProductReview::where('is_approved', true)->avg('rating');

        return view('admin.reviews.index', compact(
            'reviews',
            'products',
            'totalReviews',
            'approvedReviews',
            'pendingReviews',
            'avgRating'
        ));
    }

    /**
     * Approve or unapprove a review.
     */
    public function approve(Request $request, $id): JsonResponse|RedirectResponse
    {
        $review = ProductReview::findOrFail($id);
        $isApproved = filter_var($request->input('is_approved', true), FILTER_VALIDATE_BOOLEAN);

        try {
            DB::beginTransaction();

            $review->update(['is_approved' => $isApproved]);

            // Recalculate product rating
            $review->product->recalculateRating();

            DB::commit();

            // Fire event if approved
            if ($isApproved) {
                event(new ReviewApproved($review));
            }

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => true,
                    'message' => $isApproved ? 'Review approved successfully.' : 'Review unapproved successfully.',
                    'data' => $review->load(['product:id,name', 'user:id,name']),
                ]);
            }

            return redirect()->back()->with('success', $isApproved ? 'Review approved successfully.' : 'Review unapproved successfully.');
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Failed to approve review: ' . $e->getMessage());

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Failed to update review status.',
                ], 500);
            }

            return redirect()->back()->with('error', 'Failed to update review status.');
        }
    }

    /**
     * Delete a review.
     */
    public function destroy(Request $request, $id): JsonResponse|RedirectResponse
    {
        $review = ProductReview::findOrFail($id);

        try {
            DB::beginTransaction();

            $productId = $review->product_id;
            $review->delete();

            // Recalculate product rating
            $product = Product::find($productId);
            if ($product) {
                $product->recalculateRating();
            }

            DB::commit();

            // Fire event
            event(new ReviewDeleted($review));

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => true,
                    'message' => 'Review deleted successfully.',
                ]);
            }

            return redirect()->route('admin.reviews.index')->with('success', 'Review deleted successfully.');
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Failed to delete review: ' . $e->getMessage());

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Failed to delete review.',
                ], 500);
            }

            return redirect()->back()->with('error', 'Failed to delete review.');
        }
    }

    /**
     * Export reviews to CSV.
     */
    public function exportCsv(Request $request): StreamedResponse
    {
        $query = ProductReview::with(['product:id,name', 'user:id,name,email']);

        // Apply same filters as index
        if ($request->filled('product_id')) {
            $query->where('product_id', $request->product_id);
        }
        if ($request->filled('user_id')) {
            $query->where('user_id', $request->user_id);
        }
        if ($request->filled('is_approved')) {
            $isApproved = filter_var($request->is_approved, FILTER_VALIDATE_BOOLEAN);
            $query->where('is_approved', $isApproved);
        }
        if ($request->filled('rating')) {
            $query->where('rating', $request->rating);
        }

        $reviews = $query->orderBy('created_at', 'desc')->get();

        $filename = 'reviews_' . date('Y-m-d_His') . '.csv';

        return response()->streamDownload(function () use ($reviews) {
            $file = fopen('php://output', 'w');

            // CSV headers
            fputcsv($file, [
                'ID',
                'Product',
                'User',
                'Rating',
                'Title',
                'Body',
                'Approved',
                'Helpful Count',
                'Order ID',
                'IP Address',
                'Created At',
            ]);

            // CSV data
            foreach ($reviews as $review) {
                fputcsv($file, [
                    $review->id,
                    $review->product->name ?? 'N/A',
                    $review->user->name ?? 'Anonymous',
                    $review->rating,
                    $review->title ?? '',
                    $review->body ?? '',
                    $review->is_approved ? 'Yes' : 'No',
                    $review->helpful_count,
                    $review->order_id ?? '',
                    $review->ip_address ?? '',
                    $review->created_at->format('Y-m-d H:i:s'),
                ]);
            }

            fclose($file);
        }, $filename, [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => "attachment; filename=\"{$filename}\"",
        ]);
    }
}
