<?php

namespace App\Http\Controllers\Api;

use App\Models\Booking;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;

class BookingController extends BaseController
{
    /**
     * Create a new booking
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'tailor_id' => 'required|exists:users,id',
            'appointment_date' => 'required|date|after_or_equal:today',
            'appointment_time' => 'required|date_format:H:i',
            'service_type' => 'required|in:Perbaikan,Jahit Baru',
            'category' => 'required|in:Atasan,Bawahan,Terusan',
            'design_photo' => 'required|image|max:2048', // max 2MB
            'notes' => 'nullable|string',
            'payment_method' => 'required|string|max:50'
        ]);

        if ($validator->fails()) {
            return $this->sendError('Error validasi.', $validator->errors(), 422);
        }

        try {
            // Check if tailor exists and is actually a tailor
            $tailor = User::findOrFail($request->tailor_id);
            if (!$tailor->isPenjahit()) {
                return $this->sendError('Error validasi.', ['tailor_id' => 'ID yang dipilih bukan penjahit'], 422);
            }

            // Convert appointment time to Carbon instance
            $requestedTime = Carbon::parse($request->appointment_time);
            $requestedDate = Carbon::parse($request->appointment_date);

            // Calculate time slot (2 hours)
            $slotStart = $requestedTime->copy();
            $slotEnd = $requestedTime->copy()->addHours(2);

            // Check if there is any booking that overlaps with this time slot
            $existingBooking = Booking::where('tailor_id', $request->tailor_id)
                ->where('appointment_date', $request->appointment_date)
                ->where('status', '!=', 'dibatalkan')
                ->where(function($query) use ($slotStart, $slotEnd) {
                    $query->where(function($q) use ($slotStart, $slotEnd) {
                        // Check if existing booking's time slot overlaps with requested slot
                        $q->where(function($q) use ($slotStart, $slotEnd) {
                            $q->whereRaw('TIME(appointment_time) BETWEEN ? AND ?', [
                                $slotStart->format('H:i:s'),
                                $slotEnd->format('H:i:s')
                            ]);
                        })
                        ->orWhere(function($q) use ($slotStart, $slotEnd) {
                            $q->whereRaw('TIME(DATE_ADD(appointment_time, INTERVAL 2 HOUR)) BETWEEN ? AND ?', [
                                $slotStart->format('H:i:s'),
                                $slotEnd->format('H:i:s')
                            ]);
                        });
                    });
                })
                ->first();

            if ($existingBooking) {
                return $this->sendError('Error validasi.', [
                    'appointment' => 'Jadwal tidak tersedia. Penjahit sudah memiliki booking pada waktu tersebut (durasi 2 jam)'
                ], 422);
            }

            $booking = new Booking($request->all());
            $booking->customer_id = Auth::id();
            $booking->status = 'reservasi';
            $booking->payment_status = 'unpaid';
            $booking->payment_method = $request->payment_method;

            // Generate transaction code
            $booking->transaction_code = $this->generateTransactionCode();

            // Handle design photo upload
            if ($request->hasFile('design_photo')) {
                $path = $request->file('design_photo')->store('design_photos', 'public');
                $booking->design_photo = $path;
            }

            $booking->save();

            // Load relationships
            $booking->load(['customer', 'tailor']);

            return $this->sendResponse($booking, 'Booking berhasil dibuat.');
        } catch (\Exception $e) {
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat membuat booking'], 500);
        }
    }

    /**
     * Get customer's bookings with filter
     */
    public function customerBookings(Request $request)
    {
        try {
            $query = Booking::where('customer_id', Auth::id())
                ->with(['tailor', 'ratings']);

            // Filter by status if provided
            if ($request->has('status')) {
                $query->where('status', $request->status);
            }

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

            // Transform the bookings to add completion date information
            $transformedBookings = $bookings->map(function ($booking) {
                $data = $booking->toArray();

                // Add formatted completed_at date if booking is completed
                if ($booking->status === 'selesai' && $booking->completed_at) {
                    $data['completed_at_formatted'] = Carbon::parse($booking->completed_at)->format('Y-m-d');
                }

                // Add rating information if exists
                if ($booking->ratings->count() > 0) {
                    $rating = $booking->ratings->first();
                    $data['rating'] = [
                        'id' => $rating->id,
                        'rating' => $rating->rating,
                        'review' => $rating->review,
                        'created_at' => $rating->created_at,
                        'updated_at' => $rating->updated_at
                    ];
                } else {
                    $data['rating'] = null;
                }

                // Pastikan transaction_code dan payment_method selalu tersedia di respons
                $data['transaction_code'] = $booking->transaction_code;
                $data['payment_method'] = $booking->payment_method;

                return $data;
            });

            return $this->sendResponse($transformedBookings, 'Data booking berhasil diambil.');
        } catch (\Exception $e) {
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat mengambil data booking'], 500);
        }
    }

