<?php
/**
 * Sports Leagues Config.
 *
 * @since   0.1.0
 * @package Sports_Leagues
 */

/**
 * Sports_Leagues_Config class.
 *
 * @since 0.1.0
 */
class Sports_Leagues_Config {

	/**
	 * Parent plugin class.
	 *
	 * @var    Sports_Leagues
	 * @since  0.1.0
	 */
	protected $plugin = null;

	/**
	 * Option key
	 *
	 * @var    string
	 * @since  0.1.0
	 */
	public static $key = 'sports_leagues_config';

	/**
	 * Constructor.
	 *
	 * @param Sports_Leagues $plugin Main plugin object.
	 *
	 * @since  0.1.0
	 */
	public function __construct( $plugin ) {
		$this->plugin = $plugin;
		$this->hooks();
	}

	/**
	 * Initiate our hooks.
	 */
	public function hooks() {
		add_action( 'rest_api_init', [ $this, 'add_rest_routes' ] );
	}

	/**
	 * Register REST routes.
	 *
	 * @since 0.13.2
	 */
	public function add_rest_routes() {

		register_rest_route(
			'sports-leagues/v1',
			'/settings/save_sport_config',
			[
				'methods'             => 'POST',
				'callback'            => [ $this, 'save_sport_config' ],
				'permission_callback' => function () {
					return current_user_can( 'manage_options' );
				},
			]
		);
	}

	/**
	 * Wrapper function around cmb2_get_option.
	 *
	 * @since  0.1.0
	 *
	 * @param  string $key     Options array key
	 * @param  mixed  $default Optional default value
	 * @return mixed           Option value
	 */
	public static function get_value( $key = '', $default = false ) {

		// Fallback to get_option if CMB2 is not loaded yet.
		$opts = get_option( self::$key, $default );

		$val = $default;

		if ( 'all' === $key ) {
			$val = $opts;
		} elseif ( is_array( $opts ) && array_key_exists( $key, $opts ) && false !== $opts[ $key ] ) {
			$val = $opts[ $key ];
		}

		return $val;
	}

	/**
	 * Get player positions.
	 *
	 * @return array
	 * @since 0.1.0
	 */
	public function get_player_positions() {

		$options   = [];
		$positions = self::get_value( 'position' );

		if ( empty( $positions ) || ! is_array( $positions ) ) {
			return $options;
		}

		foreach ( $positions as $position ) {
			$options[ $position['id'] ] = $position['name'];
		}

		return $options;
	}

	/**
	 * Returns config options for selected value.
	 *
	 * @param string $value
	 *
	 * @return array
	 * @since 0.1.0
	 */
	public function get_options( $value ) {

		$options = self::get_value( $value );

		if ( ! empty( $options ) && is_array( $options ) ) {
			return $options;
		}

		return [];
	}

	/**
	 * Get Standing config data.
	 *
	 * @return array
	 * @since 0.1.0
	 */
	public function get_standing_config() {

		$options = [];

		$columns = [
			'played'   => esc_html__( 'Played', 'sports-leagues' ),
			'all_win'  => esc_html__( 'Win - all', 'sports-leagues' ),
			'ft_win'   => esc_html__( 'Win - full time', 'sports-leagues' ),
			'ov_win'   => esc_html__( 'Win - overtime', 'sports-leagues' ),
			'pen_win'  => esc_html__( 'Win - penalty', 'sports-leagues' ),
			'draw'     => esc_html__( 'Draw', 'sports-leagues' ),
			'all_loss' => esc_html__( 'Loss - all', 'sports-leagues' ),
			'ft_loss'  => esc_html__( 'Loss - full time', 'sports-leagues' ),
			'ov_loss'  => esc_html__( 'Loss - overtime', 'sports-leagues' ),
			'pen_loss' => esc_html__( 'Loss - penalty', 'sports-leagues' ),
			'sf'       => esc_html__( 'Scores - for', 'sports-leagues' ),
			'sa'       => esc_html__( 'Scores - against', 'sports-leagues' ),
			'sd'       => esc_html__( 'Scores - difference', 'sports-leagues' ),
			'ratio'    => esc_html__( 'Ratio (win/played)', 'sports-leagues' ),
			'bpts'     => esc_html__( 'Bonus Points', 'sports-leagues' ),
			'pts'      => esc_html__( 'Points', 'sports-leagues' ),
		];

		foreach ( $columns as $key => $origin ) {

			$option_value = self::get_value( 'standing_str__' . sanitize_key( $key ) );

			$options[ $key ] = [
				'origin' => $origin,
				'key'    => $key,
				'abbr'   => empty( $option_value['abbr'] ) ? $key : $option_value['abbr'],
				'name'   => empty( $option_value['name'] ) ? $origin : $option_value['name'],
			];
		}

		return $options;
	}

