<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Appointment;
use App\Models\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\Models\Holiday;

class AppointmentController extends Controller
{
    /**
     * Check if user has access to create appointments
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function checkCreateAppointmentAccess(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'customer_id' => 'required|exists:clients,id'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation failed',
                'errors' => $validator->errors()
            ], 422);
        }

        try {
            $user = $request->user();
            $client = Client::findOrFail($request->customer_id);

            // Check if user is active
            if ($user->status_id != 1) {
                return response()->json([
                    'success' => false,
                    'message' => 'Account is not active',
                    'has_access' => false
                ], 403);
            }

            // Check if client has appointment access
            $hasAccess = $client->is_appointment == 1 ? true : false;

            return response()->json([
                'success' => true,
                'message' => 'Access check completed',
                'has_access' => $hasAccess,
                'client' => [
                    'id' => $client->id,
                    'name' => $client->name,
                    'is_appointment' => $client->is_appointment == 1 ? true : false
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error checking access: ' . $e->getMessage(),
                'has_access' => false
            ], 500);
        }
    }

    public function checkAppointmentDate(Request $request)
    {
        // Validation
        $validator = Validator::make($request->all(), [
            'appointment_date' => 'required|date|after_or_equal:today'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation failed',
                'errors' => $validator->errors()
            ], 422);
        }

        try {
            $appointmentDate = \Carbon\Carbon::parse($request->appointment_date)->format('Y-m-d');
            $dayOfWeek = \Carbon\Carbon::parse($appointmentDate)->dayOfWeek; // 0=Sunday, 6=Saturday

            // Default time based on the day of the week
            $defaultTime = $this->getDefaultTime($dayOfWeek);

            // Check if it's a holiday
            $holiday = Holiday::where('holiday_date', $appointmentDate)
                ->where('is_active', true)
                ->first();

            // If it's a holiday, handle accordingly
            if ($holiday) {
                // HOLIDAY
                if ($holiday->holiday_type === 'Holiday') {
                    return response()->json([
                        'success' => false,
                        'message' => 'Selected date is a full-day holiday',
                        'is_valid' => false,
                        'holiday_name' => $holiday->holiday_name,
                        'holiday_type' => $holiday->holiday_type,
                        'start_time' => null,
                        'end_time' => null,
                        'available_slots' => []
                    ], 422);
                }

                // HALF DAY HOLIDAY
                if ($holiday->holiday_type === 'Half Day') {
                    // Use the specific times for half-day holidays
                    $defaultTime = [
                        'start' => $holiday->from_time,
                        'end' => $holiday->to_time
                    ];
                }
            }

            return response()->json([
                'success' => true,
                'message' => 'Appointment date is valid',
                'is_valid' => true,
                'formatted_date' => \Carbon\Carbon::parse($appointmentDate)->format('d-m-Y'),
                'holiday_type' => $holiday ? $holiday->holiday_type : null,
                'start_time' => $defaultTime['start'],
                'end_time' => $defaultTime['end']
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error checking appointment date: ' . $e->getMessage(),
                'is_valid' => false
            ], 500);
        }
    }

    public function create(Request $request)
    {
        // Validation
        $validator = Validator::make($request->all(), [
            'client_id' => 'required|exists:clients,id',
            'appointment_title' => 'required|string|max:255',
            'appointment_date' => 'required|date|after_or_equal:today',
            'appointment_time' => 'required|date_format:H:i',
            'no_of_persons' => 'required|integer|min:1|max:10',
            'notes' => 'nullable|string|max:1000',
            'attendees' => 'nullable|array',
            'attendees.*' => 'integer|exists:customer_members,id',
            'contact' => 'nullable|string|max:255',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation failed',
                'errors' => $validator->errors()
            ], 422);
        }

        try {
            // Appointment details
            $appointmentDate = \Carbon\Carbon::parse($request->appointment_date)->format('Y-m-d');

            // Get the day of the week (0=Sunday, 6=Saturday)
            $dayOfWeek = \Carbon\Carbon::parse($appointmentDate)->dayOfWeek;

            $appointmentTime = $request->appointment_time;

            // Default Working Hours
            $defaultTime = $this->getDefaultTime($dayOfWeek);

            // Check holiday
            $holiday = Holiday::where('holiday_date', $appointmentDate)
                ->where('is_active', true)
                ->first();

            // FULL DAY HOLIDAY BLOCK
            if ($holiday && $holiday->holiday_type === 'Full day') {
                return response()->json([
                    'success' => false,
                    'message' => 'Cannot book appointment on full-day holiday',
                ], 422);
            }

            // If it's a holiday with a half-day, update the start and end times
            if ($holiday && $holiday->holiday_type === 'Half Day') {
                $defaultTime = [
                    'start' => $holiday->from_time,
                    'end' => $holiday->to_time
                ];
            }

            // TIME VALIDATION
            $appointmentTimeParsed = \Carbon\Carbon::parse($appointmentTime);
            $isValidTime = false;

            // Check if appointment time is within the valid range
            if ($appointmentTimeParsed->between(\Carbon\Carbon::parse($defaultTime['start']), \Carbon\Carbon::parse($defaultTime['end']))) {
                $isValidTime = true;
            }

            if (!$isValidTime) {
                return response()->json([
                    'success' => false,
                    'message' => 'Selected time is outside working hours or restricted due to holiday',
                ], 422);
            }

            // CREATE APPOINTMENT
            $appointment = Appointment::create([
                'client_id' => $request->client_id,
                'appointment_title' => $request->appointment_title,
                'appointment_date' => $request->appointment_date,
                'appointment_time' => $request->appointment_time,
                'no_of_persons' => $request->no_of_persons,
                'notes' => $request->notes,
                'attendees' => $request->attendees,
                'contact' => $request->contact,
                'status' => 'pending',
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Appointment created successfully',
                'data' => [
                    'appointment' => [
                        'id' => $appointment->id,
                        'client_id' => $appointment->client_id,
                        'appointment_title' => $appointment->appointment_title,
                        'appointment_date' => $appointment->appointment_date->format('Y-m-d'),
                        'appointment_time' => $appointment->appointment_time,
                        'no_of_persons' => $appointment->no_of_persons,
                        'notes' => $appointment->notes,
                        'attendees' => $appointment->attendees,
                        'contact' => $appointment->contact,
                        'status' => $appointment->status,
                        'created_at' => $appointment->created_at->toISOString()
                    ]
                ]
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error creating appointment: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get default time based on the day of the week
     */
    private function getDefaultTime(int $dayOfWeek)
    {
        switch ($dayOfWeek) {
            case 0: // Sunday
                return [
                    'start' => '09:00:00',
                    'end' => '14:00:00'
                ];
            case 6: // Saturday
                return [
                    'start' => '09:00:00',
                    'end' => '16:00:00'
                ];
            default: // Monday to Friday
                return [
                    'start' => '09:00:00',
                    'end' => '18:00:00'
                ];
        }
    }