    /**
     * Get tailor's bookings with filter
     */
    public function tailorBookings(Request $request)
    {
        try {
            $query = Booking::where('tailor_id', Auth::id())
                ->with(['customer', 'ratings']);

            // Filter by status if provided
            if ($request->has('status')) {
                $query->where('status', $request->status);
            }

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

            // Transform bookings to include rating information
            $transformedBookings = $bookings->map(function ($booking) {
                $data = $booking->toArray();

                // Add rating information if exists
                if ($booking->ratings->count() > 0) {
                    $rating = $booking->ratings->first();
                    $data['rating'] = [
                        'id' => $rating->id,
                        'rating' => $rating->rating,
                        'review' => $rating->review,
                        'created_at' => $rating->created_at,
                        'updated_at' => $rating->updated_at
                    ];
                } else {
                    $data['rating'] = null;
                }

                // Pastikan transaction_code dan payment_method selalu tersedia di respons
                $data['transaction_code'] = $booking->transaction_code;
                $data['payment_method'] = $booking->payment_method;

                return $data;
            });

            return $this->sendResponse($transformedBookings, 'Data booking berhasil diambil.');
        } catch (\Exception $e) {
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat mengambil data booking'], 500);
        }
    }

    /**
     * Update booking status
     */
    public function updateStatus(Request $request, Booking $booking)
    {
        $validator = Validator::make($request->all(), [
            'status' => 'required|in:diproses,selesai,dibatalkan',
            'total_price' => 'required_if:status,diproses|numeric|min:0',
            'completion_date' => 'required_if:status,diproses|date|after_or_equal:today'
        ]);

        if ($validator->fails()) {
            return $this->sendError('Error validasi.', $validator->errors(), 422);
        }

        try {
            // Check if the authenticated user is the tailor of this booking
            if ($booking->tailor_id !== Auth::id()) {
                return $this->sendError('Unauthorized.', ['error' => 'Anda tidak memiliki akses untuk mengubah status booking ini'], 403);
            }

            // Validate status transition
            if ($request->status === 'diproses' && !$booking->canBeProcessed()) {
                return $this->sendError('Error validasi.', ['status' => 'Booking tidak dapat diproses. Pastikan pembayaran sudah dilakukan.'], 422);
            }

            if ($request->status === 'selesai' && !$booking->canBeCompleted()) {
                return $this->sendError('Error validasi.', ['status' => 'Booking tidak dapat diselesaikan. Status harus diproses terlebih dahulu.'], 422);
            }

            $booking->status = $request->status;
            if ($request->status === 'diproses') {
                $booking->total_price = $request->total_price;
                $booking->completion_date = $request->completion_date;
            }
            $booking->save();

            return $this->sendResponse($booking, 'Status booking berhasil diupdate.');
        } catch (\Exception $e) {
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat mengupdate status booking'], 500);
        }
    }

    /**
     * Cancel booking (for customer)
     */
    public function cancelBooking(Booking $booking)
    {
        try {
            // Check if the authenticated user is the customer of this booking
            if ($booking->customer_id !== Auth::id()) {
                return $this->sendError('Unauthorized.', ['error' => 'Anda tidak memiliki akses untuk membatalkan booking ini'], 403);
            }

            // Check if booking can be cancelled
            if (!$booking->canBeCancelled()) {
                return $this->sendError('Error validasi.', ['status' => 'Booking tidak dapat dibatalkan karena sudah diproses'], 422);
            }

            $booking->status = 'dibatalkan';
            $booking->save();

            return $this->sendResponse($booking, 'Booking berhasil dibatalkan.');
        } catch (\Exception $e) {
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat membatalkan booking'], 500);
        }
    }

    /**
     * Update payment status
     */
    public function updatePaymentStatus(Request $request, Booking $booking)
    {
        $validator = Validator::make($request->all(), [
            'payment_status' => 'required|in:paid,success'
        ]);

        if ($validator->fails()) {
            return $this->sendError('Error validasi.', $validator->errors(), 422);
        }

        try {
            // Periksa apakah pengguna yang terautentikasi adalah penjahit dari booking ini
            if ($booking->tailor_id !== Auth::id()) {
                return $this->sendError('Unauthorized.', ['error' => 'Anda tidak memiliki akses untuk mengubah status pembayaran ini'], 403);
            }

            // Periksa apakah status booking valid untuk perubahan status pembayaran
            if (!in_array($booking->status, ['reservasi', 'diproses', 'selesai'])) {
                return $this->sendError('Invalid status', ['error' => 'Status pembayaran hanya dapat diubah untuk booking yang aktif'], 422);
            }

            // Tentukan status pembayaran berdasarkan metode pembayaran
            if ($booking->payment_method === 'COD') {
                $booking->payment_status = 'success';
            } else {
                $booking->payment_status = 'paid';
            }

            $booking->save();

            // Memberikan informasi lebih detail pada respons
            return $this->sendResponse([
                'booking' => [
                    'id' => $booking->id,
                    'customer_name' => $booking->customer->name,
                    'payment_status' => $booking->payment_status,
                    'payment_method' => $booking->payment_method,
                    'status' => $booking->status,
                    'total_price' => $booking->total_price,
                    'appointment_date' => $booking->appointment_date
                ]
            ], 'Status pembayaran berhasil diubah menjadi ' . $booking->payment_status . ' oleh penjahit.');
        } catch (\Exception $e) {
            \Log::error('Error in updatePaymentStatus: ' . $e->getMessage(), [
                'booking_id' => $booking->id,
                'tailor_id' => Auth::id(),
                'exception' => $e
            ]);
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat mengupdate status pembayaran'], 500);
        }
    }

