<?php

namespace App\Http\Controllers\Api\Provider;

use App\Enums\BookingItemStatus;
use App\Enums\BookingStatus;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Api\Traits\ApiResponse;
use App\Http\Resources\BookingItemResource;
use App\Http\Resources\BookingResource;
use App\Models\Booking;
use App\Models\BookingItem;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use OpenApi\Annotations as OA;

class BookingController extends Controller
{
    use ApiResponse;

    /**
     * @OA\Get(
     *     path="/api/provider/bookings",
     *     summary="Get a list of bookings for the authenticated provider",
     *     tags={"Provider Bookings"},
     *     security={{"bearerAuth":{}}},
     *     @OA\Parameter(
     *         name="Accept-Language",
     *         in="header",
     *         required=false,
     *         description="Language preference (e.g., 'en', 'ar')",
     *         @OA\Schema(type="string", enum={"en", "ar"}, default="en")
     *     ),
     *     @OA\Parameter(
     *         name="search",
     *         in="query",
     *         description="Search by booking ID or user name or email or phone",
     *         @OA\Schema(type="string")
     *     ),
     *     @OA\Parameter(
     *         name="status",
     *         in="query",
     *         description="Filter by booking status",
     *         @OA\Schema(type="string", enum={"pending", "confirmed", "declined"})
     *     ),
     *    @OA\Parameter(
     *         name="from_date",
     *         in="query",
     *         description="Filter by booking start date",
     *         @OA\Schema(type="string", format="date")
     *     ),
     *    @OA\Parameter(
     *         name="to_date",
     *         in="query",
     *         description="Filter by booking end date",
     *         @OA\Schema(type="string", format="date")
     *     ),
     *    @OA\Parameter(
     *         name="page",
     *         in="query",
     *         description="Pagination page number",
     *         @OA\Schema(type="integer", default=1)
     *     ),
     *     @OA\Parameter(
     *         name="per_page",
     *         in="query",
     *         description="Number of items per page",
     *         @OA\Schema(type="integer", default=10)
     *     ),
     *     @OA\Parameter(
     *         name="is_transfered",
     *         in="query",
     *         description="Filter by transfer status",
     *         @OA\Schema(type="boolean")
     *     ),
     *     @OA\Response(
     *         response=200,
     *         description="A list of bookings",
     *         @OA\JsonContent(
     *             @OA\Property(property="success", type="boolean", example=true),
     *             @OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/BookingItemResource")),
     *             @OA\Property(property="message", type="string", example="Bookings retrieved successfully.")
     *         )
     *     ),
     *     @OA\Response(
     *         response=401,
     *         description="Unauthenticated"
     *     )
     * )
     */
    public function index(Request $request)
    {
        $request->validate([
            'search' => 'sometimes|string',
            'status' => 'sometimes|in:' . implode(',', array_map(fn($status) => $status->value, BookingItemStatus::cases())),
            // to_date can be null if from_date is provided
            "from_date" => ["sometimes", "date", $request->input("to_date") ? "before_or_equal:to_date" : null],
            "to_date" => ["sometimes", "date", $request->input("from_date") ? "after_or_equal:from_date" : null],
            'page' => ['sometimes', 'integer'],
            'per_page' => ['sometimes', 'integer'],
            'is_transfered' => ['sometimes', 'boolean'],
        ]);
        /** @var \App\Models\ServiceProvider $provider */
        $provider = Auth::user();
        $bookings = $provider->bookingItems()
            ->whereHas('booking', fn($query) => $query->where('status', BookingStatus::PAID))
            ->with(['user', 'product.media'])
            ->when($request->from_date && $request->to_date, function ($query) use ($request) {
                $query->whereBetween('service_date', [$request->from_date, $request->to_date]);
            })
            ->when($request->from_date && !$request->to_date, function ($query) use ($request) {
                $query->whereDate('service_date', '>=', $request->from_date);
            })
            ->when(!$request->from_date && $request->to_date, function ($query) use ($request) {
                $query->whereDate('service_date', '<=', $request->to_date);
            })
            ->when($request->search, function ($query, $search) {
                $query->where(function ($q) use ($search) {
                    $q->where('booking_id', $search)
                        ->orWhereHas('user', function ($query) use ($search) {
                            $query->where('first_name', 'like', "%{$search}%")
                                ->orWhere('last_name', 'like', "%{$search}%")
                                ->orWhere(DB::raw("CONCAT(first_name, ' ', last_name)"), 'like', "%{$search}%")
                                ->orWhere('email', 'like', "%{$search}%")
                                ->orWhere('phone', 'like', "%{$search}%");
                        })
                        ->orWhereHas('product', function ($query) use ($search) {
                            $query->where('name_' . app()->getLocale(), 'like', "%{$search}%");
                        });
                });
            })
            ->when($request->status, function ($query, $status) {
                $query->where('status', $status);
            })
            ->when($request->has('is_transfered'), function ($query) use ($request) {
                $query->where('is_transfered', $request->is_transfered);
            })
            ->paginate($request->get('per_page', 10), ['*'], 'page', $request->get('page', 1));

        return $this->successResponse(BookingItemResource::collection($bookings), __('messages.bookings_retrieved_successfully'));
    }

