<?php

namespace Bookaro\Controller\Ajax;

defined( 'ABSPATH' ) || exit;


use Bookaro\Controller\AbstractController;
use Bookaro\Service\BookingActionService;
use Bookaro\Utils\Logger;

/**
 * AJAX endpoints related to bookings. Responsible only for
 * validating requests and delegating to the BookingActionService.
 */
class BookingController extends AbstractController
{
    private BookingActionService $actions;

    public function __construct( BookingActionService $actions )
    {
        $this->actions = $actions;
    }

    public function register_hooks(): void
    {
        $actions = [
            'bookaro_submit'             => 'handle_booking',
            'bookaro_check_availability' => 'check_availability',
            'bookaro_update_status'      => 'handle_update_status',
            'bookaro_bulk_update_status' => 'handle_bulk_update_status',
            'bookaro_get_provider_bookings' => 'get_provider_bookings',
            'bookaro_get_owner_bookings'    => 'get_owner_bookings',
            'bookaro_get_notification_logs' => 'get_notification_logs',
            'bookaro_cancel_booking'        => 'cancel_booking',
            'bookaro_add_note'              => 'add_note',
            'bookaro_reschedule_booking'    => 'reschedule_booking',
        ];
        foreach ($actions as $hook => $method) {
            add_action("wp_ajax_{$hook}", [ $this, $method ]);
        }
    }