    /**
     * Get appointment history for a client
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function history(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'client_id' => 'nullable|exists:clients,id',
            'status' => 'nullable|in:pending,confirmed,completed,cancelled',
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date|after_or_equal:start_date',
            'limit' => 'nullable|integer|min:1|max:100',
            'offset' => 'nullable|integer|min:0'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation failed',
                'errors' => $validator->errors()
            ], 422);
        }

        try {
            $query = Appointment::with(['client:id,name,email,phone']);

            // Filter by authenticated client if no client_id provided
            if (!$request->client_id) {
                $query->where('client_id', $request->user()->id);
            } else {
                $query->where('client_id', $request->client_id);
            }

            // Apply status filter
            if ($request->status) {
                $query->where('status', $request->status);
            }

            if ($request->start_date && $request->end_date) {
                $query->whereBetween('appointment_date', [$request->start_date, $request->end_date]);
            }

            // Order by appointment date and time
            $query->orderBy('appointment_date', 'desc')
                ->orderBy('appointment_time', 'desc');

            // Apply pagination
            $limit = $request->limit ?? 20;
            $offset = $request->offset ?? 0;
            $appointments = $query->skip($offset)->take($limit)->get();

            $totalCount = $query->count();

            return response()->json([
                'success' => true,
                'message' => 'Appointment history retrieved successfully',
                'data' => [
                    'appointments' => $appointments->map(function ($appointment) {
                        return [
                            'id' => $appointment->id,
                            'client_id' => $appointment->client_id,
                            'appointment_title' => $appointment->appointment_title,
                            'appointment_date' => $appointment->appointment_date->format('Y-m-d'),
                            'appointment_time' => $appointment->appointment_time,
                            'no_of_persons' => $appointment->no_of_persons,
                            'notes' => $appointment->notes,
                            'attendees' => $appointment->attendees,
                            'contact' => $appointment->contact,
                            'status' => $appointment->status,
                            'created_at' => $appointment->created_at->toISOString(),
                            'client' => $appointment->client
                        ];
                    }),
                    'pagination' => [
                        'total_count' => $totalCount,
                        'limit' => $limit,
                        'offset' => $offset,
                        'has_more' => ($offset + $limit) < $totalCount
                    ]
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error retrieving appointment history: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get appointments by client_id for Flutter app
     *
     * @param int $clientId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getAppointmentsByClient($clientId)
    {
        try {
            // Validate client ID
            if (!is_numeric($clientId) || $clientId <= 0) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid client ID'
                ], 400);
            }

            // Check if client exists
            $client = \App\Models\Client::find($clientId);
            if (!$client) {
                return response()->json([
                    'success' => false,
                    'message' => 'Client not found'
                ], 404);
            }

            // Get appointments for the client
            $appointments = Appointment::where('client_id', $clientId)
                ->with(['client:id,name,email,phone'])
                ->orderBy('appointment_date', 'desc')
                ->orderBy('appointment_time', 'desc')
                ->get();

            // Format the response
            $formattedAppointments = $appointments->map(function ($appointment) {
                // Get attendee names from customer_members table
                $attendeeNames = [];
                if ($appointment->attendees && is_array($appointment->attendees)) {
                    $attendeeNames = \App\Models\CustomerMember::whereIn('id', $appointment->attendees)
                        ->where('is_active', 1)
                        ->pluck('name')
                        ->toArray();
                }

                return [
                    'id' => $appointment->id,
                    'client_id' => $appointment->client_id,
                    'appointment_title' => $appointment->appointment_title,
                    'appointment_date' => $appointment->appointment_date->format('Y-m-d'),
                    'appointment_time' => $appointment->appointment_time,
                    'formatted_time' => $appointment->formatted_time,
                    'no_of_persons' => $appointment->no_of_persons,
                    'notes' => $appointment->notes,
                    'attendees' => $attendeeNames,
                    'attendees_ids' => $appointment->attendees, // Keep IDs for reference if needed
                    'contact' => $appointment->contact,
                    'status' => $appointment->status,
                    'created_at' => $appointment->created_at->toISOString(),
                    'updated_at' => $appointment->updated_at->toISOString(),
                    'client' => $appointment->client
                ];
            });

            return response()->json([
                'success' => true,
                'message' => 'Appointments retrieved successfully',
                'data' => [
                    'client' => [
                        'id' => $client->id,
                        'name' => $client->name,
                        'email' => $client->email,
                        'phone' => $client->phone
                    ],
                    'appointments' => $formattedAppointments,
                    'total_count' => $appointments->count(),
                    'status_counts' => [
                        'pending' => $appointments->where('status', 'pending')->count(),
                        'confirmed' => $appointments->where('status', 'confirmed')->count(),
                        'completed' => $appointments->where('status', 'completed')->count(),
                        'cancelled' => $appointments->where('status', 'cancelled')->count()
                    ]
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error retrieving appointments: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get today's appointments by client_id API
     *
     * @param int $clientId
     * @return \Illuminate\Http\JsonResponse
     */
    public function getTodayAppointmentsByClient($clientId)
    {
        try {
            // Validate client ID
            if (!is_numeric($clientId) || $clientId <= 0) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid client ID'
                ], 400);
            }

            // Check if client exists
            $client = \App\Models\Client::find($clientId);
            if (!$client) {
                return response()->json([
                    'success' => false,
                    'message' => 'Client not found'
                ], 404);
            }

            // Get today's appointments for the client
            $today = \Carbon\Carbon::today()->format('Y-m-d');
            $appointments = Appointment::where('client_id', $clientId)
                ->whereDate('appointment_date', $today)
                ->with(['client:id,name,email,phone'])
                ->orderBy('appointment_time', 'asc')
                ->get();

            // Format the response
            $formattedAppointments = $appointments->map(function ($appointment) {
                // Get attendee names from customer_members table
                $attendeeNames = [];
                if ($appointment->attendees && is_array($appointment->attendees)) {
                    $attendeeNames = \App\Models\CustomerMember::whereIn('id', $appointment->attendees)
                        ->where('is_active', 1)
                        ->pluck('name')
                        ->toArray();
                }

                return [
                    'id' => $appointment->id,
                    'client_id' => $appointment->client_id,
                    'appointment_title' => $appointment->appointment_title,
                    'appointment_date' => $appointment->appointment_date->format('Y-m-d'),
                    'appointment_time' => $appointment->appointment_time,
                    'formatted_time' => $appointment->formatted_time,
                    'no_of_persons' => $appointment->no_of_persons,
                    'notes' => $appointment->notes,
                    'attendees' => $attendeeNames,
                    'attendees_ids' => $appointment->attendees, // Keep IDs for reference if needed
                    'contact' => $appointment->contact,
                    'status' => $appointment->status,
                    'created_at' => $appointment->created_at->toISOString(),
                    'updated_at' => $appointment->updated_at->toISOString(),
                    'client' => $appointment->client
                ];
            });

            return response()->json([
                'success' => true,
                'message' => 'Today\'s appointments retrieved successfully',
                'data' => [
                    'client' => [
                        'id' => $client->id,
                        'name' => $client->name,
                        'email' => $client->email,
                        'phone' => $client->phone
                    ],
                    'date' => $today,
                    'appointments' => $formattedAppointments,
                    'total_count' => $appointments->count(),
                    'status_counts' => [
                        'pending' => $appointments->where('status', 'pending')->count(),
                        'confirmed' => $appointments->where('status', 'confirmed')->count(),
                        'completed' => $appointments->where('status', 'completed')->count(),
                        'cancelled' => $appointments->where('status', 'cancelled')->count()
                    ]
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error retrieving today\'s appointments: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get appointments by client_id and status for Flutter app
     *
     * @param int $clientId
     * @param string $status
     * @return \Illuminate\Http\JsonResponse
     */
    public function getAppointmentsByClientAndStatus($clientId, $status)
    {
        try {
            // Validate client ID
            if (!is_numeric($clientId) || $clientId <= 0) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid client ID'
                ], 400);
            }

            // Validate status
            $validStatuses = ['pending', 'confirmed', 'completed', 'cancelled'];
            if (!in_array($status, $validStatuses)) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid status. Must be one of: ' . implode(', ', $validStatuses)
                ], 400);
            }

            // Check if client exists
            $client = \App\Models\Client::find($clientId);
            if (!$client) {
                return response()->json([
                    'success' => false,
                    'message' => 'Client not found'
                ], 404);
            }

            // Get appointments for the client by status
            $appointments = Appointment::where('client_id', $clientId)
                ->where('status', $status)
                ->with(['client:id,name,email,phone'])
                ->orderBy('appointment_date', 'desc')
                ->orderBy('appointment_time', 'desc')
                ->get();

            // Format the response
            $formattedAppointments = $appointments->map(function ($appointment) {
                // Get attendee names from customer_members table
                $attendeeNames = [];
                if ($appointment->attendees && is_array($appointment->attendees)) {
                    $attendeeNames = \App\Models\CustomerMember::whereIn('id', $appointment->attendees)
                        ->where('is_active', 1)
                        ->pluck('name')
                        ->toArray();
                }

                return [
                    'id' => $appointment->id,
                    'client_id' => $appointment->client_id,
                    'appointment_title' => $appointment->appointment_title,
                    'appointment_date' => $appointment->appointment_date->format('Y-m-d'),
                    'appointment_time' => $appointment->appointment_time,
                    'formatted_time' => $appointment->formatted_time,
                    'no_of_persons' => $appointment->no_of_persons,
                    'notes' => $appointment->notes,
                    'attendees' => $attendeeNames,
                    'attendees_ids' => $appointment->attendees, // Keep IDs for reference if needed
                    'contact' => $appointment->contact,
                    'status' => $appointment->status,
                    'created_at' => $appointment->created_at->toISOString(),
                    'updated_at' => $appointment->updated_at->toISOString(),
                    'client' => $appointment->client
                ];
            });

            return response()->json([
                'success' => true,
                'message' => ucfirst($status) . ' appointments retrieved successfully',
                'data' => [
                    'client' => [
                        'id' => $client->id,
                        'name' => $client->name,
                        'email' => $client->email,
                        'phone' => $client->phone
                    ],
                    'status' => $status,
                    'appointments' => $formattedAppointments,
                    'total_count' => $appointments->count()
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error retrieving appointments: ' . $e->getMessage()
            ], 500);
        }
    }
}