	/**
	 * Save Sport Configuration
	 *
	 * @param WP_REST_Request $request
	 *
	 * @return void|WP_Error
	 * @since 0.10.0
	 */
	public function save_sport_config( WP_REST_Request $request ) {

		// Get Request params
		$params = $request->get_params();

		// Check API Method exists
		if ( empty( $params['sport_config'] ) ) {
			return new WP_Error( 'rest_invalid', 'Incorrect Data', [ 'status' => 400 ] );
		}

		$sport_config = $this->plugin->helper->recursive_sanitize( $params['sport_config'] );
		$old_settings = get_option( self::$key, [] );

		if ( $sport_config === $old_settings || maybe_serialize( $sport_config ) === maybe_serialize( $old_settings ) ) {
			return rest_ensure_response( [ 'result' => 'Nothing to Update' ] );
		}

		if ( ! update_option( self::$key, $sport_config, true ) ) {
			return new WP_Error( 'rest_invalid', 'Update Problem', [ 'status' => 400 ] );
		}

		return rest_ensure_response( [ 'result' => 'Saved Successfully' ] );
	}

	/**
	 * Get available sports for configuration.
	 *
	 * @return array Array of sports with slug, title, and icon.
	 * @since 0.14.1
	 */
	public static function get_sports_available() {
		return [
			[
				'slug'  => 'basketball',
				'title' => esc_html__( 'Basketball', 'sports-leagues' ),
				'icon'  => '🏀',
			],
			[
				'slug'  => 'handball',
				'title' => esc_html__( 'Handball', 'sports-leagues' ),
				'icon'  => '🤾',
			],
			[
				'slug'  => 'rugby',
				'title' => esc_html__( 'Rugby', 'sports-leagues' ),
				'icon'  => '🏉',
			],
			[
				'slug'  => 'football',
				'title' => esc_html__( 'American football', 'sports-leagues' ),
				'icon'  => '🏈',
			],
			[
				'slug'  => 'ice_hockey',
				'title' => esc_html__( 'Ice Hockey', 'sports-leagues' ),
				'icon'  => '🏒',
			],
			[
				'slug'  => 'other',
				'title' => esc_html__( 'Other', 'sports-leagues' ),
				'icon'  => '⚙️',
			],
		];
	}