    /**
     * @OA\Get(
     *     path="/api/provider/bookings/{id}",
     *     summary="Get a specific booking for the authenticated provider",
     *     tags={"Provider Bookings"},
     *     security={{"bearerAuth":{}}},
     *     @OA\Parameter(
     *         name="Accept-Language",
     *         in="header",
     *         required=false,
     *         description="Language preference (e.g., 'en', 'ar')",
     *         @OA\Schema(type="string", enum={"en", "ar"}, default="en")
     *     ),
     *     @OA\Parameter(
     *         name="id",
     *         in="path",
     *         required=true,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Response(
     *         response=200,
     *         description="Booking data",
     *         @OA\JsonContent(
     *             @OA\Property(property="success", type="boolean", example=true),
     *             @OA\Property(property="data", ref="#/components/schemas/BookingItemResource"),
     *             @OA\Property(property="message", type="string", example="Booking retrieved successfully.")
     *         )
     *     ),
     *     @OA\Response(
     *         response=401,
     *         description="Unauthenticated"
     *     ),
     *     @OA\Response(
     *         response=404,
     *         description="Booking not found"
     *     )
     * )
     */
    public function show(string $id)
    {
        /** @var \App\Models\ServiceProvider $provider */
        $provider = Auth::user();
        $bookingItem = $provider->bookingItems()->with(['product', 'user', 'activities'])->findOrFail($id);

        return $this->successResponse(new BookingItemResource($bookingItem), __('messages.booking_retrieved_successfully'));
    }