    public function handle_booking(): void
    {
        check_ajax_referer('bookaro_nonce', 'security');
        try {
            $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
            $payload = $this->actions->sanitize_booking_payload( $payload, [ 'source' => 'ajax', 'action' => 'create_booking' ] );
            $result = $this->actions->create_booking( $payload, get_current_user_id() );
            if ( is_wp_error( $result ) ) {
                $data = $result->get_error_data();
                $status = is_array( $data ) && isset( $data['status'] ) ? (int) $data['status'] : 400;
                if ( is_array( $data ) && isset( $data['retry_after'] ) ) {
                    header( 'Retry-After: ' . absint( $data['retry_after'] ) );
                }
                wp_send_json_error( $result->get_error_message(), $status );
            }
            if ( is_array( $result ) ) {
                $result['message'] = __( 'Booking submitted successfully!', 'mybookaro' );
                wp_send_json_success( $result );
            }
            if ($result) {
                wp_send_json_success(['message' => __('Booking submitted successfully!', 'mybookaro')]);
            }
            wp_send_json_error(__('Failed to save booking.', 'mybookaro'));
        } catch (\Throwable $e) {
            Logger::log('handle_booking failed', [
                'exception' => $e->getMessage(),
                'code' => $e->getCode(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error(__('Failed to save booking.', 'mybookaro'));
        }
    }

    public function check_availability(): void
    {
        check_ajax_referer('bookaro_nonce', 'security');
        if (!is_user_logged_in()) {
            wp_send_json_error(__('You must be logged in to check availability.', 'mybookaro'));
        }
        if ( ! bookaro_user_has_dashboard_access() ) {
            wp_send_json_error( __( 'Permission denied.', 'mybookaro' ) );
        }
        try {
            $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
            $provider_id = absint( $payload['provider_id'] ?? 0 );
            $date        = sanitize_text_field( $payload['date'] ?? '' );
            $duration    = absint( $payload['duration'] ?? 0 );
            $times = $this->actions->check_availability( $provider_id, $date, $duration );
            if (empty($times)) {
                wp_send_json_error(__('No available slots for the selected date.', 'mybookaro'));
            }
            wp_send_json_success(['available_times' => $times]);
        } catch (\Throwable $e) {
            Logger::log('check_availability failed', [
                'exception' => $e->getMessage(),
                'code' => $e->getCode(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error( __( 'Failed to check availability.', 'mybookaro' ) );
        }
    }

    public function get_provider_bookings(): void
    {
        check_ajax_referer('bookaro_nonce', 'security');
        try {
            $rows = $this->actions->get_provider_bookings( get_current_user_id() );
            if ( is_wp_error( $rows ) ) {
                wp_send_json_error( $rows->get_error_message() );
            }
            wp_send_json_success( $rows );
        } catch (\Throwable $e) {
            Logger::log('get_provider_bookings failed', [
                'exception' => $e->getMessage(),
                'code' => $e->getCode(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error(__('Failed to fetch bookings.', 'mybookaro'));
        }
    }

    public function get_owner_bookings(): void
    {
        check_ajax_referer('bookaro_nonce', 'security');
        try {
            $rows = $this->actions->get_owner_bookings( get_current_user_id() );
            if ( is_wp_error( $rows ) ) {
                wp_send_json_error( $rows->get_error_message() );
            }
            wp_send_json_success( $rows );
        } catch (\Throwable $e) {
            Logger::log('get_owner_bookings failed', [
                'exception' => $e->getMessage(),
                'code' => $e->getCode(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error(__('Failed to fetch bookings.', 'mybookaro'));
        }
    }

    public function get_notification_logs(): void
    {
        check_ajax_referer( 'bookaro_nonce', 'security' );
        $is_admin = current_user_can( 'manage_options' );

        $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
        $booking_id = absint( $payload['booking_id'] ?? 0 );

        try {
            $logs = $this->actions->get_notification_logs( $booking_id, get_current_user_id(), $is_admin );
            if ( is_wp_error( $logs ) ) {
                wp_send_json_error( $logs->get_error_message() );
            }
            wp_send_json_success( $logs );
        } catch ( \Throwable $e ) {
            Logger::log( 'get_notification_logs failed', [
                'exception' => $e->getMessage(),
                'code'      => $e->getCode(),
                'trace'     => $e->getTraceAsString(),
            ] );
            wp_send_json_error( __( 'Failed to load notification logs.', 'mybookaro' ) );
        }
    }

    public function cancel_booking(): void
    {
        check_ajax_referer('bookaro_nonce', 'security');

        $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
        $booking_id = absint( $payload['booking_id'] ?? 0 );
        $reason     = sanitize_text_field( $payload['cancel_reason'] ?? '' );

        try {
            $result = $this->actions->cancel_booking( $booking_id, get_current_user_id(), $reason );
            if ( is_wp_error( $result ) ) {
                wp_send_json_error( $result->get_error_message() );
            }
            if ( is_array( $result ) ) {
                wp_send_json_success( $result );
            }
            if ($result) {
                wp_send_json_success(__('Booking cancelled successfully.', 'mybookaro'));
            }
            wp_send_json_error(__('You cannot cancel this booking.', 'mybookaro'));
        } catch (\Throwable $e) {
            Logger::log('cancel_booking failed', [
                'exception' => $e->getMessage(),
                'code'      => $e->getCode(),
                'trace'     => $e->getTraceAsString(),
            ]);
            wp_send_json_error(__('You cannot cancel this booking.', 'mybookaro'));
        }
    }

    public function add_note(): void
    {
        check_ajax_referer('bookaro_nonce', 'security');

        $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
        $booking_id = absint( $payload['booking_id'] ?? 0 );
        $note       = sanitize_textarea_field( $payload['note'] ?? '' );

        try {
            $result = $this->actions->add_note( $booking_id, get_current_user_id(), $note );
            if ( is_wp_error( $result ) ) {
                wp_send_json_error( $result->get_error_message() );
            }
            if ( $result ) {
                wp_send_json_success(__('Note saved.', 'mybookaro'));
            }
            wp_send_json_error(__('Failed to save note.', 'mybookaro'));
        } catch (\Throwable $e) {
            Logger::log('add_note failed', [
                'exception' => $e->getMessage(),
                'code'      => $e->getCode(),
                'trace'     => $e->getTraceAsString(),
            ]);
            wp_send_json_error(__('Failed to save note.', 'mybookaro'));
        }
    }

    public function reschedule_booking(): void
    {
        check_ajax_referer('bookaro_nonce', 'security');

        $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
        $payload = $this->actions->sanitize_booking_payload( $payload, [ 'source' => 'ajax', 'action' => 'reschedule_booking' ] );
        $booking_id = absint( $payload['booking_id'] ?? 0 );

        try {
            $result = $this->actions->reschedule_booking( $booking_id, get_current_user_id(), $payload );
            if ( is_wp_error( $result ) ) {
                wp_send_json_error( $result->get_error_message() );
            }
            if ( is_array( $result ) ) {
                wp_send_json_success( $result );
            }
            if ($result) {
                wp_send_json_success(__('Booking rescheduled successfully.', 'mybookaro'));
            }
            wp_send_json_error(__('Failed to reschedule booking.', 'mybookaro'));
        } catch (\Throwable $e) {
            Logger::log('reschedule_booking failed', [
                'exception' => $e->getMessage(),
                'code'      => $e->getCode(),
                'trace'     => $e->getTraceAsString(),
            ]);
            wp_send_json_error(__('Failed to reschedule booking.', 'mybookaro'));
        }
    }

    public function handle_update_status(): void
    {
        check_ajax_referer('bookaro_nonce', 'security');
        $is_admin = current_user_can( 'manage_options' );
        $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
        $booking_id = absint( $payload['booking_id'] ?? 0 );
        $new_status = sanitize_text_field( $payload['new_status'] ?? $payload['status'] ?? '' );

        try {
            $result = $this->actions->update_status( $booking_id, $new_status, get_current_user_id(), $is_admin );
            if ( is_wp_error( $result ) ) {
                wp_send_json_error( $result->get_error_message() );
            }
            wp_send_json_success( __( 'Booking status updated.', 'mybookaro' ) );
        } catch ( \Throwable $e ) {
            Logger::log('handle_update_status failed', [
                'exception' => $e->getMessage(),
                'code'      => $e->getCode(),
                'trace'     => $e->getTraceAsString(),
            ]);
            wp_send_json_error( __( 'Failed to update booking status.', 'mybookaro' ) );
        }
    }

    public function handle_bulk_update_status(): void
    {
        check_ajax_referer('bookaro_nonce', 'security');
        $is_admin = current_user_can( 'manage_options' );

        $payload = is_array( $_POST ) ? wp_unslash( $_POST ) : [];
        $action = sanitize_text_field( $payload['bulk_action'] ?? '' );
        $raw_ids = $payload['booking_ids'] ?? [];
        if ( ! is_array( $raw_ids ) ) {
            $raw_ids = [];
        }
        $booking_ids = array_values( array_filter( array_map( 'absint', $raw_ids ) ) );

        $result = $this->actions->bulk_update_status( $action, $booking_ids, get_current_user_id(), $is_admin );
        if ( is_wp_error( $result ) ) {
            wp_send_json_error( $result->get_error_message() );
        }
        wp_send_json_success( $result );
    }
}
