<?php

namespace RadiusTheme\RadiusBooking\Controllers;

use RadiusTheme\RadiusBooking\Core\Api\ApiResponse;
use RadiusTheme\RadiusBooking\Core\Api\Middleware\AuthMiddleware;
use RadiusTheme\RadiusBooking\Core\Api\Middleware\PermissionMiddleware;
use RadiusTheme\RadiusBooking\Core\Container\Container;
use RadiusTheme\RadiusBooking\Helpers\SettingsHelper;
use RadiusTheme\RadiusBooking\Models\Appointment;
use RadiusTheme\RadiusBooking\Models\EmployeeService;
use RadiusTheme\RadiusBooking\Models\Service;
use RadiusTheme\RadiusBooking\Models\User;
use RadiusTheme\RadiusBooking\Repositories\UserProfileRepository;
use RadiusTheme\RadiusBooking\Repositories\ServiceRepository;
use RadiusTheme\RadiusBooking\Repositories\UserRepository;
use RadiusTheme\RadiusBooking\Resources\UserResource;
use RadiusTheme\RadiusBooking\Services\AppointmentService;
use RadiusTheme\RadiusBooking\Services\EmployeePanelService;
use RadiusTheme\RadiusBooking\Services\UserService;
use RadiusTheme\RadiusBooking\Services\EmployeeServices\UserWeekdayDataService;
use WP_REST_Request;
use RadiusTheme\RadiusBooking\Abstracts\BaseController;

/**
 * Api/Controllers/EmployeePanelController.php
 * EmployeePanel API controller
 */
class EmployeePanelController extends BaseController {

	public function __construct() {
		parent::__construct( new UserRepository() );
		$this->middleware[] = new AuthMiddleware();
		$this->middleware[] = new PermissionMiddleware( 'radius_booking_employee' );
	}

	protected function transformItem( $item ): array {
		return ( new UserResource() )->transform( $item );
	}

	protected function transformCollection( array $items ): array {
		return UserResource::collection( $items );
	}

	/**
	 * Validation rules for create and update.
	 *
	 * @param string $context 'create' or 'update'
	 *
	 * @return array
	 */
	protected function getValidationRules( $request, string $context = 'create' ): array {
		$rules = [
			// Add your fields below
			// 'field_name' => [ new RequiredRule(), new IntegerRule() ],
		];

		if ( $context === 'update' ) {
			// Make some fields optional
			// unset( $rules['field_name'] );
		}

		return $rules;
	}

