<?php
/**
 * Instructor Management Class
 *
 * Handles CRUD operations for instructors
 *
 * @package    Karate_Club_Manager
 * @subpackage Karate_Club_Manager/includes/classes
 * @since      1.0.57
 */

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class MACM_Instructor
 *
 * Manages instructors
 *
 * @since 1.0.57
 */
class MACM_Instructor {

	/**
	 * Create a new instructor
	 *
	 * @since 1.0.57
	 * @param array $data Instructor data.
	 * @return int|WP_Error Instructor ID on success, WP_Error on failure.
	 */
	public static function create( $data ) {
		global $wpdb;

		// Validate required fields.
		if ( empty( $data['full_name'] ) ) {
			return new WP_Error( 'missing_name', __( 'Instructor name is required.', 'martial-arts-club-manager' ) );
		}

		// Validate name length.
		if ( strlen( $data['full_name'] ) > 255 ) {
			return new WP_Error( 'name_too_long', __( 'Instructor name must be less than 255 characters.', 'martial-arts-club-manager' ) );
		}

		// Validate email if provided.
		if ( ! empty( $data['email'] ) && ! is_email( $data['email'] ) ) {
			return new WP_Error( 'invalid_email', __( 'Invalid email address.', 'martial-arts-club-manager' ) );
		}

		// Prepare data for insertion.
		$insert_data = array(
			'full_name'      => sanitize_text_field( $data['full_name'] ),
			'email'          => ! empty( $data['email'] ) ? sanitize_email( $data['email'] ) : null,
			'phone'          => ! empty( $data['phone'] ) ? sanitize_text_field( $data['phone'] ) : null,
			'specialization' => ! empty( $data['specialization'] ) ? sanitize_textarea_field( $data['specialization'] ) : null,
			'bio'            => ! empty( $data['bio'] ) ? sanitize_textarea_field( $data['bio'] ) : null,
			'is_active'      => isset( $data['is_active'] ) ? (int) $data['is_active'] : 1,
			'created_at'     => current_time( 'mysql' ),
		);

		$table_name = $wpdb->prefix . 'macm_instructors';

		// Insert into database.
		$inserted = $wpdb->insert(
			$table_name,
			$insert_data,
			array( '%s', '%s', '%s', '%s', '%s', '%d', '%s' )
		);

		if ( false === $inserted ) {
			return new WP_Error( 'db_error', __( 'Failed to create instructor.', 'martial-arts-club-manager' ) . ' ' . $wpdb->last_error );
		}

		$instructor_id = $wpdb->insert_id;

		// Fire action hook.
		do_action( 'macm_instructor_created', $instructor_id, $insert_data );

		return $instructor_id;
	}

	/**
	 * Get instructor by ID
	 *
	 * @since 1.0.57
	 * @param int $instructor_id Instructor ID.
	 * @return object|false Instructor object on success, false on failure.
	 */
	public static function get( $instructor_id ) {
		global $wpdb;

		$table_name = $wpdb->prefix . 'macm_instructors';

		$instructor = $wpdb->get_row(
			$wpdb->prepare(
				'SELECT * FROM %i WHERE id = %d',
				$table_name,
				$instructor_id
			)
		);

		return $instructor ? $instructor : false;
	}

	/**
	 * Get all instructors
	 *
	 * @since 1.0.57
	 * @param bool $active_only Whether to get only active instructors.
	 * @return array Array of instructor objects.
	 */
	public static function get_all( $active_only = true ) {
		global $wpdb;

		$table_name = $wpdb->prefix . 'macm_instructors';

		if ( $active_only ) {
			$instructors = $wpdb->get_results(
				$wpdb->prepare(
					'SELECT * FROM %i WHERE is_active = 1 ORDER BY full_name ASC',
					$table_name
				)
			);
		} else {
			$instructors = $wpdb->get_results(
				$wpdb->prepare(
					'SELECT * FROM %i ORDER BY full_name ASC',
					$table_name
				)
			);
		}

		return $instructors ? $instructors : array();
	}

