<?php

namespace SugarCalendarBookings\Appointments\Admin;

use Exception;
use SugarCalendarBookings\Appointments\AppointmentDTO;
use SugarCalendarBookings\Appointments\AppointmentModel;
use SugarCalendarBookings\Appointments\AppointmentService;
use SugarCalendarBookings\Appointments\CreateAppointmentDTO;
use SugarCalendarBookings\Notifications\Emails\EmailService;
use SugarCalendarBookings\Notifications\PaymentNotifier;
use SugarCalendarBookings\Payments\CreatePaymentDTO;
use SugarCalendarBookings\Payments\Gateways\Onsite\OnSitePaymentGateway;
use SugarCalendarBookings\Payments\PaymentModel;
use SugarCalendarBookings\Payments\PaymentService;
use SugarCalendarBookings\Payments\PaymentsHelpers;
use SugarCalendarBookings\Integrations\MeetingManager;
use SugarCalendarBookings\Plugin;
use SugarCalendarBookings\Support\Ajax\AbstractController;

/**
 * Controller for Appointment admin actions.
 *
 * @since 1.0.0
 */
class AppointmentController extends AbstractController {

	/**
	 * Handle appointment creation request.
	 *
	 * @since 1.0.0
	 */
	public function create() {

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( esc_html__( 'You are not allowed to create appointment.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$appointment_form = Plugin::get( AppointmentFormService::class );
		$data             = $this->get_input_data( $appointment_form->rules() );

		$dto = new CreateAppointmentDTO( $data );

		try {
			$appointment = Plugin::get( AppointmentService::class )->create( $dto );
		} catch ( Exception $e ) {
			wp_send_json_error( $e->getMessage() );
		}

		// Check if meeting creation failed (runs synchronously in the appointment_created hook).
		$meeting_error = Plugin::get( MeetingManager::class )->get_last_error();

		if ( $meeting_error ) {
			Plugin::get( AppointmentService::class )->delete( $appointment );

			wp_send_json_error(
				esc_html__( 'Failed to create online meeting. Please check your integration connection and try again.', 'sugar-calendar-bookings-scheduling-appointments-lite' )
			);
		}

		$gateway = 'onsite';

		$payment_dto = new CreatePaymentDTO(
			[
				'customer_id'     => $data['customer_id'],
				'item_id'         => $appointment->id,
				'total_amount'    => $appointment->service->price ?? 0,
				'subtotal_amount' => $appointment->service->price ?? 0,
				'currency'        => PaymentsHelpers::get_currency(),
				'gateway'         => $gateway,
			]
		);

		try {
			Plugin::get( PaymentService::class )->create( $gateway, $payment_dto );
		} catch ( Exception $e ) {
			Plugin::get( AppointmentService::class )->delete( $appointment );

			wp_send_json_error( $e->getMessage() );
		}

		wp_send_json_success(
			[
				'id' => $appointment->id,
			]
		);
	}

	/**
	 * Handle appointment update request.
	 *
	 * @since 1.0.0
	 */
	public function update() {

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( esc_html__( 'You are not allowed to update appointment.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$appointment_form = Plugin::get( AppointmentFormService::class );

		$rules = $appointment_form->rules(
			[
				'id' => 'required|id',
			]
		);

		$data        = $this->get_input_data( $rules );
		$appointment = AppointmentModel::get( $data['id'] );

		if ( ! $appointment ) {
			wp_send_json_error( esc_html__( 'Appointment not found.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$dto = new AppointmentDTO( $data );

		try {
			$appointment = Plugin::get( AppointmentService::class )->update( $appointment, $dto );
		} catch ( Exception $e ) {
			wp_send_json_error( $e->getMessage() );
		}

		$response = [
			'id' => $appointment->id,
		];

		// Include meeting update warning if it failed (appointment is still saved).
		$meeting_error = Plugin::get( MeetingManager::class )->get_last_error();

		if ( $meeting_error ) {
			$response['warning'] = esc_html__( 'Appointment updated, but the online meeting could not be synced. Please check your integration connection.', 'sugar-calendar-bookings-scheduling-appointments-lite' );
		}

		wp_send_json_success( $response );
	}

	/**
	 * Handle appointment cancellation request.
	 *
	 * @since 1.0.0
	 */
	public function cancel() {

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( esc_html__( 'You are not allowed to cancel appointment.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$rules = [
			'id' => 'required|id',
		];

		$data        = $this->get_input_data( $rules );
		$appointment = AppointmentModel::query()
			->with( [ 'payments' => fn( $q ) => $q->select( [ 'id', 'status', 'gateway' ] ) ] )
			->where( 'id', '=', $data['id'], '%d' )
			->first();

		if ( ! $appointment ) {
			wp_send_json_error( esc_html__( 'Appointment not found.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$cancelled = Plugin::get( AppointmentService::class )->cancel( $appointment );

		if ( ! $cancelled ) {
			wp_send_json_error( esc_html__( 'Failed to cancel appointment.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		// Check if appointment has refundable payment.
		$response_data                           = [];
		$response_data['has_refundable_payment'] = false;

		$payment = PaymentsHelpers::get_payment( $appointment );

		if ( $payment && $payment->gateway !== OnSitePaymentGateway::ID && $payment->status === PaymentModel::STATUS_COMPLETED ) {
			$response_data['has_refundable_payment'] = true;
			$response_data['payment_id']             = $payment->id;
		}

		wp_send_json_success( $response_data );
	}

	/**
	 * Handle appointment deletion request.
	 *
	 * @since 1.0.0
	 */
	public function delete() {

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( esc_html__( 'You are not allowed to delete appointment.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$rules = [
			'id' => 'required|id',
		];

		$data        = $this->get_input_data( $rules );
		$appointment = AppointmentModel::get( $data['id'] );

		if ( ! $appointment ) {
			wp_send_json_error( esc_html__( 'Appointment not found.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$appointment->delete();

		wp_send_json_success();
	}

	/**
	 * Get data for appointment creation form.
	 *
	 * @since 1.0.0
	 */
	public function get_create_form_data() {

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( esc_html__( 'You are not allowed to create appointment.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$data = Plugin::get( AppointmentFormService::class )->get_create_form_data();

		wp_send_json_success( $data );
	}

	/**
	 * Get data for appointment edit form.
	 *
	 * @since 1.0.0
	 */
	public function get_edit_form_data() {

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( esc_html__( 'You are not allowed to edit appointment.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$rules = [
			'id' => 'required|id',
		];

		$data        = $this->get_input_data( $rules );
		$appointment = AppointmentModel::get( $data['id'] );

		if ( ! $appointment ) {
			wp_send_json_error( esc_html__( 'Appointment not found.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$data = Plugin::get( AppointmentFormService::class )->get_edit_form_data( $appointment );

		wp_send_json_success( $data );
	}

	/**
	 * Handle appointment navigation to position request.
	 *
	 * @since 1.0.0
	 */
	public function navigate_to_position() {

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( esc_html__( 'You are not allowed to access this resource.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$rules = [
			'position' => 'required|numeric|min:1',
		];

		$data     = $this->get_input_data( $rules );
		$position = (int) $data['position'];

		// TODO: Use a service whenever we have it.
		$appointment_id = $this->get_appointment_id_at_position( $position );

		if ( ! $appointment_id ) {
			wp_send_json_error( esc_html__( 'No appointment found at this position.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		// Return the URL for redirection.
		wp_send_json_success(
			[
				'url' => AppointmentDetailsPage::get_url( $appointment_id ),
			]
		);
	}

	/**
	 * Get appointment ID at a specific position.
	 *
	 * @since 1.0.0
	 *
	 * @param int $position Position in the list (1-based).
	 *
	 * @return int|null Appointment ID or null if position is invalid.
	 */
	private function get_appointment_id_at_position( $position ) {

		// Use efficient query with limit and offset instead of fetching all appointments.
		$appointment = AppointmentModel::query()
			->order_by( 'id', 'ASC' )
			->offset( $position - 1 )
			->limit( 1 )
			->first();

		return $appointment ? $appointment->id : null;
	}

	/**
	 * Handle appointment resend notifications request.
	 *
	 * @since 1.0.0
	 */
	public function resend_notifications() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh, Generic.Metrics.NestingLevel.MaxExceeded

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( esc_html__( 'You are not allowed to resend notifications.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		$rules = [
			'appointment_id'       => 'required|id',
			'notification_types'   => 'required|array',
			'notification_types.*' => 'string',
		];

		$data        = $this->get_input_data( $rules );
		$appointment = AppointmentModel::query()
			->with(
				[
					'customer',
					'employee',
					'service',
					'payments',
				]
			)
			->where( 'id', '=', $data['appointment_id'], '%d' )
			->first();

		if ( ! $appointment ) {
			wp_send_json_error( esc_html__( 'Appointment not found.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
		}

		// Send notification emails.
		$email_service    = Plugin::get( EmailService::class );
		$payment_notifier = Plugin::get( PaymentNotifier::class );

		foreach ( $data['notification_types'] as $notification_type ) {
			if ( $notification_type === 'payment_refund_attendee' ) {
				$payment_notifier->notify( $appointment->payments, '' );
			} else {
				$email_service->send_email( $notification_type, $appointment );
			}
		}

		wp_send_json_success( esc_html__( 'Notifications have been resent successfully.', 'sugar-calendar-bookings-scheduling-appointments-lite' ) );
	}
}