    /**
     * Tailor accepts booking and changes status to "diproses"
     */
    public function acceptBooking(Booking $booking)
    {
        try {
            // Check if user is the tailor
            if ($booking->tailor_id !== Auth::id()) {
                return $this->sendError('Unauthorized.', ['error' => 'Anda tidak memiliki akses untuk menerima pesanan ini'], 403);
            }

            // Debug: Log current booking status
            \Log::info('Current booking status: ' . $booking->status);

            // Check if booking can be processed
            if (!in_array($booking->status, ['pending', 'reservasi'])) {
                return $this->sendError('Invalid status', ['error' => 'Pesanan tidak dapat diproses. Status saat ini: ' . $booking->status], 422);
            }

            // Update booking status to diproses
            $booking->status = 'diproses';
            $booking->accepted_at = now();
            $booking->save();

            // Load customer relationship for response with correct column name
            $booking->load(['customer:id,name,email,phone_number']);

            return $this->sendResponse([
                'booking' => [
                    'id' => $booking->id,
                    'customer_name' => $booking->customer->name,
                    'customer_phone' => $booking->customer->phone_number,
                    'service_type' => $booking->service_type,
                    'category' => $booking->category,
                    'appointment_date' => Carbon::parse($booking->appointment_date)->format('Y-m-d'),
                    'appointment_time' => $booking->appointment_time,
                    'design_photo' => $booking->design_photo,
                    'notes' => $booking->notes,
                    'status' => $booking->status,
                    'accepted_at' => Carbon::parse($booking->accepted_at)->format('Y-m-d H:i:s')
                ]
            ], 'Pesanan berhasil diterima dan diproses');

        } catch (\Exception $e) {
            \Log::error('Error in acceptBooking: ' . $e->getMessage());
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat memproses pesanan'], 500);
        }
    }

    /**
     * Reject booking by tailor
     */
    public function rejectBooking(Request $request, Booking $booking)
    {
        try {
            // Validate request
            $validator = Validator::make($request->all(), [
                'rejection_reason' => 'required|string|max:255'
            ]);

            if ($validator->fails()) {
                return $this->sendError('Error validasi.', $validator->errors(), 422);
            }

            // Check if the authenticated user is the tailor assigned to this booking
            if ($booking->tailor_id !== Auth::id()) {
                return $this->sendError('Unauthorized.', ['error' => 'Anda tidak memiliki akses untuk menolak booking ini'], 403);
            }

            // Check if booking is in reservasi status
            if ($booking->status !== 'reservasi') {
                return $this->sendError('Error validasi.', ['error' => 'Booking ini tidak dapat ditolak karena status bukan reservasi'], 422);
            }

            $booking->update([
                'status' => 'dibatalkan',
                'rejection_reason' => $request->rejection_reason,
                'rejected_at' => now()
            ]);

            // Load the customer relationship
            $booking->load('customer');

            // TODO: Send notification to customer that booking has been rejected

            return $this->sendResponse($booking, 'Booking telah ditolak');
        } catch (\Exception $e) {
            // Log error detail untuk keperluan debugging
            \Log::error('Error in rejectBooking: ' . $e->getMessage(), [
                'booking_id' => $booking->id,
                'exception' => $e
            ]);
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat menolak booking'], 500);
        }
    }

