<?php
/**
 * Location Management Class
 *
 * Handles CRUD operations for training locations
 *
 * @package    Karate_Club_Manager
 * @subpackage Karate_Club_Manager/includes/classes
 * @since      1.0.0
 */

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

/**
 * Class MACM_Location
 *
 * Manages training locations for karate classes
 *
 * @since 1.0.0
 */
class MACM_Location {

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

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

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

		// Validate address length if provided.
		if ( ! empty( $data['address'] ) && strlen( $data['address'] ) > 255 ) {
			return new WP_Error( 'address_too_long', __( 'Address must be less than 255 characters.', 'martial-arts-club-manager' ) );
		}

		// Prepare data for insertion.
		$insert_data = array(
			'location_name' => sanitize_text_field( $data['name'] ),
			'address'       => ! empty( $data['address'] ) ? sanitize_textarea_field( $data['address'] ) : null,
			'is_active'     => isset( $data['is_active'] ) ? (int) $data['is_active'] : 1,
			'created_at'    => current_time( 'mysql' ),
		);

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

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

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

		$location_id = $wpdb->insert_id;

		// Fire action hook.
		do_action( 'macm_location_created', $location_id, $insert_data );

		return $location_id;
	}

	/**
	 * Get location by ID
	 *
	 * @since 1.0.0
	 * @param int $location_id Location ID.
	 * @return object|false Location object on success, false on failure.
	 */
	public static function get( $location_id ) {
		global $wpdb;

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

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

		return $location ? $location : false;
	}

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

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

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

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

	/**
	 * Update location
	 *
	 * @since 1.0.0
	 * @param int   $location_id Location ID.
	 * @param array $data Location data to update.
	 * @return bool|WP_Error True on success, WP_Error on failure.
	 */
	public static function update( $location_id, $data ) {
		global $wpdb;

		// Check if location exists.
		$location = self::get( $location_id );
		if ( ! $location ) {
			return new WP_Error( 'not_found', __( 'Location not found.', 'martial-arts-club-manager' ) );
		}

		// Validate name if provided.
		if ( isset( $data['name'] ) ) {
			if ( empty( $data['name'] ) ) {
				return new WP_Error( 'missing_name', __( 'Location name is required.', 'martial-arts-club-manager' ) );
			}
			if ( strlen( $data['name'] ) > 100 ) {
				return new WP_Error( 'name_too_long', __( 'Location name must be less than 100 characters.', 'martial-arts-club-manager' ) );
			}
		}

		// Validate address if provided.
		if ( isset( $data['address'] ) && strlen( $data['address'] ) > 255 ) {
			return new WP_Error( 'address_too_long', __( 'Address must be less than 255 characters.', 'martial-arts-club-manager' ) );
		}

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

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

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

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

		if ( empty( $update_data ) ) {
			return new WP_Error( 'no_data', __( 'No data to update.', 'martial-arts-club-manager' ) );
		}

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

		// Update database.
		$updated = $wpdb->update(
			$table_name,
			$update_data,
			array( 'id' => $location_id ),
			$format,
			array( '%d' )
		);

		if ( false === $updated ) {
			return new WP_Error( 'db_error', __( 'Failed to update location.', 'martial-arts-club-manager' ) );
		}

		// Fire action hook.
		do_action( 'macm_location_updated', $location_id, $update_data );

		return true;
	}

	/**
	 * Delete location
	 *
	 * Checks if location is in use by any classes before deleting
	 *
	 * @since 1.0.0
	 * @param int $location_id Location ID.
	 * @return bool|WP_Error True on success, WP_Error on failure.
	 */
	public static function delete( $location_id ) {
		global $wpdb;

		// Check if location exists.
		$location = self::get( $location_id );
		if ( ! $location ) {
			return new WP_Error( 'not_found', __( 'Location not found.', 'martial-arts-club-manager' ) );
		}

		// Check if location is used by any active classes.
		$classes_table = $wpdb->prefix . 'macm_classes';
		$class_count   = $wpdb->get_var(
			$wpdb->prepare(
				'SELECT COUNT(*) FROM %i WHERE location_id = %d AND is_archived = 0',
				$classes_table,
				$location_id
			)
		);

		if ( $class_count > 0 ) {
			return new WP_Error(
				'in_use',
				sprintf(
					/* translators: %d: number of classes using this location */
					__( 'Cannot delete location. It is used by %d active class(es).', 'martial-arts-club-manager' ),
					$class_count
				)
			);
		}

		// Set location_id to NULL for all archived classes using this location.
		$wpdb->update(
			$classes_table,
			array( 'location_id' => null ),
			array(
				'location_id' => $location_id,
				'is_archived' => 1,
			),
			array( '%d' ),
			array( '%d', '%d' )
		);

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

		// Delete from database.
		$deleted = $wpdb->delete(
			$table_name,
			array( 'id' => $location_id ),
			array( '%d' )
		);

		if ( false === $deleted ) {
			return new WP_Error( 'db_error', __( 'Failed to delete location.', 'martial-arts-club-manager' ) );
		}

		// Fire action hook.
		do_action( 'macm_location_deleted', $location_id );

		return true;
	}

	/**
	 * Get classes for a location
	 *
	 * @since 1.0.0
	 * @param int  $location_id Location ID.
	 * @param bool $active_only Whether to return only active classes.
	 * @return array Array of class objects.
	 */
	public static function get_classes( $location_id, $active_only = true ) {
		global $wpdb;

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

		if ( $active_only ) {
			$classes = $wpdb->get_results(
				$wpdb->prepare(
					'SELECT * FROM %i WHERE location_id = %d AND is_archived = 0 ORDER BY day_of_week ASC, start_time ASC',
					$classes_table,
					$location_id
				)
			);
		} else {
			$classes = $wpdb->get_results(
				$wpdb->prepare(
					'SELECT * FROM %i WHERE location_id = %d ORDER BY day_of_week ASC, start_time ASC',
					$classes_table,
					$location_id
				)
			);
		}

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

	/**
	 * Check if location name already exists
	 *
	 * @since 1.0.0
	 * @param string $name Location name.
	 * @param int    $exclude_id Location ID to exclude from check (for updates).
	 * @return bool True if exists, false if not.
	 */
	public static function name_exists( $name, $exclude_id = 0 ) {
		global $wpdb;

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

		$count = $wpdb->get_var(
			$wpdb->prepare(
				'SELECT COUNT(*) FROM %i WHERE location_name = %s AND id != %d',
				$table_name,
				sanitize_text_field( $name ),
				$exclude_id
			)
		);

		return $count > 0;
	}
}
