<?php

namespace RadiusTheme\RadiusBooking\Services;

use RadiusTheme\RadiusBooking\Core\Container\Container;
use RadiusTheme\RadiusBooking\Core\Support\Collection;
use RadiusTheme\RadiusBooking\Models\User;
use RadiusTheme\RadiusBooking\Repositories\EmployeeRepository;
use RadiusTheme\RadiusBooking\Repositories\UserProfileRepository;
use RadiusTheme\RadiusBooking\Repositories\UserRepository;
use function Avifinfo\read;

/**
 * Business logic layer for Employee Panel.
 */
class EmployeePanelService {

	private UserRepository $userRepo;

	private EmployeeRepository $employeeRepo;

	/**
	 * Constructor.
	 *
	 * @param UserRepository $userRepo User repository instance.
	 * @param EmployeeRepository $employeeRepo Employee repository instance.
	 */
	public function __construct( UserRepository $userRepo, EmployeeRepository $employeeRepo ) {
		$this->userRepo     = $userRepo;
		$this->employeeRepo = $employeeRepo;
	}

	/**
	 * Get comprehensive dashboard data for an employee.
	 *
	 * @param int $employee_id Employee ID.
	 * @param int $appointments_page Page number for appointments.
	 * @param int $appointments_per_page Items per page for appointments.
	 * @param int $clients_page Page number for clients.
	 * @param int $clients_per_page Items per page for clients.
	 *
	 * @return array Dashboard data including stats, appointments, clients, and services.
	 */
	public function getDashboardData( $employee_id ) {
		$employee = $this->employeeRepo->find( $employee_id );

		if ( ! $employee ) {
			return array(
				'success' => false,
				'message' => __( 'Employee not found.', 'radius-booking' ),
			);
		}

		$today = wp_date( 'Y-m-d' );

		// Gather all dashboard data.
		$stats              = array(
			'today_appointments'     => $this->employeeRepo->getTodayAppointmentCount( $employee_id, $today ),
			'total_completed'        => $this->employeeRepo->getCompletedAppointmentCount( $employee_id ),
			'total_active_clients'   => $this->employeeRepo->getActiveClientCount( $employee_id ),
			'total_earnings'         => $this->employeeRepo->getTotalEarnings( $employee_id ),
			'pending_appointments'   => $this->employeeRepo->getPendingAppointmentCount( $employee_id ),
			'cancelled_appointments' => $this->employeeRepo->getCancelledAppointmentCount( $employee_id ),
		);
		$services           = $this->userRepo->getUserServices( $employee_id );
		$today_appointments = $this->employeeRepo->getTodayAppointments( $employee_id, $today );

		$today_list = array_map(
			function ( $appointment ) {
				return apply_filters( 'rtrb_my_booking_item_data', (object) $appointment );
			},
			is_array( $today_appointments ) ? $today_appointments : $today_appointments->toArray()
		);

		return array(
			'success'            => true,
			'stats'              => $stats,
			'today_appointments' => $today_list,
			'services'           => $services,
		);
	}

	/**
	 * Get paginated appointments for an employee.
	 *
	 * @param int $employee_id Employee ID.
	 * @param int $page Current page number.
	 * @param int $per_page Items per page.
	 *
	 * @return array Paginated appointments data.
	 */
	public function getAppointments( $employee_id, $page = 1, $per_page = 10, $search = '', $status = '' ) {
		$offset      = ( $page - 1 ) * $per_page;
		$booking     = $this->employeeRepo->getPaginatedAppointments(
			$employee_id,
			$per_page,
			$offset,
			$search,
			$status
		);
		$total_items = $this->employeeRepo->appointmentCount( $employee_id, $status );

		$booking_list = array_map(
			function ( $item ) {
				return apply_filters( 'rtrb_my_booking_item_data', (object) $item );
			},
			is_array( $booking ) ? $booking : $booking->toArray()
		);

		return $this->paginate( $booking_list, $page, $per_page, $total_items );
	}

	/**
	 * Get paginated clients for an employee.
	 *
	 * @param int $employee_id Employee ID.
	 * @param int $page Current page number.
	 * @param int $per_page Items per page.
	 *
	 * @return array Paginated clients data.
	 */
	public function getClients( $employee_id, $page = 1, $per_page = 10 ) {
		$offset  = ( $page - 1 ) * $per_page;
		$clients = $this->employeeRepo->getPaginatedClients(
			$employee_id,
			$per_page,
			$offset
		);

		// Get total unique clients count.
		$total_items = $this->employeeRepo->getActiveClientCount( $employee_id );

		return $this->paginate( $clients, $page, $per_page, $total_items );
	}