    /**
     * Get booking details
     */
    public function show(Booking $booking)
    {
        try {
            // Check if user is authorized to view this booking
            if ($booking->customer_id !== Auth::id() && $booking->tailor_id !== Auth::id()) {
                return $this->sendError('Unauthorized.', ['error' => 'Anda tidak memiliki akses ke pesanan ini'], 403);
            }

            // Load relationships
            $booking->load(['customer:id,name,phone_number', 'tailor:id,name,profile_photo']);

            $response = [
                'id' => $booking->id,
                'transaction_code' => $booking->transaction_code,
                'customer' => [
                    'name' => $booking->customer->name,
                    'phone_number' => $booking->customer->phone_number
                ],
                'tailor' => [
                    'name' => $booking->tailor->name,
                    'profile_photo' => $booking->tailor->profile_photo
                ],
                'appointment_date' => Carbon::parse($booking->appointment_date)->format('Y-m-d'),
                'appointment_time' => $booking->appointment_time,
                'service_type' => $booking->service_type,
                'category' => $booking->category,
                'status' => $booking->status,
                'total_price' => $booking->total_price,
                'completion_date' => $booking->completion_date ? Carbon::parse($booking->completion_date)->format('Y-m-d') : null,
                'payment_status' => $booking->payment_status,
                'payment_method' => $booking->payment_method,
                'notes' => $booking->notes,
                'measurements' => $booking->measurements,
                'repair_details' => $booking->repair_details,
                'repair_photo' => $booking->repair_photo,
                'repair_notes' => $booking->repair_notes,
                'completion_photo' => $booking->completion_photo,
                'completion_notes' => $booking->completion_notes,
                'pickup_date' => $booking->pickup_date ? Carbon::parse($booking->pickup_date)->format('Y-m-d') : null
            ];

            return $this->sendResponse($response, 'Detail pesanan berhasil diambil');
        } catch (\Exception $e) {
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat mengambil detail pesanan'], 500);
        }
    }

    /**
     * Update measurements for the booking
     */
    public function updateMeasurements(Request $request, Booking $booking)
    {
        try {
            // Check if the authenticated user is the tailor assigned to this booking
            if ($booking->tailor_id !== Auth::id()) {
                return $this->sendError('Unauthorized.', ['error' => 'Anda tidak memiliki akses untuk mengupdate ukuran pesanan ini'], 403);
            }

            // Check if booking is in correct status
            if ($booking->status !== 'diproses') {
                return $this->sendError('Error validasi.', ['error' => 'Ukuran hanya dapat diinput setelah booking diterima dan dalam status diproses'], 422);
            }

            // Validate measurements based on category
            $validator = Validator::make($request->all(), [
                'measurements' => 'required|array',
                'measurements.lingkar_pinggang' => 'required_if:category,Bawahan,Terusan|numeric',
                'measurements.lingkar_pinggul' => 'required_if:category,Bawahan,Terusan|numeric',
                'measurements.lingkar_paha' => 'required_if:category,Bawahan|numeric',
                'measurements.lingkar_lutut' => 'required_if:category,Bawahan|numeric',
                'measurements.panjang_celana' => 'required_if:category,Bawahan|numeric',
                'measurements.lingkar_badan' => 'required_if:category,Atasan,Terusan|numeric',
                'measurements.lingkar_dada' => 'required_if:category,Atasan,Terusan|numeric',
                'measurements.panjang_lengan' => 'required_if:category,Atasan,Terusan|numeric',
                'measurements.lingkar_lengan' => 'required_if:category,Atasan,Terusan|numeric',
                'measurements.lingkar_pergelangan' => 'required_if:category,Atasan,Terusan|numeric',
                'measurements.panjang_baju' => 'required_if:category,Atasan,Terusan|numeric',
                'measurements.lebar_bahu' => 'required_if:category,Atasan,Terusan|numeric',
                'measurements.panjang_rok' => 'required_if:category,Terusan|numeric',
                'measurements.lingkar_pinggang_dress' => 'required_if:category,Terusan|numeric',
                'measurements.lingkar_ketiak' => 'required_if:category,Terusan|numeric',
                'measurements.panjang_dress' => 'required_if:category,Terusan|numeric'
            ]);

            if ($validator->fails()) {
                return $this->sendError('Error validasi.', $validator->errors(), 422);
            }

            // Update measurements
            $booking->measurements = $request->measurements;
            $booking->save();

            return $this->sendResponse($booking, 'Ukuran pesanan berhasil diupdate');
        } catch (\Exception $e) {
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat mengupdate ukuran pesanan'], 500);
        }
    }