    /**
     * @OA\Post(
     *     path="/api/provider/bookings/{id}/confirm",
     *     summary="Confirm a booking",
     *     tags={"Provider Bookings"},
     *     security={{"bearerAuth":{}}},
     *     @OA\Parameter(
     *         name="Accept-Language",
     *         in="header",
     *         required=false,
     *         description="Language preference (e.g., 'en', 'ar')",
     *         @OA\Schema(type="string", enum={"en", "ar"}, default="en")
     *     ),
     *     @OA\Parameter(
     *         name="id",
     *         in="path",
     *         required=true,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Response(
     *         response=200,
     *         description="Booking confirmed successfully",
     *         @OA\JsonContent(
     *             @OA\Property(property="success", type="boolean", example=true),
     *             @OA\Property(property="data", ref="#/components/schemas/BookingItemResource"),
     *             @OA\Property(property="message", type="string", example="Booking confirmed successfully.")
     *         )
     *     ),
     *     @OA\Response(
     *         response=401,
     *         description="Unauthenticated"
     *     ),
     *     @OA\Response(
     *         response=404,
     *         description="Booking not found"
     *     )
     * )
     */
    public function confirm(string $id)
    {
        /** @var \App\Models\ServiceProvider $provider */
        $provider = Auth::user();
        $bookingItem = $provider->bookingItems()->with(['user', 'product', "booking"])->findOrFail($id);

        if ($bookingItem->booking->status != BookingStatus::PAID) {
            return $this->errorResponse(__("cant_change_booking_item_status"));
        }

        $bookingItem->update(['status' => BookingItemStatus::CONFIRMED]);

        return $this->successResponse(new BookingItemResource($bookingItem), __('messages.booking_confirmed'));
    }
    /**
     * @OA\Post(
     *     path="/api/provider/bookings/{id}/complete",
     *     summary="Complete a booking",
     *     tags={"Provider Bookings"},
     *     security={{"bearerAuth":{}}},
     *     @OA\Parameter(
     *         name="Accept-Language",
     *         in="header",
     *         required=false,
     *         description="Language preference (e.g., 'en', 'ar')",
     *         @OA\Schema(type="string", enum={"en", "ar"}, default="en")
     *     ),
     *     @OA\Parameter(
     *         name="id",
     *         in="path",
     *         required=true,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Response(
     *         response=200,
     *         description="Booking Completed successfully",
     *         @OA\JsonContent(
     *             @OA\Property(property="success", type="boolean", example=true),
     *             @OA\Property(property="data", ref="#/components/schemas/BookingItemResource"),
     *             @OA\Property(property="message", type="string", example="Booking Completed successfully.")
     *         )
     *     ),
     *     @OA\Response(
     *         response=401,
     *         description="Unauthenticated"
     *     ),
     *     @OA\Response(
     *         response=404,
     *         description="Booking not found"
     *     )
     * )
     */
    public function complete(string $id)
    {
        /** @var \App\Models\ServiceProvider $provider */
        $provider = Auth::user();
        $bookingItem = $provider->bookingItems()->with(['user', 'product', "booking"])->findOrFail($id);

        if ($bookingItem->booking->status != BookingStatus::PAID) {
            return $this->errorResponse(__("cant_change_booking_item_status"));
        }

        if ($bookingItem->status != BookingItemStatus::CONFIRMED) {
            return $this->errorResponse(__("cant_change_booking_item_status"));
        }

        $bookingItem->update(['status' => BookingItemStatus::COMPLETED]);

        return $this->successResponse(new BookingItemResource($bookingItem), __('messages.booking_completed'));
    }
    /**
     * @OA\Post(
     *     path="/api/provider/bookings/{id}/decline",
     *     summary="Decline a booking",
     *     tags={"Provider Bookings"},
     *     security={{"bearerAuth":{}}},
     *     @OA\Parameter(
     *         name="Accept-Language",
     *         in="header",
     *         required=false,
     *         description="Language preference (e.g., 'en', 'ar')",
     *         @OA\Schema(type="string", enum={"en", "ar"}, default="en")
     *     ),
     *     @OA\Parameter(
     *         name="id",
     *         in="path",
     *         required=true,
     *         @OA\Schema(type="integer")
     *     ),
     *     @OA\Response(
     *         response=200,
     *         description="Booking declined successfully",
     *         @OA\JsonContent(
     *             @OA\Property(property="success", type="boolean", example=true),
     *             @OA\Property(property="data", ref="#/components/schemas/BookingItemResource"),
     *             @OA\Property(property="message", type="string", example="Booking declined successfully.")
     *         )
     *     ),
     *     @OA\Response(
     *         response=401,
     *         description="Unauthenticated"
     *     ),
     *     @OA\Response(
     *         response=404,
     *         description="Booking not found"
     *     )
     * )
     */
    public function decline(string $id)
    {
        /** @var \App\Models\ServiceProvider $provider */
        $provider = Auth::user();
        $bookingItem = $provider->bookingItems()->with(['user', 'product', "booking"])->findOrFail($id);

        if ($bookingItem->booking->status != BookingStatus::PAID) {
            return $this->errorResponse(__("cant_change_booking_item_status"));
        }
        $bookingItem->update(['status' => BookingItemStatus::DECLINED]);

        return $this->successResponse(new BookingItemResource($bookingItem), __('messages.booking_declined'));
    }
}
