<?php

namespace App\Http\Controllers\Api;

use App\Enums\ReservationStatus;
use App\Http\Controllers\Controller;
use App\Models\CaptainReview;
use App\Models\CaptainReviewImage;
use App\Models\Reservation;
use App\Models\User;
use App\Services\ImageService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class CaptainReviewController extends Controller
{
    /**
     * Kaptan yorumlarını getir (public)
     */
    public function captainReviews(User $captain): JsonResponse
    {
        $reviews = CaptainReview::where('captain_id', $captain->id)
            ->with([
                'user:id,name,avatar',
                'images',
                'reservation:id,listing_id',
                'reservation.listing:id,title',
            ])
            ->latest()
            ->paginate(10);

        $stats = $this->getCaptainStats($captain->id);

        return response()->json([
            'reviews' => $reviews,
            'stats' => $stats,
        ]);
    }

    /**
     * Yorum oluştur
     */
    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'reservation_id' => 'required|integer|exists:reservations,id',
            'rating' => 'required|integer|min:1|max:5',
            'comment' => 'nullable|string|max:1000',
            'images' => 'nullable|array|max:5',
            'images.*' => 'image|mimes:jpeg,png,jpg,webp|max:5120',
        ]);

        $reservation = Reservation::with('listing.owner')->findOrFail($validated['reservation_id']);

        if ($reservation->user_id !== $request->user()->id) {
            return response()->json(['message' => 'Bu rezervasyon size ait değil.'], 403);
        }

        if ($reservation->status !== ReservationStatus::COMPLETED) {
            return response()->json(['message' => 'Sadece tamamlanmış rezervasyonlara yorum yapabilirsiniz.'], 422);
        }

        if ($reservation->review) {
            return response()->json(['message' => 'Bu rezervasyona zaten yorum yapmışsınız.'], 422);
        }

        $captainId = $reservation->listing->user_id;

        $review = DB::transaction(function () use ($validated, $request, $captainId) {
            $review = CaptainReview::create([
                'user_id' => $request->user()->id,
                'captain_id' => $captainId,
                'reservation_id' => $validated['reservation_id'],
                'rating' => $validated['rating'],
                'comment' => $validated['comment'] ?? null,
            ]);

            if ($request->hasFile('images')) {
                $imageService = app(ImageService::class);
                foreach ($request->file('images') as $image) {
                    $path = $imageService->compress(
                        $image,
                        'reviews/' . $review->id,
                        ImageService::PRESET_REVIEW,
                    );
                    CaptainReviewImage::create([
                        'review_id' => $review->id,
                        'image_path' => $path,
                    ]);
                }
            }

            return $review;
        });

        $review->load(['images', 'user:id,name,avatar']);

        return response()->json([
            'message' => 'Yorumunuz başarıyla eklendi.',
            'review' => $review,
        ], 201);
    }

    /**
     * Yorumu güncelle
     */
    public function update(Request $request, CaptainReview $review): JsonResponse
    {
        if ($review->user_id !== $request->user()->id) {
            return response()->json(['message' => 'Bu yorum size ait değil.'], 403);
        }

        $validated = $request->validate([
            'rating' => 'sometimes|integer|min:1|max:5',
            'comment' => 'nullable|string|max:1000',
            'images' => 'nullable|array|max:5',
            'images.*' => 'image|mimes:jpeg,png,jpg,webp|max:5120',
            'remove_image_ids' => 'nullable|array',
            'remove_image_ids.*' => 'integer|exists:captain_review_images,id',
        ]);

        DB::transaction(function () use ($validated, $request, $review) {
            $review->update([
                'rating' => $validated['rating'] ?? $review->rating,
                'comment' => array_key_exists('comment', $validated) ? $validated['comment'] : $review->comment,
            ]);

            if (!empty($validated['remove_image_ids'])) {
                $imagesToRemove = $review->images()->whereIn('id', $validated['remove_image_ids'])->get();
                foreach ($imagesToRemove as $img) {
                    Storage::disk('public')->delete($img->image_path);
                    $img->delete();
                }
            }

            if ($request->hasFile('images')) {
                $imageService = app(ImageService::class);
                foreach ($request->file('images') as $image) {
                    $path = $imageService->compress(
                        $image,
                        'reviews/' . $review->id,
                        ImageService::PRESET_REVIEW,
                    );
                    CaptainReviewImage::create([
                        'review_id' => $review->id,
                        'image_path' => $path,
                    ]);
                }
            }
        });

        $review->load(['images', 'user:id,name,avatar']);

        return response()->json([
            'message' => 'Yorum güncellendi.',
            'review' => $review,
        ]);
    }

    private function getCaptainStats(int $captainId): array
    {
        $reviews = CaptainReview::where('captain_id', $captainId);
        $totalCount = $reviews->count();

        if ($totalCount === 0) {
            return [
                'average_rating' => 0,
                'total_count' => 0,
                'distribution' => [5 => 0, 4 => 0, 3 => 0, 2 => 0, 1 => 0],
            ];
        }

        $average = round($reviews->avg('rating'), 1);

        $distribution = CaptainReview::where('captain_id', $captainId)
            ->select('rating', DB::raw('count(*) as count'))
            ->groupBy('rating')
            ->pluck('count', 'rating')
            ->toArray();

        $fullDistribution = [];
        for ($i = 5; $i >= 1; $i--) {
            $fullDistribution[$i] = $distribution[$i] ?? 0;
        }

        return [
            'average_rating' => $average,
            'total_count' => $totalCount,
            'distribution' => $fullDistribution,
        ];
    }
}