    /**
     * Complete booking and change status to "selesai"
     */
    public function completeBooking(Request $request, Booking $booking)
    {
        try {
            // Check if user is the tailor
            if ($booking->tailor_id !== Auth::id()) {
                return $this->sendError('Unauthorized.', ['error' => 'Anda tidak memiliki akses untuk menyelesaikan pesanan ini'], 403);
            }

            // Check if booking status is diproses
            if ($booking->status !== 'diproses') {
                return $this->sendError('Invalid status', ['error' => 'Hanya pesanan dengan status diproses yang dapat diselesaikan'], 422);
            }

            // Validate request
            $validator = Validator::make($request->all(), [
                'completion_photo' => 'required|image|mimes:jpeg,jpg,png|max:2048',
                'completion_notes' => 'nullable|string|max:500',
                'total_price' => 'nullable|numeric|min:0'
            ]);

            if ($validator->fails()) {
                return $this->sendError('Error validasi.', $validator->errors(), 422);
            }

            // Upload completion photo
            if ($request->hasFile('completion_photo')) {
                $photo = $request->file('completion_photo');

                // Buat direktori jika belum ada
                $storagePath = storage_path('app/public/completion_photos');
                if (!file_exists($storagePath)) {
                    mkdir($storagePath, 0755, true);
                }

                // Simpan file dengan nama yang unik
                $filename = 'completion_' . time() . '_' . $booking->id . '.' . $photo->getClientOriginalExtension();
                $photo->move($storagePath, $filename);

                // Simpan path relatif ke database untuk akses via URL /storage/completion_photos/...
                $booking->completion_photo = 'completion_photos/' . $filename;
            }

            // Update price if provided
            if ($request->has('total_price')) {
                $booking->total_price = $request->total_price;
            }

            // Update booking
            $booking->status = 'selesai';
            $booking->completion_notes = $request->completion_notes;
            $booking->completed_at = now();
            $booking->save();

            // Load relationships
            $booking->load(['customer:id,name,phone_number', 'tailor:id,name']);

            // Tambahkan URL lengkap untuk akses gambar
            $completionPhotoUrl = $booking->completion_photo ? url('storage/' . $booking->completion_photo) : null;

            return $this->sendResponse([
                'id' => $booking->id,
                'status' => $booking->status,
                'completion_photo' => $booking->completion_photo,
                'completion_photo_url' => $completionPhotoUrl,
                'completion_notes' => $booking->completion_notes,
                'total_price' => $booking->total_price,
                'completed_at' => Carbon::parse($booking->completed_at)->format('Y-m-d H:i:s'),
                'customer' => [
                    'name' => $booking->customer->name,
                    'phone_number' => $booking->customer->phone_number
                ],
                'tailor' => [
                    'name' => $booking->tailor->name
                ]
            ], 'Pesanan berhasil diselesaikan');

        } catch (\Exception $e) {
            \Log::error('Error in completeBooking: ' . $e->getMessage());
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat menyelesaikan pesanan'], 500);
        }
    }

    /**
     * Update repair details for the booking
     */
    public function updateRepairDetails(Request $request, Booking $booking)
    {
        try {
            // Check if the authenticated user is the tailor assigned to this booking
            if ($booking->tailor_id !== Auth::id()) {
                return $this->sendError('Unauthorized.', ['error' => 'Anda tidak memiliki akses untuk mengupdate detail perbaikan'], 403);
            }

            // Validate repair details
            $validator = Validator::make($request->all(), [
                'repair_details' => 'required|string|max:1000',
                'repair_photo' => 'nullable|image|max:2048', // max 2MB
                'repair_notes' => 'nullable|string|max:1000'
            ]);

            if ($validator->fails()) {
                return $this->sendError('Error validasi.', $validator->errors(), 422);
            }

            // Handle repair photo upload
            if ($request->hasFile('repair_photo')) {
                $path = $request->file('repair_photo')->store('repair_photos', 'public');
                $booking->repair_photo = $path;
            }

            // Update repair details
            $booking->repair_details = $request->repair_details;
            $booking->repair_notes = $request->repair_notes;
            $booking->save();

            return $this->sendResponse($booking, 'Detail perbaikan berhasil diupdate');
        } catch (\Exception $e) {
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat mengupdate detail perbaikan'], 500);
        }
    }

    /**
     * Get tailor's bookings by status
     */
    public function tailorBookingsByStatus($status)
    {
        try {
            // Validate status
            if (!in_array($status, ['pending', 'diterima', 'diproses', 'selesai', 'dibatalkan', 'reservasi'])) {
                return $this->sendError('Error validasi.', ['status' => 'Status tidak valid'], 422);
            }

            $bookings = Booking::where('tailor_id', Auth::id())
                ->where('status', $status)
                ->with(['customer'])
                ->orderBy('created_at', 'desc')
                ->get();

            return $this->sendResponse($bookings, 'Data booking ' . $status . ' berhasil diambil.');
        } catch (\Exception $e) {
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat mengambil data booking'], 500);
        }
    }