	public function employeeDashboard( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			$employee_id = $request->get_param( 'employee_id' );
			$user        = $this->repository->find( $employee_id );
			$is_employee = $user->is_employee();
			if ( ! $is_employee ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}
			$employee_service = Container::resolve( EmployeePanelService::class );
			$dashboard_data   = $employee_service->getDashboardData( $employee_id );

			return ApiResponse::success( $dashboard_data, 'Resource fetch successfully' )->send();
		} );
	}

	public function employeeSchedule( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			$employee_id = $request->get_param( 'employee_id' );
			$user        = $this->repository->find( $employee_id );
			$is_employee = $user->is_employee();
			if ( ! $is_employee ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}
			$all_params       = $request->get_params();
			$employee_service = Container::resolve( EmployeePanelService::class );
			$schedule_data    = $employee_service->getScheduleData( $employee_id, $all_params );

			return ApiResponse::success( $schedule_data, 'Schedule info fetch successfully' )->send();
		} );
	}

	public function employeePayment( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			$employee_id = $request->get_param( 'employee_id' );
			$user        = $this->repository->find( $employee_id );
			$is_employee = $user->is_employee();
			if ( ! $is_employee ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}
			$page             = $request->get_param( 'page' );
			$per_page         = $request->get_param( 'per_page' );
			$date_filter      = $request->get_param( 'date_filter' );
			$status           = $request->get_param( 'status' );
			$search           = $request->get_param( 'search' );
			$employee_service = Container::resolve( EmployeePanelService::class );
			$payment_data     = $employee_service->getPaymentData( $employee_id, $date_filter, $page, $per_page, $status, $search );

			return ApiResponse::success( $payment_data, 'Payment info fetch successfully' )->send();
		} );
	}

	public function employeeCustomer( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			$employee_id = $request->get_param( 'employee_id' );
			$user        = $this->repository->find( $employee_id );
			$is_employee = $user->is_employee();
			if ( ! $is_employee ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}
			$page             = $request->get_param( 'page' );
			$per_page         = $request->get_param( 'per_page' );
			$employee_service = Container::resolve( EmployeePanelService::class );
			$customer_data    = $employee_service->getClients( $employee_id, $page, $per_page );

			return ApiResponse::success( $customer_data, 'Payment info fetch successfully' )->send();
		} );
	}

	public function updateAppointmentStatus( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			$appointment_id = $request->get_param( 'appointment_id' );
			$employee_id    = $request->get_param( 'employee_id' );
			$user           = $this->repository->find( $employee_id );
			$is_employee    = $user->is_employee();
			if ( ! $is_employee ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}
			$status           = $request->get_param( 'status' );
			$employee_service = Container::resolve( EmployeePanelService::class );
			$service          = Container::resolve( AppointmentService::class );

			$result = $employee_service->updateAppointmentStatus( $appointment_id, $service, $status, $request );
			if ( is_wp_error( $result ) ) {
				return ApiResponse::error( $result->get_error_message() )->send();
			}
			if ( ! $result ) {
				return ApiResponse::error( 'Failed to update appointment status' )->send();
			}
			$appointment = Appointment::find( $appointment_id );
			$service->fireStatusAction( $appointment );
			$data = [
				'status' => $status,
				'id'     => $appointment_id,
			];

			return ApiResponse::success( $data, 'Appointment status updated successfully' )->send();
		} );
	}

	public function employeeProfile( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			$employee_id = $request->get_param( 'employee_id' );
			$user        = $this->repository->find( $employee_id );
			$is_employee = $user->is_employee();
			if ( ! $is_employee ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}
			$employee_service = Container::resolve( EmployeePanelService::class );
			$profile_data     = $employee_service->getProfileData( $employee_id );
			return ApiResponse::success( $profile_data, 'Profile info fetch successfully' )->send();
		});
	}

	public function employeeUpdateProfile( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			$employee_id = $request->get_param( 'employee_id' );
			$user        = $this->repository->find( $employee_id );
			$is_employee = $user->is_employee();
			if ( ! $is_employee ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}
			$employee_service = Container::resolve( EmployeePanelService::class );
			$profile_data     = $employee_service->updateProfileData( $request );
			return ApiResponse::success( $profile_data, 'Profile info updated successfully' )->send();
		});
	}

	public function employeeChangePassword( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			$employee_id = $request->get_param( 'employee_id' );
			$user        = $this->repository->find( $employee_id );
			$is_employee = $user->is_employee();
			if ( ! $is_employee ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}
			$employee_service = Container::resolve( EmployeePanelService::class );
			$profile_data     = $employee_service->changePassword( $request );
			if( $profile_data['success'] === false ) {
				return ApiResponse::error( $profile_data['message'] ?? 'Password change failed' )->send();
			}
			return ApiResponse::success( $profile_data, 'Password changed successfully' )->send();
		});
	}

	// ─── Staff Permission Helpers ─────────────────────────────────────

	/**
	 * Get staff permissions from settings.
	 *
	 * @return array
	 */
	private function getStaffPermissions() {
		return SettingsHelper::get_setting( 'staffPermissions' );
	}

	/**
	 * Check if a permission is allowed (and pro-gated where needed).
	 *
	 * @param string $permission Permission key.
	 *
	 * @return bool
	 */
	private function hasPermission( $permission ) {
		$perms = $this->getStaffPermissions();

		if ( empty( $perms[ $permission ] ) ) {
			return false;
		}

		// Pro-gated permissions.
		$pro_only = array( 'canCreateService', 'canDeleteService', 'canManageStaff' );
		if ( in_array( $permission, $pro_only, true ) && ! rtrb_pro_active() ) {
			return false;
		}

		// Sub-staff cannot manage staff or services.
		$sub_staff_blocked = array( 'canManageStaff', 'canEditService', 'canCreateService', 'canDeleteService' );
		if ( in_array( $permission, $sub_staff_blocked, true ) && $this->isSubStaff() ) {
			return false;
		}

		return true;
	}

	/**
	 * Check if the current logged-in user is a sub-staff (created by another employee).
	 *
	 * @return bool
	 */
	private function isSubStaff() {
		$wp_user_id = get_current_user_id();
		if ( ! $wp_user_id ) {
			return false;
		}

		$profile_repo = Container::resolve( UserProfileRepository::class );
		$profile      = $profile_repo->findProfileByWPId( $wp_user_id );
		if ( ! $profile || empty( $profile->user_id ) ) {
			return false;
		}

		$user = User::find( $profile->user_id );

		return $user && ! empty( $user->created_by );
	}

	/**
	 * Verify the requesting user is the employee and return them, or send error.
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \RadiusTheme\RadiusBooking\Models\User|null
	 */
	private function verifyEmployee( WP_REST_Request $request ) {
		$employee_id = $request->get_param( 'employee_id' );
		$user        = $this->repository->find( $employee_id );

		if ( ! $user || ! $user->is_employee() ) {
			return null;
		}

		return $user;
	}

	// ─── Employee Service CRUD ────────────────────────────────────────

	/**
	 * Get a single service for editing.
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function getService( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$service_id = $request->get_param( 'service_id' );
			$service    = Service::find( $service_id );

			if ( ! $service ) {
				return ApiResponse::error( 'Service not found', 404 )->send();
			}

			// Verify the employee is assigned to this service.
			$employee_id = $request->get_param( 'employee_id' );
			$assigned    = EmployeeService::where( 'service_id', $service_id )
				->where( 'user_id', $employee_id )
				->first();

			if ( ! $assigned ) {
				return ApiResponse::error( 'You are not assigned to this service', 403 )->send();
			}

			$service_repo = Container::resolve( ServiceRepository::class );
			$data         = $service_repo->find( $service_id );

			return ApiResponse::success( $data ? $data->toArray() : array(), 'Service fetched successfully' )->send();
		} );
	}

	/**
	 * Update an assigned service (requires canEditService permission).
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function updateService( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->hasPermission( 'canEditService' ) ) {
				return ApiResponse::error( 'You do not have permission to edit services', 403 )->send();
			}

			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$employee_id = $request->get_param( 'employee_id' );
			$service_id  = $request->get_param( 'service_id' );

			// Verify assignment.
			$assigned = EmployeeService::where( 'service_id', $service_id )
				->where( 'user_id', $employee_id )
				->first();

			if ( ! $assigned ) {
				return ApiResponse::error( 'You are not assigned to this service', 403 )->send();
			}

			$service_repo = Container::resolve( ServiceRepository::class );
			$params       = $request->get_params();

			// Employees can update these fields.
			$allowed = array(
				'name', 'description', 'price', 'duration', 'category_id', 'color',
				'picture_full_path', 'picture_thumb_path',
				'time_before', 'time_after', 'is_visible',
			);

			// Pro-only fields — only allow when Pro is active.
			if ( rtrb_pro_active() ) {
				$pro_fields = array(
					'min_capacity', 'max_capacity', 'bringing_anyone', 'aggregated_price', 'max_extra_people',
					'recurring_cycle', 'recurring_sub', 'recurring_payment',
					'deposit_payment', 'deposit_type', 'deposit', 'deposit_per_person', 'full_payment',
					'settings',
				);
				$allowed = array_merge( $allowed, $pro_fields );
			}

			$data = array_intersect_key( $params, array_flip( $allowed ) );

			$service_repo->update( $service_id, $data );

			$updated = $service_repo->find( $service_id );
			return ApiResponse::success(
				$updated ? $updated->toArray() : array(),
				'Service updated successfully'
			)->send();
		} );
	}

	/**
	 * Create a new service (requires canCreateService permission — Pro).
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function createService( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->hasPermission( 'canCreateService' ) ) {
				return ApiResponse::error( 'You do not have permission to create services', 403 )->send();
			}

			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$employee_id = $request->get_param( 'employee_id' );
			$params      = $request->get_params();

			// Validate required fields.
			if ( empty( $params['name'] ) || empty( $params['duration'] ) ) {
				return ApiResponse::error( 'Name and duration are required', 422 )->send();
			}

			$service_repo = Container::resolve( ServiceRepository::class );
			$service      = $service_repo->create( $params );

			// Auto-assign the creating employee to this service.
			if ( $service ) {
				EmployeeService::create( array(
					'user_id'    => $employee_id,
					'service_id' => $service->id,
					'price'      => $params['price'] ?? 0,
				) );
			}

			$created = $service_repo->find( $service->id );
			return ApiResponse::success(
				$created ? $created->toArray() : array(),
				'Service created successfully'
			)->send();
		} );
	}

	/**
	 * Delete a service (requires canDeleteService permission — Pro).
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function deleteService( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->hasPermission( 'canDeleteService' ) ) {
				return ApiResponse::error( 'You do not have permission to delete services', 403 )->send();
			}

			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$employee_id = $request->get_param( 'employee_id' );
			$service_id  = $request->get_param( 'service_id' );

			// Verify assignment.
			$assigned = EmployeeService::where( 'service_id', $service_id )
				->where( 'user_id', $employee_id )
				->first();

			if ( ! $assigned ) {
				return ApiResponse::error( 'You are not assigned to this service', 403 )->send();
			}

			$service_repo = Container::resolve( ServiceRepository::class );
			$service      = Service::find( $service_id );

			// If this service is linked to a Classified Listing, remove booking meta from the listing.
			if ( $service && ! empty( $service->listing_id ) ) {
				$listing_id = (int) $service->listing_id;
				delete_post_meta( $listing_id, '_rtrb_booking_enabled' );
				delete_post_meta( $listing_id, '_rtrb_booking_duration' );
				delete_post_meta( $listing_id, '_rtrb_booking_category_id' );
			}

			$service_repo->delete( $service_id );

			return ApiResponse::success( null, 'Service deleted successfully' )->send();
		} );
	}

	// ─── Employee Staff Management ────────────────────────────────────

	/**
	 * List all staff members (requires canManageStaff — Pro).
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function listStaff( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->hasPermission( 'canManageStaff' ) ) {
				return ApiResponse::error( 'You do not have permission to manage staff', 403 )->send();
			}

			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$employee_id = $request->get_param( 'employee_id' );

			// Only fetch staff created by the current employee.
			$users = User::where( 'created_by', $employee_id )
				->where( 'user_type', 'employee' )
				->get();

			$user_profile_repo = Container::resolve( UserProfileRepository::class );
			$staff_list        = array();

			foreach ( $users as $user ) {
				$profile = $user_profile_repo->findBy( array( 'user_id' => (int) $user->id ) );

				$assigned       = EmployeeService::where( 'user_id', $user->id )->get();
				$service_ids    = array();
				$service_prices = array();
				foreach ( $assigned as $es ) {
					$sid                    = (int) $es->service_id;
					$service_ids[]          = $sid;
					$service_prices[ $sid ] = (float) $es->price;
				}

				$image_url = '';
				if ( $profile && ! empty( $profile->image_id ) ) {
					$image_url = wp_get_attachment_image_url( $profile->image_id, 'thumbnail' ) ?: '';
				}

				$staff_list[] = array(
					'id'             => (int) $user->id,
					'email'          => $user->email,
					'first_name'     => $profile ? $profile->first_name : '',
					'last_name'      => $profile ? $profile->last_name : '',
					'phone'          => $profile ? $profile->phone : '',
					'status'         => $user->status ?? 'active',
					'service_ids'    => $service_ids,
					'service_prices' => (object) $service_prices,
					'note'           => $profile ? ( $profile->note ?? '' ) : '',
					'time_zone'      => $profile ? ( $profile->time_zone ?? '' ) : '',
					'image_id'       => $profile ? ( $profile->image_id ?? 0 ) : 0,
					'image_url'      => $image_url,
				);
			}

			return ApiResponse::success( $staff_list, 'Staff list fetched successfully' )->send();
		} );
	}

	/**
	 * Get a single staff member for editing (requires canManageStaff — Pro).
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function getStaff( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->hasPermission( 'canManageStaff' ) ) {
				return ApiResponse::error( 'You do not have permission to manage staff', 403 )->send();
			}

			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$staff_id = $request->get_param( 'staff_id' );
			$staff    = $this->repository->find( $staff_id );

			if ( ! $staff || ! $staff->is_employee() ) {
				return ApiResponse::error( 'Staff member not found', 404 )->send();
			}

			return ApiResponse::success( $this->transformItem( $staff ), 'Staff fetched successfully' )->send();
		} );
	}

	/**
	 * Create a new staff member (requires canManageStaff — Pro).
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function createStaff( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->hasPermission( 'canManageStaff' ) ) {
				return ApiResponse::error( 'You do not have permission to manage staff', 403 )->send();
			}

			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$employee_id  = $request->get_param( 'employee_id' );
			$params       = $request->get_params();
			$params['created_by'] = (int) $employee_id;

			$user_service = Container::resolve( UserService::class );
			$result       = $user_service->createEmployee( $params );

			if ( is_wp_error( $result ) ) {
				return ApiResponse::error( $result->get_error_message() )->send();
			}

			// Assign services from the main staff to the new sub-staff.
			$service_ids    = $request->get_param( 'service_ids' );
			$service_prices = $request->get_param( 'service_prices' );
			if ( ! empty( $service_ids ) && is_array( $service_ids ) ) {
				$main_service_ids = array_map(
					function ( $es ) {
						return (int) $es->service_id;
					},
					EmployeeService::where( 'user_id', $employee_id )->get()
				);

				foreach ( $service_ids as $sid ) {
					$sid = (int) $sid;
					if ( ! in_array( $sid, $main_service_ids, true ) ) {
						continue;
					}

					// Use custom price if sent, else main staff's price.
					$custom_price = null;
					if ( is_array( $service_prices ) && isset( $service_prices[ $sid ] ) ) {
						$custom_price = (float) $service_prices[ $sid ];
					} elseif ( is_object( $service_prices ) && isset( $service_prices->$sid ) ) {
						$custom_price = (float) $service_prices->$sid;
					}

					$existing = EmployeeService::where( 'user_id', $result['id'] )
						->where( 'service_id', $sid )
						->first();
					if ( ! $existing ) {
						if ( null === $custom_price ) {
							$main_es      = EmployeeService::where( 'user_id', $employee_id )
								->where( 'service_id', $sid )
								->first();
							$custom_price = $main_es ? $main_es->price : 0;
						}
						$es = new EmployeeService();
						$es->fill(
							array(
								'user_id'    => $result['id'],
								'service_id' => $sid,
								'price'      => $custom_price,
							)
						);
						$es->save();
					}
				}
				$result['service_ids'] = array_values( array_map( 'intval', $service_ids ) );
			}

			return ApiResponse::success( $result, 'Staff member created successfully' )->send();
		} );
	}

	/**
	 * Update a staff member (requires canManageStaff — Pro).
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function updateStaff( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->hasPermission( 'canManageStaff' ) ) {
				return ApiResponse::error( 'You do not have permission to manage staff', 403 )->send();
			}

			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$staff_id = $request->get_param( 'staff_id' );
			$staff    = $this->repository->find( $staff_id );

			if ( ! $staff || ! $staff->is_employee() ) {
				return ApiResponse::error( 'Staff member not found', 404 )->send();
			}

			$user_service = Container::resolve( UserService::class );
			$result       = $user_service->updateEmployee( $staff_id, $request->get_params() );

			if ( is_wp_error( $result ) ) {
				return ApiResponse::error( $result->get_error_message() )->send();
			}

			// Sync service assignments if provided.
			$service_ids    = $request->get_param( 'service_ids' );
			$service_prices = $request->get_param( 'service_prices' );
			if ( is_array( $service_ids ) ) {
				$employee_id      = $request->get_param( 'employee_id' );
				$main_service_ids = array_map(
					function ( $es ) {
						return (int) $es->service_id;
					},
					EmployeeService::where( 'user_id', $employee_id )->get()
				);

				// Remove services no longer selected.
				$current = EmployeeService::where( 'user_id', $staff_id )->get();
				foreach ( $current as $es ) {
					if ( ! in_array( (int) $es->service_id, array_map( 'intval', $service_ids ), true ) ) {
						$es->delete();
					}
				}

				// Add or update selected services.
				foreach ( $service_ids as $sid ) {
					$sid = (int) $sid;
					if ( ! in_array( $sid, $main_service_ids, true ) ) {
						continue;
					}

					// Determine price: use custom price if sent, else main staff's price.
					$custom_price = null;
					if ( is_array( $service_prices ) && isset( $service_prices[ $sid ] ) ) {
						$custom_price = (float) $service_prices[ $sid ];
					} elseif ( is_object( $service_prices ) && isset( $service_prices->$sid ) ) {
						$custom_price = (float) $service_prices->$sid;
					}

					$existing_raw = EmployeeService::where( 'user_id', $staff_id )
						->where( 'service_id', $sid )
						->first();

					if ( $existing_raw ) {
						// Update price if custom price was sent.
						if ( null !== $custom_price ) {
							$existing_model = EmployeeService::hydrate( $existing_raw );
							$existing_model->fill( array( 'price' => $custom_price ) );
							$existing_model->save();
						}
					} else {
						// Create new assignment.
						if ( null === $custom_price ) {
							$main_es_raw  = EmployeeService::where( 'user_id', $employee_id )
								->where( 'service_id', $sid )
								->first();
							$custom_price = $main_es_raw ? $main_es_raw->price : 0;
						}
						$es = new EmployeeService();
						$es->fill(
							array(
								'user_id'    => $staff_id,
								'service_id' => $sid,
								'price'      => $custom_price,
							)
						);
						$es->save();
					}
				}
				$result['service_ids'] = array_values( array_map( 'intval', $service_ids ) );
			}

			return ApiResponse::success( $result, 'Staff member updated successfully' )->send();
		} );
	}

	/**
	 * Delete a staff member (requires canManageStaff — Pro).
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function deleteStaff( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->hasPermission( 'canManageStaff' ) ) {
				return ApiResponse::error( 'You do not have permission to manage staff', 403 )->send();
			}

			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$staff_id    = $request->get_param( 'staff_id' );
			$employee_id = $request->get_param( 'employee_id' );

			// Cannot delete yourself.
			if ( (int) $staff_id === (int) $employee_id ) {
				return ApiResponse::error( 'You cannot delete your own account', 400 )->send();
			}

			$staff = $this->repository->find( $staff_id );
			if ( ! $staff || ! $staff->is_employee() ) {
				return ApiResponse::error( 'Staff member not found', 404 )->send();
			}

			$this->repository->delete( $staff_id );

			return ApiResponse::success( array(), 'Staff member deleted successfully' )->send();
		} );
	}

	// ─── Employee Schedule Management ────────────────────────────────

	/**
	 * Get the employee's schedule settings (weekdays, days off, special days).
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function getScheduleSettings( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$employee_id      = (int) $request->get_param( 'employee_id' );
			$user_repo        = new UserRepository();
			$weekday_service  = new UserWeekdayDataService();

			// Employee custom data (DB-only).
			$custom_weekdays     = $user_repo->getUserWeekdays( $employee_id );
			$custom_days_off     = $user_repo->getUserDaysOff( $employee_id );
			$custom_special_days = $user_repo->getUserSpecialDays( $employee_id );

			// Global schedule data.
			$global_weekdays     = $weekday_service->getGlobalScheduleAsWeekdays( $employee_id );
			$global_days_off     = $weekday_service->getGlobalHolidaysAsDaysOff();
			$global_special_days = $weekday_service->getGlobalCustomSchedulesAsSpecialDays();

			$data = array(
				'weekdays'              => $custom_weekdays,
				'days_off'              => $custom_days_off,
				'special_days'          => $custom_special_days,
				'global_weekdays'       => $global_weekdays,
				'global_days_off'       => $global_days_off,
				'global_special_days'   => $global_special_days,
				'has_custom_weekdays'   => ! empty( $custom_weekdays ),
				'has_custom_days_off'   => ! empty( $custom_days_off ),
				'has_custom_special_days' => ! empty( $custom_special_days ),
				'is_pro'                => rtrb_pro_active(),
			);

			return ApiResponse::success( $data, 'Schedule settings fetched successfully' )->send();
		} );
	}

	/**
	 * Update the employee's weekly work schedule.
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function updateWeekdays( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$employee_id = $request->get_param( 'employee_id' );
			$weekdays    = $request->get_param( 'weekdays' );

			if ( ! is_array( $weekdays ) ) {
				return ApiResponse::error( 'Invalid weekdays data', 400 )->send();
			}

			$user_service = Container::resolve( UserService::class );
			$user_service->createOrUpdateUserWeekdays( $employee_id, $weekdays );

			$user_repo = new UserRepository();

			return ApiResponse::success(
				$user_repo->getUserWeekdays( $employee_id ),
				'Work schedule updated successfully'
			)->send();
		} );
	}

	/**
	 * Update the employee's days off.
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function updateDaysOff( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$employee_id = $request->get_param( 'employee_id' );
			$days_off    = $request->get_param( 'days_off' );

			if ( ! is_array( $days_off ) ) {
				return ApiResponse::error( 'Invalid days off data', 400 )->send();
			}

			$user_service = Container::resolve( UserService::class );
			$user_service->createOrUpdateUserDaysOff( $employee_id, $days_off );

			$user_repo = new UserRepository();

			return ApiResponse::success(
				$user_repo->getUserDaysOff( $employee_id ),
				'Days off updated successfully'
			)->send();
		} );
	}

	/**
	 * Update the employee's special days schedule.
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function updateSpecialDays( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$employee_id = $request->get_param( 'employee_id' );
			$special_days = $request->get_param( 'special_days' );

			if ( ! is_array( $special_days ) ) {
				return ApiResponse::error( 'Invalid special days data', 400 )->send();
			}

			$user_service = Container::resolve( UserService::class );
			$user_service->createOrUpdateUserSpecialDays( $employee_id, $special_days );

			$user_repo = new UserRepository();

			return ApiResponse::success(
				$user_repo->getUserSpecialDays( $employee_id ),
				'Special days updated successfully'
			)->send();
		} );
	}

	/**
	 * Retrieves the resource type for this controller.
	 *
	 * @return string The resource type, which is 'user' in this case.
	 */
	/**
	 * Get all booking categories (read-only for employees).
	 *
	 * @param WP_REST_Request $request The request.
	 *
	 * @return \WP_REST_Response
	 */
	public function getCategories( WP_REST_Request $request ) {
		return $this->applyMiddleware( $request, function ( $request ) {
			if ( ! $this->verifyEmployee( $request ) ) {
				return ApiResponse::error( 'Invalid User ID', 400 )->send();
			}

			$categories = \RadiusTheme\RadiusBooking\Models\Category::all();
			$list       = array();
			foreach ( $categories as $cat ) {
				$list[] = array(
					'id'   => (int) $cat->id,
					'name' => $cat->name,
				);
			}

			return ApiResponse::success( $list, 'Categories fetched successfully' )->send();
		} );
	}

	protected function getResourceType(): string {
		return "employee_panel";
	}
}