	/**
	 * Get recommended configurations for all sports.
	 *
	 * Returns pre-defined configurations for supported sports (basketball, ice_hockey,
	 * handball, rugby, football). Data is parsed into arrays ready for saving.
	 *
	 * @return array Associative array of sport configs keyed by sport slug.
	 * @since 0.14.1
	 */
	public static function get_recommended_configs() {

		// Raw recommended config with translatable strings.
		$raw_config = [
			'basketball' => [
				'title'                  => esc_html__( 'Basketball', 'sports-leagues' ),
				'icon'                   => '🏀',
				'position'               => esc_html_x( 'Point Guard|P-G;Shooting Guard|S-G;Small Forward|S-F;Power Forward|P-F;Center|C;Power Forward and Center|C-F;Point Guard and Shooting Guard|G;Forward Center|F-C;Small Forward and Power Forward|F;Shooting Guard and Small Forward|G-F', 'config basketball: position', 'sports-leagues' ),
				'roster_status'          => esc_html_x( 'in team;on loan;on trial', 'config basketball: roster-status', 'sports-leagues' ),
				'game_player_groups'     => esc_html_x( 'Starters;Bench', 'config basketball: game-player-groups', 'sports-leagues' ),
				'game_team_stats'        => esc_html_x( 'Field Goals %;Three Pointers %;Free Throws %;Rebounds;Assists;Steals;Blocks;Turnovers;Fouls', 'config basketball: game-team-stats', 'sports-leagues' ),
				'num_of_periods'         => esc_html_x( '4', 'config basketball: num_of_periods', 'sports-leagues' ),
				'standing_str__all_win'  => esc_html_x( 'Wins|W', 'config basketball: standing_str__all_win', 'sports-leagues' ),
				'standing_str__all_loss' => esc_html_x( 'Losses|L', 'config basketball: standing_str__all_loss', 'sports-leagues' ),
				'standing_str__ratio'    => esc_html_x( 'Winning Percentage|PCT', 'config basketball: standing_str__ratio', 'sports-leagues' ),
			],
			'ice_hockey' => [
				'title'                  => esc_html__( 'Ice Hockey', 'sports-leagues' ),
				'icon'                   => '🏒',
				'position'               => esc_html_x( 'Goaltender|G;Left Defenceman|L;Right Defenceman|R;Left Wing|LW;Centre|C;Right Wing|RW', 'config ice_hockey: position', 'sports-leagues' ),
				'roster_status'          => esc_html_x( 'in team;on loan;on trial', 'config ice_hockey: roster-status', 'sports-leagues' ),
				'roster_groups'          => esc_html_x( 'Goalies;Defense;Forwards', 'config ice_hockey: roster-groups', 'sports-leagues' ),
				'game_player_groups'     => esc_html_x( 'Goalies;Defense;Forwards', 'config ice_hockey: game-player-groups', 'sports-leagues' ),
				'game_team_stats'        => esc_html_x( 'Shots;Hits;Faceoffs Won;Power Play Opportunities;Total Penalties;Penalty Minutes;Blocked Shots;Takeaways;Giveaways', 'config ice_hockey: game-team-stats', 'sports-leagues' ),
				'num_of_periods'         => esc_html_x( '3', 'config ice_hockey: num_of_periods', 'sports-leagues' ),
				'points_ft_win'          => esc_html_x( '2', 'config ice_hockey: points_ft_win', 'sports-leagues' ),
				'points_ov_win'          => esc_html_x( '2', 'config ice_hockey: points_ov_win', 'sports-leagues' ),
				'points_pen_win'         => esc_html_x( '2', 'config ice_hockey: points_pen_win', 'sports-leagues' ),
				'points_ft_loss'         => esc_html_x( '0', 'config ice_hockey: points_ft_loss', 'sports-leagues' ),
				'points_ov_loss'         => esc_html_x( '1', 'config ice_hockey: points_ov_loss', 'sports-leagues' ),
				'points_pen_loss'        => esc_html_x( '1', 'config ice_hockey: points_pen_loss', 'sports-leagues' ),
				'standing_str__played'   => esc_html_x( 'Games Played|GP', 'config ice_hockey: standing_str__played', 'sports-leagues' ),
				'standing_str__all_win'  => esc_html_x( 'Wins|W', 'config ice_hockey: standing_str__all_win', 'sports-leagues' ),
				'standing_str__ft_loss'  => esc_html_x( 'Losses|L', 'config ice_hockey: standing_str__ft_loss', 'sports-leagues' ),
				'standing_str__ov_loss'  => esc_html_x( 'Overtime Losses|OTL', 'config ice_hockey: standing_str_ov_loss', 'sports-leagues' ),
				'standing_str__pen_loss' => esc_html_x( 'Shootout Losses|SOL', 'config ice_hockey: standing_str_pen_loss', 'sports-leagues' ),
				'standing_str__pts'      => esc_html_x( 'Total Points|PTS', 'config ice_hockey: standing_str__pts', 'sports-leagues' ),
				'standing_str__sf'       => esc_html_x( 'Goals For|GF', 'config ice_hockey: standing_str__sf', 'sports-leagues' ),
				'standing_str__sa'       => esc_html_x( 'Goals Against|GA', 'config ice_hockey: standing_str__sa', 'sports-leagues' ),
				'standing_str__sd'       => esc_html_x( 'Goal Differential|DIFF', 'config ice_hockey: standing_str__sd', 'sports-leagues' ),
			],
			'handball'   => [
				'title'                  => esc_html__( 'Handball', 'sports-leagues' ),
				'icon'                   => '🤾',
				'position'               => esc_html_x( 'Goalkeeper|GK;Left Back|LB;Centre Back|CB;Right Back|RB;Left Winger|LW;Right Winger|RW;Line Player|LP', 'config handball: position', 'sports-leagues' ),
				'roster_status'          => esc_html_x( 'in team;on loan;on trial', 'config handball: roster-status', 'sports-leagues' ),
				'roster_groups'          => esc_html_x( 'Goalkeepers;Field players', 'config handball: roster-groups', 'sports-leagues' ),
				'game_player_groups'     => esc_html_x( 'Lineups;Substitutes', 'config handball: game-player-groups', 'sports-leagues' ),
				'game_team_stats'        => esc_html_x( 'Total Shots;Total Goals;7m Shots;7m Goals;Total Misses;Technical Faults;2 min Suspensions;Warnings;Disqualifications', 'config handball: game-team-stats', 'sports-leagues' ),
				'num_of_periods'         => esc_html_x( '2', 'config handball: num_of_periods', 'sports-leagues' ),
				'points_ft_win'          => esc_html_x( '2', 'config handball: points_ft_win', 'sports-leagues' ),
				'points_draw'            => esc_html_x( '1', 'config handball: points_draw', 'sports-leagues' ),
				'points_ft_loss'         => esc_html_x( '0', 'config handball: points_ft_loss', 'sports-leagues' ),
				'standing_str__played'   => esc_html_x( 'Played|Pld', 'config handball: standing_str__played', 'sports-leagues' ),
				'standing_str__all_win'  => esc_html_x( 'Won|W', 'config handball: standing_str__all_win', 'sports-leagues' ),
				'standing_str__draw'     => esc_html_x( 'Drawn|D', 'config handball: standing_str__draw', 'sports-leagues' ),
				'standing_str__all_loss' => esc_html_x( 'Lost|L', 'config handball: standing_str__all_loss', 'sports-leagues' ),
				'standing_str__sf'       => esc_html_x( 'Goals For|GF', 'config handball: standing_str__sf', 'sports-leagues' ),
				'standing_str__sa'       => esc_html_x( 'Goals Against|GA', 'config handball: standing_str__sa', 'sports-leagues' ),
				'standing_str__sd'       => esc_html_x( 'Goal Difference|GD', 'config handball: standing_str__sd', 'sports-leagues' ),
				'standing_str__pts'      => esc_html_x( 'Points|Pts', 'config handball: standing_str__pts', 'sports-leagues' ),
			],
			'rugby'      => [
				'title'                  => esc_html__( 'Rugby', 'sports-leagues' ),
				'icon'                   => '🏉',
				'position'               => esc_html_x( 'Full back;Right wing;Outside centre;Inside centre;Left wing;Fly-half;Scrum-half;Loosehead prop;Hooker;Tighthead prop;Lock;Blindside flanker;Openside flanker;Number eight', 'config rugby: position', 'sports-leagues' ),
				'roster_status'          => esc_html_x( 'in team;on loan;on trial', 'config rugby: roster-status', 'sports-leagues' ),
				'game_player_groups'     => esc_html_x( 'Lineups;Substitutes', 'config rugby: game-player-groups', 'sports-leagues' ),
				'game_team_stats'        => esc_html_x( 'Possession;Territory;Clean breaks;Defenders beaten;Rucks won%;Mauls won;Offloads;Turnovers won;Tackles made;Tackles missed;Tackle success %;Lineouts won;Lineouts lost;Scrums won;Scrums lost;Restarts won;Restarts lost;Penalties conceded;Yellow cards;Red cards', 'config rugby: game-team-stats', 'sports-leagues' ),
				'num_of_periods'         => esc_html_x( '2', 'config rugby: num_of_periods', 'sports-leagues' ),
				'points_ft_win'          => esc_html_x( '4', 'config rugby: points_ft_win', 'sports-leagues' ),
				'points_draw'            => esc_html_x( '2', 'config rugby: points_draw', 'sports-leagues' ),
				'points_ft_loss'         => esc_html_x( '0', 'config rugby: points_ft_loss', 'sports-leagues' ),
				'standing_str__played'   => esc_html_x( 'Played|P', 'config rugby: standing_str__played', 'sports-leagues' ),
				'standing_str__all_win'  => esc_html_x( 'Win|W', 'config rugby: standing_str__all_win', 'sports-leagues' ),
				'standing_str__draw'     => esc_html_x( 'Draw|D', 'config rugby: standing_str__draw', 'sports-leagues' ),
				'standing_str__all_loss' => esc_html_x( 'Lose|L', 'config rugby: standing_str__all_loss', 'sports-leagues' ),
				'standing_str__sf'       => esc_html_x( 'Points For|PF', 'config rugby: standing_str__sf', 'sports-leagues' ),
				'standing_str__sa'       => esc_html_x( 'Points Against|PA', 'config rugby: standing_str__sa', 'sports-leagues' ),
				'standing_str__sd'       => esc_html_x( 'Points Difference|PD', 'config rugby: standing_str__sd', 'sports-leagues' ),
				'standing_str__bpts'     => esc_html_x( 'Bonus Points|BP', 'config rugby: standing_str__bpts', 'sports-leagues' ),
				'standing_str__pts'      => esc_html_x( 'Points|Pts', 'config rugby: standing_str__pts', 'sports-leagues' ),
			],
			'football'   => [
				'title'                => esc_html__( 'American football', 'sports-leagues' ),
				'icon'                 => '🏈',
				'position'             => esc_html_x( 'Safety|S;Cornerback|CB;Defensive end|DE;Defensive tackle|DT;Fullback|FB;Guard|G;Linebacker|LB;Long snapper|LS;Offensive tackle|OT;Punter|P;Placekicker|PK;Quarterback|QB;Running back|RB;Tight end|TE;Wide receiver|WR', 'config football: position', 'sports-leagues' ),
				'roster_status'        => esc_html_x( 'in team;on loan;on trial', 'config football: roster-status', 'sports-leagues' ),
				'game_team_stats'      => esc_html_x( 'Total 1st Downs;Passing 1st Downs;Rushing 1st Downs;1st Downs from Penalties;Total Plays;Total Yards;Yards per Play;Total Drives;Total Passing;Yards per Pass;Interceptions Thrown;Sacks-Yards Lost;Total Rushing;Rushing Attempts;Yards per Rush;Penalties;Total Turnovers;Fumbles lost;Turnovers Interceptions;Possession;Total Interceptions;Total Safeties', 'config football: game-team-stats', 'sports-leagues' ),
				'num_of_periods'       => esc_html_x( '4', 'config football: num_of_periods', 'sports-leagues' ),
				'bonus_points_hide'    => 'hide',
				'standing_points_hide' => 'hide',
				'penalty_hide'         => 'hide',
			],
		];

		// Standing columns to parse.
		$standing_columns = [
			'standing_str__played',
			'standing_str__all_win',
			'standing_str__ft_win',
			'standing_str__ov_win',
			'standing_str__pen_win',
			'standing_str__draw',
			'standing_str__all_loss',
			'standing_str__ft_loss',
			'standing_str__ov_loss',
			'standing_str__pen_loss',
			'standing_str__sf',
			'standing_str__sa',
			'standing_str__sd',
			'standing_str__ratio',
			'standing_str__bpts',
			'standing_str__pts',
		];

		$parsed_config = [];

		// Parse each sport configuration.
		foreach ( $raw_config as $sport_slug => $sport_config ) {

			$parsed_config[ $sport_slug ] = $sport_config;

			// Add sport slug to config (used by Dashboard quick setup).
			$parsed_config[ $sport_slug ]['sport'] = $sport_slug;

			// Parse position field: "Name|Abbr;Name2|Abbr2" => array of [name, id, abbr].
			if ( ! empty( $sport_config['position'] ) ) {
				$parsed_data = [];

				foreach ( explode( ';', $sport_config['position'] ) as $field_data ) {
					if ( ! empty( $field_data ) ) {
						$field_data_inner = explode( '|', $field_data );

						$parsed_data[] = [
							'name' => $field_data_inner[0],
							'id'   => $field_data_inner[0],
							'abbr' => $field_data_inner[1] ?? '',
						];
					}
				}

				$parsed_config[ $sport_slug ]['position'] = $parsed_data;
			}

			// Parse roster_status field: "status1;status2" => simple array.
			if ( ! empty( $sport_config['roster_status'] ) ) {
				$parsed_data = [];

				foreach ( explode( ';', $sport_config['roster_status'] ) as $field_data ) {
					if ( ! empty( $field_data ) ) {
						$parsed_data[] = $field_data;
					}
				}

				$parsed_config[ $sport_slug ]['roster_status'] = $parsed_data;
			}

			// Parse group fields: "Name1;Name2" => array of [name, id].
			foreach ( [ 'roster_groups', 'game_player_groups', 'game_team_stats' ] as $field_slug ) {
				if ( ! empty( $sport_config[ $field_slug ] ) ) {
					$parsed_data = [];

					foreach ( explode( ';', $sport_config[ $field_slug ] ) as $field_data ) {
						if ( ! empty( $field_data ) ) {
							$parsed_data[] = [
								'name' => $field_data,
								'id'   => $field_data,
							];
						}
					}

					$parsed_config[ $sport_slug ][ $field_slug ] = $parsed_data;
				}
			}

			// Parse standing columns: "Name|Abbr" => [name, abbr].
			foreach ( $standing_columns as $field_slug ) {
				$parsed_data = [
					'name' => '',
					'abbr' => '',
				];

				if ( ! empty( $sport_config[ $field_slug ] ) ) {
					$field_data_inner = explode( '|', $sport_config[ $field_slug ] );

					$parsed_data = [
						'name' => $field_data_inner[0],
						'abbr' => $field_data_inner[1] ?? '',
					];
				}

				$parsed_config[ $sport_slug ][ $field_slug ] = $parsed_data;
			}
		}

		return $parsed_config;
	}