    /**
     * Simplified booking creation from tailor detail page
     */
    public function bookTailor(Request $request, $tailorId)
    {
        try {
            // Set timezone to Asia/Jakarta
            date_default_timezone_set('Asia/Jakarta');

            // Get today's date in Asia/Jakarta timezone
            $today = Carbon::now('Asia/Jakarta')->startOfDay();

            // Validate request
            $validator = Validator::make($request->all(), [
                'appointment_date' => ['required', 'date', function ($attribute, $value, $fail) use ($today) {
                    $appointmentDate = Carbon::parse($value)->startOfDay();
                    if ($appointmentDate->lt($today)) {
                        $fail('Tanggal booking harus hari ini atau setelah hari ini.');
                    }
                }],
                'appointment_time' => 'required|date_format:H:i',
                'service_type' => 'required|in:Perbaikan,Jahit Baru',
                'category' => 'required|in:Atasan,Bawahan,Terusan',
                'design_photo' => 'required|image|mimes:jpeg,png,jpg|max:2048',
                'notes' => 'nullable|string',
                'payment_method' => 'required|string|max:50'
            ]);

            if ($validator->fails()) {
                return $this->sendError('Error validasi.', $validator->errors(), 422);
            }

            // Check if tailor exists and is a valid tailor
            $tailor = User::where('id', $tailorId)
                ->where('role', 'penjahit')
                ->first();

            if (!$tailor) {
                return $this->sendError('Not found.', ['error' => 'Penjahit tidak ditemukan'], 404);
            }

            // Convert appointment time to Carbon instance
            $requestedTime = Carbon::parse($request->appointment_time);
            $requestedDate = Carbon::parse($request->appointment_date);

            // Calculate time slot (2 hours)
            $slotStart = $requestedTime->copy();
            $slotEnd = $requestedTime->copy()->addHours(2);

            // Check if there is any booking that overlaps with this time slot
            $existingBooking = Booking::where('tailor_id', $tailorId)
                ->where('appointment_date', $request->appointment_date)
                ->where('status', '!=', 'dibatalkan')
                ->where(function($query) use ($slotStart, $slotEnd) {
                    $query->where(function($q) use ($slotStart, $slotEnd) {
                        // Check if existing booking's time slot overlaps with requested slot
                        $q->where(function($q) use ($slotStart, $slotEnd) {
                            $q->whereRaw('TIME(appointment_time) BETWEEN ? AND ?', [
                                $slotStart->format('H:i:s'),
                                $slotEnd->format('H:i:s')
                            ]);
                        })
                        ->orWhere(function($q) use ($slotStart, $slotEnd) {
                            $q->whereRaw('TIME(DATE_ADD(appointment_time, INTERVAL 2 HOUR)) BETWEEN ? AND ?', [
                                $slotStart->format('H:i:s'),
                                $slotEnd->format('H:i:s')
                            ]);
                        });
                    });
                })
                ->first();

            if ($existingBooking) {
                return $this->sendError('Error validasi.', [
                    'appointment' => 'Jadwal tidak tersedia. Penjahit sudah memiliki booking pada waktu tersebut (durasi 2 jam)'
                ], 422);
            }

            // Create booking
            $booking = new Booking();
            $booking->tailor_id = $tailorId;
            $booking->customer_id = Auth::id();
            $booking->appointment_date = $request->appointment_date;
            $booking->appointment_time = $request->appointment_time;
            $booking->service_type = $request->service_type;
            $booking->category = $request->category;
            $booking->notes = $request->notes;
            $booking->status = 'reservasi';
            $booking->payment_status = 'unpaid';
            $booking->payment_method = $request->payment_method;

            // Generate transaction code
            $booking->transaction_code = $this->generateTransactionCode();

            // Handle design photo if provided
            if ($request->hasFile('design_photo')) {
                $path = $request->file('design_photo')->store('design_photos', 'public');
                $booking->design_photo = $path;
            }

            $booking->save();

            // Load relationships
            $booking->load(['customer', 'tailor']);

            return $this->sendResponse([
                'booking' => $booking,
                'message' => 'Booking berhasil dibuat',
                'next_steps' => [
                    'payment' => 'Silakan lakukan pembayaran untuk mengkonfirmasi booking',
                    'cancellation' => 'Anda dapat membatalkan booking sebelum melakukan pembayaran'
                ]
            ], 'Booking berhasil dibuat');

        } catch (\Exception $e) {
            \Log::error('Error creating booking: ' . $e->getMessage());
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat membuat booking: ' . $e->getMessage()], 500);
        }
    }