	/**
	 * Update instructor
	 *
	 * @since 1.0.57
	 * @param int   $instructor_id Instructor ID.
	 * @param array $data Update data.
	 * @return bool True on success, false on failure.
	 */
	public static function update( $instructor_id, $data ) {
		global $wpdb;

		// Validate instructor exists.
		$instructor = self::get( $instructor_id );
		if ( ! $instructor ) {
			return false;
		}

		// Validate email if provided.
		if ( ! empty( $data['email'] ) && ! is_email( $data['email'] ) ) {
			return false;
		}

		// Prepare update data.
		$update_data = array();
		$format      = array();

		if ( isset( $data['full_name'] ) ) {
			$update_data['full_name'] = sanitize_text_field( $data['full_name'] );
			$format[]                 = '%s';
		}

		if ( isset( $data['email'] ) ) {
			$update_data['email'] = ! empty( $data['email'] ) ? sanitize_email( $data['email'] ) : null;
			$format[]             = '%s';
		}

		if ( isset( $data['phone'] ) ) {
			$update_data['phone'] = ! empty( $data['phone'] ) ? sanitize_text_field( $data['phone'] ) : null;
			$format[]             = '%s';
		}

		if ( isset( $data['specialization'] ) ) {
			$update_data['specialization'] = ! empty( $data['specialization'] ) ? sanitize_textarea_field( $data['specialization'] ) : null;
			$format[]                      = '%s';
		}

		if ( isset( $data['bio'] ) ) {
			$update_data['bio'] = ! empty( $data['bio'] ) ? sanitize_textarea_field( $data['bio'] ) : null;
			$format[]           = '%s';
		}

		if ( isset( $data['is_active'] ) ) {
			$update_data['is_active'] = (int) $data['is_active'];
			$format[]                 = '%d';
		}

		if ( empty( $update_data ) ) {
			return false;
		}

		$table_name = $wpdb->prefix . 'macm_instructors';

		$updated = $wpdb->update(
			$table_name,
			$update_data,
			array( 'id' => $instructor_id ),
			$format,
			array( '%d' )
		);

		// Fire action hook.
		do_action( 'macm_instructor_updated', $instructor_id, $update_data );

		return false !== $updated;
	}

	/**
	 * Delete instructor
	 *
	 * @since 1.0.57
	 * @param int $instructor_id Instructor ID.
	 * @return bool True on success, false on failure.
	 */
	public static function delete( $instructor_id ) {
		global $wpdb;

		// Remove all class assignments first.
		self::remove_all_class_assignments( $instructor_id );

		$table_name = $wpdb->prefix . 'macm_instructors';

		$deleted = $wpdb->delete(
			$table_name,
			array( 'id' => $instructor_id ),
			array( '%d' )
		);

		if ( $deleted ) {
			// Fire action hook.
			do_action( 'macm_instructor_deleted', $instructor_id );
		}

		return false !== $deleted;
	}

	/**
	 * Archive instructor (soft delete)
	 *
	 * @since 1.0.57
	 * @param int $instructor_id Instructor ID.
	 * @return bool True on success, false on failure.
	 */
	public static function archive( $instructor_id ) {
		return self::update( $instructor_id, array( 'is_active' => 0 ) );
	}

	/**
	 * Restore archived instructor
	 *
	 * @since 1.0.57
	 * @param int $instructor_id Instructor ID.
	 * @return bool True on success, false on failure.
	 */
	public static function restore( $instructor_id ) {
		return self::update( $instructor_id, array( 'is_active' => 1 ) );
	}

	/**
	 * Assign instructor to class
	 *
	 * @since 1.0.57
	 * @param int $class_id Class ID.
	 * @param int $instructor_id Instructor ID.
	 * @return bool True on success, false on failure.
	 */
	public static function assign_to_class( $class_id, $instructor_id ) {
		global $wpdb;

		$table_name = $wpdb->prefix . 'macm_class_instructors';

		$inserted = $wpdb->insert(
			$table_name,
			array(
				'class_id'      => (int) $class_id,
				'instructor_id' => (int) $instructor_id,
				'assigned_at'   => current_time( 'mysql' ),
			),
			array( '%d', '%d', '%s' )
		);

		if ( $inserted ) {
			do_action( 'macm_instructor_assigned_to_class', $instructor_id, $class_id );
		}

		return false !== $inserted;
	}

	/**
	 * Remove instructor from class
	 *
	 * @since 1.0.57
	 * @param int $class_id Class ID.
	 * @param int $instructor_id Instructor ID.
	 * @return bool True on success, false on failure.
	 */
	public static function remove_from_class( $class_id, $instructor_id ) {
		global $wpdb;

		$table_name = $wpdb->prefix . 'macm_class_instructors';

		$deleted = $wpdb->delete(
			$table_name,
			array(
				'class_id'      => (int) $class_id,
				'instructor_id' => (int) $instructor_id,
			),
			array( '%d', '%d' )
		);

		if ( $deleted ) {
			do_action( 'macm_instructor_removed_from_class', $instructor_id, $class_id );
		}

		return false !== $deleted;
	}