	public function getPaymentData( $employee_id, $date_filter, $page = 1, $per_page = 10, $status = '', $search = '' ) {
		$offset        = ( $page - 1 ) * $per_page;
		$date_range    = $this->employeeRepo->getDateRangeForFilter( $date_filter );
		$payments_data = $this->employeeRepo->getPaginatedPayments( $employee_id, $date_range, $per_page, $offset, $status, $search );

		$payments     = ! empty( $payments_data['data'] ) ? $payments_data['data'] : [];
		$status_total = ! empty( $payments_data['count'] ) ? $payments_data['count'] : 0;
		$statistics   = $this->employeeRepo->getTotalPaymentCount( $employee_id, $date_range );
		$data         = array(
			'statistics' => $statistics,
			'payments'   => $payments
		);

		return $this->paginate( $data, $page, $per_page, $status_total );
	}

	public function getScheduleData( $employee_id, $params ) {
		$page     = $params['page'] ?? 1;
		$per_page = $params['per_page'] ?? 10;
		$search   = $params['search'] ?? '';
		$status   = $params['status'] ?? '';

		$appointments = $this->getAppointments( $employee_id, $page, $per_page, $search, $status );

		$total_pending   = $this->employeeRepo->getPendingAppointmentCount( $employee_id );
		$total_completed = $this->employeeRepo->getCompletedAppointmentCount( $employee_id );
		$total_cancelled = $this->employeeRepo->getCancelledAppointmentCount( $employee_id );
		$total_confirmed = $this->employeeRepo->getConfirmedAppointmentCount( $employee_id );
		$total_items     = $total_pending + $total_completed + $total_cancelled + $total_confirmed;

		return array(
			'appointments' => $appointments,
			'statistics'   => array(
				'pending'   => $total_pending,
				'completed' => $total_completed,
				'cancelled' => $total_cancelled,
				'confirmed' => $total_confirmed,
				'all'       => $total_items
			)
		);

	}

	public function updateAppointmentStatus( $appointment_id, $service, $status, $request ) {
		return $service->executeStatusChange( $service, $appointment_id, $status, $request );
	}

	public function getProfileData( $employee_id ) {
		$user_profile                    = (array) $this->userRepo->get_profile( $employee_id );
		$user_profile['image_full_path'] = $this->userRepo->getImageUrl( $user_profile['id'] );
		$user                            = (array) User::where( 'id', $employee_id )->first();

		return array_merge( $user_profile, $user );
	}

	public function updateProfileData( $request ) {
		$employee_id     = $request->get_param( 'employee_id' );
		$user            = $this->userRepo->find( $employee_id );
		$data            = $request->get_params();
		$data['user_id'] = $employee_id;
		$user->update( $request->get_params() );
		$user_profile = Container::resolve( UserProfileRepository::class );
		$user_profile->updateProfile( $employee_id, $data );

		return $this->getProfileData( $employee_id );
	}

	public function changePassword( $request ) {
		$employee_id      = $request->get_param( 'employee_id' );
		$current_password = $request->get_param( 'current_password' );
		$new_password     = $request->get_param( 'new_password' );

		$user_service = Container::resolve( UserService::class );
		$result       = $user_service->updatePassword( $employee_id, $current_password, $new_password );

		return $result;
	}

	/**
	 * Build a standardized paginated response array.
	 *
	 * @param array $data The data items for the current page.
	 * @param int $page The current page number.
	 * @param int $per_page The number of items per page.
	 * @param int $total_items The total number of items across all pages.
	 *
	 * @return array The formatted paginated response with data and pagination metadata.
	 */
	public function paginate( array $data, int $page, int $per_page, int $total_items ): array {
		$total_pages = $per_page > 0 ? (int) ceil( $total_items / $per_page ) : 0;

		return array(
			'data'       => $data,
			'pagination' => array(
				'current_page' => $page,
				'per_page'     => $per_page,
				'total_items'  => $total_items,
				'total_pages'  => $total_pages,
				'has_previous' => $page > 1,
				'has_next'     => $page < $total_pages,
			),
		);
	}
}