    /**
     * Get customer bookings by status
     */
    public function customerBookingsByStatus($status)
    {
        try {
            $allowedStatuses = ['reservasi', 'dikonfirmasi', 'diproses', 'selesai', 'dibatalkan'];

            if (!in_array($status, $allowedStatuses)) {
                return $this->sendError('Invalid status', ['error' => 'Status tidak valid'], 422);
            }

            $bookings = Booking::where('customer_id', Auth::id())
                ->where('status', $status)
                ->with(['tailor:id,name,profile_photo', 'ratings'])
                ->orderBy('created_at', 'desc')
                ->get()
                ->map(function ($booking) use ($status) {
                    $data = [
                        'id' => $booking->id,
                        'transaction_code' => $booking->transaction_code,
                        'tailor_name' => $booking->tailor->name,
                        'tailor_photo' => $booking->tailor->profile_photo,
                        'payment_method' => $booking->payment_method,
                        'payment_status' => $booking->payment_status
                    ];

                    if ($status === 'selesai') {
                        $data = array_merge($data, [
                            'service_type' => $booking->service_type,
                            'category' => $booking->category,
                            'appointment_date' => Carbon::parse($booking->appointment_date)->format('Y-m-d'),
                            'completed_at' => $booking->completed_at ? Carbon::parse($booking->completed_at)->format('Y-m-d') : null,
                            'total_price' => $booking->total_price ?? 0,
                            'has_rating' => $booking->ratings->count() > 0,
                            'rating_id' => $booking->ratings->first() ? $booking->ratings->first()->id : null
                        ]);
                    } else if ($status === 'diproses') {
                        $data = array_merge($data, [
                            'service_type' => $booking->service_type,
                            'appointment_date' => Carbon::parse($booking->appointment_date)->format('Y-m-d'),
                            'completed_at' => $booking->completed_at ? Carbon::parse($booking->completed_at)->format('Y-m-d') : null,
                            'total_price' => $booking->total_price ?? 0,
                            'design_photo' => $booking->design_photo ? '/storage/' . $booking->design_photo : null,
                            'repair_photo' => $booking->repair_photo ? '/storage/' . $booking->repair_photo : null,
                            'repair_details' => $booking->repair_details,
                            'repair_notes' => $booking->repair_notes,
                            'category' => $booking->category
                        ]);
                    } else if (in_array($status, ['reservasi', 'dikonfirmasi'])) {
                        $data = array_merge($data, [
                            'service_type' => $booking->service_type,
                            'category' => $booking->category,
                            'appointment_date' => Carbon::parse($booking->appointment_date)->format('Y-m-d'),
                            'appointment_time' => $booking->appointment_time,
                            'design_photo' => $booking->design_photo ? '/storage/' . $booking->design_photo : null,
                            'notes' => $booking->notes,
                            'status' => $status === 'reservasi' ? 'Menunggu Konfirmasi' : 'Dikonfirmasi',
                            'status_code' => $status
                        ]);
                    }

                    return $data;
                });

            return $this->sendResponse([
                'bookings' => $bookings,
                'total' => $bookings->count()
            ], 'Daftar pesanan berhasil diambil');

        } catch (\Exception $e) {
            \Log::error('Error getting bookings: ' . $e->getMessage());
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat mengambil data pesanan'], 500);
        }
    }

    /**
     * Get completed booking details with measurements
     */
    public function getCompletedBookingDetails(Booking $booking)
    {
        try {
            // Check if user is authorized to view this booking
            if ($booking->customer_id !== Auth::id()) {
                return $this->sendError('Unauthorized.', ['error' => 'Anda tidak memiliki akses ke pesanan ini'], 403);
            }

            // Check if booking is completed
            if ($booking->status !== 'selesai') {
                return $this->sendError('Invalid status', ['error' => 'Pesanan belum selesai'], 422);
            }

            // Load relationships and measurements
            $booking->load(['tailor:id,name,profile_photo']);

            $response = [
                'id' => $booking->id,
                'transaction_code' => $booking->transaction_code,
                'tailor_name' => $booking->tailor->name,
                'tailor_photo' => $booking->tailor->profile_photo,
                'service_type' => $booking->service_type,
                'category' => $booking->category,
                'appointment_date' => Carbon::parse($booking->appointment_date)->format('Y-m-d'),
                'completed_at' => $booking->completed_at ? Carbon::parse($booking->completed_at)->format('Y-m-d') : null,
                'total_price' => $booking->total_price ?? 0,
                'payment_status' => $booking->payment_status,
                'payment_method' => $booking->payment_method,
                'measurements' => $booking->measurements ?? [],
                'completion_photo' => $booking->completion_photo,
                'completion_notes' => $booking->completion_notes,
                'pickup_date' => $booking->pickup_date
            ];

            return $this->sendResponse($response, 'Detail pesanan selesai berhasil diambil');

        } catch (\Exception $e) {
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat mengambil detail pesanan'], 500);
        }
    }