	/**
	 * Remove all class assignments for an instructor
	 *
	 * @since 1.0.57
	 * @param int $instructor_id Instructor ID.
	 * @return bool True on success, false on failure.
	 */
	public static function remove_all_class_assignments( $instructor_id ) {
		global $wpdb;

		$table_name = $wpdb->prefix . 'macm_class_instructors';

		$deleted = $wpdb->delete(
			$table_name,
			array( 'instructor_id' => (int) $instructor_id ),
			array( '%d' )
		);

		return false !== $deleted;
	}

	/**
	 * Get instructors for a class
	 *
	 * @since 1.0.57
	 * @param int $class_id Class ID.
	 * @return array Array of instructor objects.
	 */
	public static function get_class_instructors( $class_id ) {
		global $wpdb;

		$instructors_table = $wpdb->prefix . 'macm_instructors';
		$junction_table    = $wpdb->prefix . 'macm_class_instructors';

		$instructors = $wpdb->get_results(
			$wpdb->prepare(
				'SELECT i.*
				FROM %i i
				INNER JOIN %i ci ON i.id = ci.instructor_id
				WHERE ci.class_id = %d
				ORDER BY i.full_name ASC',
				$instructors_table,
				$junction_table,
				$class_id
			)
		);

		return $instructors ? $instructors : array();
	}

	/**
	 * Get classes for an instructor
	 *
	 * @since 1.0.57
	 * @param int $instructor_id Instructor ID.
	 * @return array Array of class objects.
	 */
	public static function get_instructor_classes( $instructor_id ) {
		global $wpdb;

		$classes_table  = $wpdb->prefix . 'macm_classes';
		$junction_table = $wpdb->prefix . 'macm_class_instructors';

		$classes = $wpdb->get_results(
			$wpdb->prepare(
				'SELECT c.*
				FROM %i c
				INNER JOIN %i ci ON c.id = ci.class_id
				WHERE ci.instructor_id = %d
				ORDER BY c.day_of_week ASC, c.start_time ASC',
				$classes_table,
				$junction_table,
				$instructor_id
			)
		);

		return $classes ? $classes : array();
	}

	/**
	 * Get instructor IDs for a class
	 *
	 * @since 1.0.57
	 * @param int $class_id Class ID.
	 * @return array Array of instructor IDs.
	 */
	public static function get_class_instructor_ids( $class_id ) {
		global $wpdb;

		$table_name = $wpdb->prefix . 'macm_class_instructors';

		$ids = $wpdb->get_col(
			$wpdb->prepare(
				'SELECT instructor_id FROM %i WHERE class_id = %d',
				$table_name,
				$class_id
			)
		);

		return $ids ? array_map( 'intval', $ids ) : array();
	}

	/**
	 * Update class instructors
	 *
	 * @since 1.0.57
	 * @param int   $class_id Class ID.
	 * @param array $instructor_ids Array of instructor IDs.
	 * @return bool True on success, false on failure.
	 */
	public static function update_class_instructors( $class_id, $instructor_ids ) {
		global $wpdb;

		// Get current instructor IDs.
		$current_ids = self::get_class_instructor_ids( $class_id );

		// Convert to arrays of integers.
		$instructor_ids = array_map( 'intval', (array) $instructor_ids );
		$current_ids    = array_map( 'intval', $current_ids );

		// Find instructors to add.
		$to_add = array_diff( $instructor_ids, $current_ids );

		// Find instructors to remove.
		$to_remove = array_diff( $current_ids, $instructor_ids );

		// Add new instructors.
		foreach ( $to_add as $instructor_id ) {
			self::assign_to_class( $class_id, $instructor_id );
		}

		// Remove old instructors.
		foreach ( $to_remove as $instructor_id ) {
			self::remove_from_class( $class_id, $instructor_id );
		}

		return true;
	}

	/**
	 * Get count of classes for instructor
	 *
	 * @since 1.0.57
	 * @param int $instructor_id Instructor ID.
	 * @return int Number of classes.
	 */
	public static function get_class_count( $instructor_id ) {
		global $wpdb;

		$table_name = $wpdb->prefix . 'macm_class_instructors';

		$count = $wpdb->get_var(
			$wpdb->prepare(
				'SELECT COUNT(*) FROM %i WHERE instructor_id = %d',
				$table_name,
				$instructor_id
			)
		);

		return (int) $count;
	}
}