	/**
	 * Get field name by its id
	 *
	 * @param string $field
	 * @param string $field_id
	 * @param bool   $return_empty_false
	 *
	 * @return string
	 * @since 0.10.0
	 */
	public function get_name_by_id( $field, $field_id, $return_empty_false = false ) {

		$options    = [];
		$field_name = '';

		static $cached_output = [];

		if ( ! empty( $cached_output[ $field ] ) && ! empty( $cached_output[ $field ][ $field_id ] ) ) {
			return $cached_output[ $field ][ $field_id ];
		}

		switch ( $field ) {
			case 'position':
				$options = $this->get_options( 'position' );
				break;

			case 'game_player_groups':
				$options = $this->get_options( 'game_player_groups' );
				break;

			case 'official_groups':
				$options = $this->get_options( 'official_groups' );
				break;

			case 'staff_roster_groups':
				$options = $this->get_options( 'staff_roster_groups' );
				break;

			case 'roster_groups':
				$options = $this->get_options( 'roster_groups' );
				break;
		}

		$cached_output[ $field ] = [];

		foreach ( $options as $single_option ) {

			$cached_output[ $field ][ $single_option['id'] ] = $single_option['name'];

			if ( $single_option['id'] === $field_id ) {
				$field_name = $single_option['name'];
			}
		}

		return $field_name ?: ( $return_empty_false ? false : $field_id );
	}
}