    /**
     * Process final payment and set pickup date for completed booking
     */
    public function processCompletionPayment(Request $request, Booking $booking)
    {
        try {
            // Add debugging
            \Log::info('Attempting completion payment', [
                'booking_id' => $booking->id,
                'status' => $booking->status,
                'payment_status' => $booking->payment_status,
                'tailor_id' => $booking->tailor_id,
                'auth_id' => Auth::id()
            ]);

            // Check if user is authorized (penjahit)
            if ($booking->tailor_id !== Auth::id()) {
                \Log::warning('Unauthorized payment attempt', [
                    'booking_id' => $booking->id,
                    'tailor_id' => $booking->tailor_id,
                    'auth_id' => Auth::id()
                ]);
                return $this->sendError('Unauthorized.', ['error' => 'Anda tidak memiliki akses untuk menandai pembayaran selesai'], 403);
            }

            // Validate booking status
            if ($booking->status !== 'selesai') {
                \Log::warning('Invalid booking status for payment', [
                    'booking_id' => $booking->id,
                    'status' => $booking->status
                ]);
                return $this->sendError('Invalid status', ['error' => 'Pembayaran hanya dapat dilakukan untuk pesanan yang sudah selesai'], 422);
            }

            // Check if already paid
            if ($booking->payment_status === 'paid' || $booking->payment_status === 'success') {
                \Log::warning('Booking already paid', ['booking_id' => $booking->id]);
                return $this->sendError('Already paid', ['error' => 'Pesanan ini sudah dibayar'], 422);
            }

            // Validate request
            $validator = Validator::make($request->all(), [
                'pickup_date' => 'required|date|after_or_equal:today'
            ]);

            if ($validator->fails()) {
                return $this->sendError('Error validasi.', $validator->errors(), 422);
            }

            // Update booking with payment and pickup date
            if ($booking->payment_method === 'COD') {
                $booking->payment_status = 'success';
            } else {
                $booking->payment_status = 'paid';
            }
            $booking->pickup_date = $request->pickup_date;
            $booking->save();

            // Load customer for response
            $booking->load('customer:id,name,phone_number');

            return $this->sendResponse([
                'booking' => [
                    'id' => $booking->id,
                    'customer_name' => $booking->customer->name,
                    'customer_phone' => $booking->customer->phone_number,
                    'payment_status' => $booking->payment_status,
                    'payment_method' => $booking->payment_method,
                    'status' => $booking->status,
                    'pickup_date' => Carbon::parse($booking->pickup_date)->format('Y-m-d')
                ],
                'message' => 'Pembayaran telah dikonfirmasi oleh penjahit',
                'pickup_info' => [
                    'date' => Carbon::parse($booking->pickup_date)->format('Y-m-d'),
                    'status' => 'Sudah dibayar dengan status ' . $booking->payment_status
                ]
            ], 'Pembayaran telah dikonfirmasi dan tanggal pengambilan berhasil diatur');

        } catch (\Exception $e) {
            \Log::error('Error processing completion payment: ' . $e->getMessage(), [
                'booking_id' => $booking->id,
                'exception' => $e
            ]);
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat memproses pembayaran'], 500);
        }
    }

    /**
     * Get all bookings (Admin only)
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function getAllBookings(Request $request): JsonResponse
    {
        $status = $request->query('status');
        $perPage = $request->query('per_page', 10);

        $query = Booking::with(['customer', 'tailor'])
            ->orderBy('created_at', 'desc');

        if ($status) {
            $query->where('status', $status);
        }

        $bookings = $query->paginate($perPage);

        return response()->json([
            'status' => 'success',
            'message' => 'Bookings retrieved successfully',
            'data' => $bookings
        ]);
    }

    /**
     * Update booking price and completion date
     *
     * @param Request $request
     * @param Booking $booking
     * @return JsonResponse
     */
    public function updatePrice(Request $request, Booking $booking): JsonResponse
    {
        try {
            // Check if the authenticated user is the tailor of this booking
            if ($booking->tailor_id !== Auth::id()) {
                return $this->sendError('Unauthorized.', ['error' => 'Anda tidak memiliki akses untuk mengubah harga booking ini'], 403);
            }

            // Validate request
            $validator = Validator::make($request->all(), [
                'total_price' => 'required|numeric|min:0',
                'completion_date' => 'required|date|after_or_equal:today'
            ]);

            if ($validator->fails()) {
                return $this->sendError('Error validasi.', $validator->errors(), 422);
            }

            // Update price and completion date
            $booking->total_price = $request->total_price;
            $booking->completion_date = $request->completion_date;
            $booking->save();

            return $this->sendResponse([
                'id' => $booking->id,
                'total_price' => $booking->total_price,
                'completion_date' => Carbon::parse($booking->completion_date)->format('Y-m-d'),
                'status' => $booking->status,
                'customer' => [
                    'name' => $booking->customer->name,
                    'phone_number' => $booking->customer->phone_number
                ]
            ], 'Harga dan tanggal selesai pesanan berhasil diupdate');
        } catch (\Exception $e) {
            return $this->sendError('Error.', ['error' => 'Terjadi kesalahan saat mengupdate harga dan tanggal selesai pesanan'], 500);
        }
    }

    /**
     * Generate unique transaction code
     *
     * @return string
     */
    private function generateTransactionCode()
    {
        // Format: TRX-{YYYYMMDD}-{6 random characters}
        $date = Carbon::now()->format('Ymd');
        $random = strtoupper(substr(md5(uniqid()), 0, 6));
        $code = "TRX-{$date}-{$random}";

        // Check if code already exists, if so, regenerate
        while (Booking::where('transaction_code', $code)->exists()) {
            $random = strtoupper(substr(md5(uniqid()), 0, 6));
            $code = "TRX-{$date}-{$random}";
        }

        return $code;
    }
}
