<?php
/**
 * Ajustes del plugin Logistica.
 *
 * @package Logistica
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Opciones guardadas en wp_options.
 */
final class Logistica_Settings {

	public const OPTION_FRONTEND_MENU = 'logistica_frontend_menu_tabs';

	public const OPTION_FRONTEND_PAGE = 'logistica_frontend_page_id';

	public const OPTION_PANEL_COMPRA_STATUSES = 'logistica_panel_compra_statuses';

	public const OPTION_PANEL_HOLIDAYS = 'logistica_panel_holidays';

	public const OPTION_OPERATIONS_MENU_ORDER = 'logistica_operations_menu_order';

	public const OPTION_HELP = 'logistica_help_settings';

	/**
	 * @return array<string, string>
	 */
	public static function default_help_settings() {
		return array(
			'hero_title'    => '',
			'hero_intro'    => '',
			'content_mode'  => 'default',
			'custom_html'   => '',
			'sections_json' => '',
		);
	}

	/**
	 * @return array<string, string>
	 */
	public static function get_help_settings() {
		$saved = get_option( self::OPTION_HELP, array() );

		if ( ! is_array( $saved ) ) {
			$saved = array();
		}

		return array_merge( self::default_help_settings(), $saved );
	}

	/**
	 * @return array{title: string, intro: string}
	 */
	public static function get_help_hero() {
		$settings = self::get_help_settings();

		return array(
			'title' => '' !== trim( (string) $settings['hero_title'] )
				? (string) $settings['hero_title']
				: __( 'Ayuda de JB Planeación', 'logistica' ),
			'intro' => '' !== trim( (string) $settings['hero_intro'] )
				? (string) $settings['hero_intro']
				: __( 'Guía completa para usar JB Planeación: cada pestaña, botones, cálculos, métricas y roles explicados en lenguaje sencillo. Abre el menú de navegación interna (icono de secciones en la barra) para saltar al tema que necesites.', 'logistica' ),
		);
	}

	/**
	 * @param array<string, mixed> $raw POST data.
	 * @return void
	 */
	public static function save_help_settings( $raw ) {
		if ( ! is_array( $raw ) ) {
			$raw = array();
		}

		$mode = sanitize_key( (string) ( $raw['content_mode'] ?? 'default' ) );
		if ( ! in_array( $mode, array( 'default', 'html', 'json' ), true ) ) {
			$mode = 'default';
		}

		$existing      = self::get_help_settings();
		$sections_json = (string) ( $existing['sections_json'] ?? '' );
		$custom_html   = (string) ( $existing['custom_html'] ?? '' );

		if ( 'json' === $mode ) {
			$sections_json = isset( $raw['sections_json'] ) ? wp_unslash( (string) $raw['sections_json'] ) : '';
			if ( '' !== trim( $sections_json ) ) {
				$decoded = json_decode( $sections_json, true );
				if ( ! is_array( $decoded ) ) {
					$mode          = (string) ( $existing['content_mode'] ?? 'default' );
					$sections_json = (string) ( $existing['sections_json'] ?? '' );
				}
			}
		}

		if ( 'html' === $mode && isset( $raw['custom_html'] ) ) {
			$custom_html = wp_kses_post( wp_unslash( (string) $raw['custom_html'] ) );
		}

		$payload = array(
			'hero_title'    => sanitize_text_field( (string) ( $raw['hero_title'] ?? '' ) ),
			'hero_intro'    => sanitize_textarea_field( (string) ( $raw['hero_intro'] ?? '' ) ),
			'content_mode'  => $mode,
			'custom_html'   => $custom_html,
			'sections_json' => $sections_json,
		);

		if ( ! empty( $raw['help_reset_defaults'] ) ) {
			$payload = self::default_help_settings();
		}

		update_option( self::OPTION_HELP, $payload, false );
	}

	/**
	 * Orden por defecto del menú operativo (slug de cada pestaña).
	 *
	 * @return list<string>
	 */
	public static function default_operations_menu_order() {
		require_once LOGISTICA_PLUGIN_DIR . 'includes/class-logistica-tabs.php';

		return Logistica_Tabs::operational_slugs();
	}

	/**
	 * @return array<string, string> slug => etiqueta (sin Configuración).
	 */
	public static function operations_menu_choices() {
		require_once LOGISTICA_PLUGIN_DIR . 'admin/views/partials.php';

		$all = logistica_get_nav_tabs();
		unset( $all['logistica-configuracion'] );

		return $all;
	}

	/**
	 * Orden guardado del menú lateral del panel de operaciones.
	 *
	 * @return list<string>
	 */
	public static function get_operations_menu_order() {
		$saved   = get_option( self::OPTION_OPERATIONS_MENU_ORDER, array() );
		$default = self::default_operations_menu_order();
		$choices = self::operations_menu_choices();

		if ( ! is_array( $saved ) || empty( $saved ) ) {
			return $default;
		}

		$valid = array();

		foreach ( $saved as $slug ) {
			$slug = sanitize_key( (string) $slug );
			if ( '' !== $slug && isset( $choices[ $slug ] ) && ! in_array( $slug, $valid, true ) ) {
				$valid[] = $slug;
			}
		}

		foreach ( $default as $slug ) {
			if ( ! in_array( $slug, $valid, true ) ) {
				$valid[] = $slug;
			}
		}

		return $valid;
	}

	/**
	 * Etiquetas del menú operativo en el orden configurado.
	 *
	 * @return array<string, string>
	 */
	public static function get_operations_menu_order_with_labels() {
		$choices = self::operations_menu_choices();
		$ordered = array();

		foreach ( self::get_operations_menu_order() as $slug ) {
			if ( isset( $choices[ $slug ] ) ) {
				$ordered[ $slug ] = $choices[ $slug ];
			}
		}

		return $ordered;
	}

	/**
	 * Reordena un mapa slug => etiqueta según la configuración del menú.
	 *
	 * @param array<string, string> $tabs Pestañas visibles.
	 * @return array<string, string>
	 */
	public static function sort_tabs_by_menu_order( array $tabs ) {
		if ( empty( $tabs ) ) {
			return $tabs;
		}

		$config_label = $tabs['logistica-configuracion'] ?? null;
		if ( null !== $config_label ) {
			unset( $tabs['logistica-configuracion'] );
		}

		$order  = self::get_operations_menu_order();
		$sorted = array();

		foreach ( $order as $slug ) {
			if ( isset( $tabs[ $slug ] ) ) {
				$sorted[ $slug ] = $tabs[ $slug ];
			}
		}

		foreach ( $tabs as $slug => $label ) {
			if ( ! isset( $sorted[ $slug ] ) ) {
				$sorted[ $slug ] = $label;
			}
		}

		if ( null !== $config_label ) {
			$sorted['logistica-configuracion'] = $config_label;
		}

		return $sorted;
	}

	/**
	 * @param array<int, string>|mixed $raw Slugs en orden desde POST.
	 * @return void
	 */
	public static function save_operations_menu_order( $raw ) {
		if ( ! is_array( $raw ) ) {
			$raw = array();
		}

		$choices = self::operations_menu_choices();
		$valid   = array();

		foreach ( $raw as $slug ) {
			$slug = sanitize_key( (string) $slug );
			if ( '' !== $slug && isset( $choices[ $slug ] ) && ! in_array( $slug, $valid, true ) ) {
				$valid[] = $slug;
			}
		}

		foreach ( self::default_operations_menu_order() as $slug ) {
			if ( ! in_array( $slug, $valid, true ) ) {
				$valid[] = $slug;
			}
		}

		update_option( self::OPTION_OPERATIONS_MENU_ORDER, $valid, false );
	}

	/**
	 * Pestañas del menú público por defecto.
	 *
	 * @return list<string>
	 */
	public static function default_frontend_menu_tabs() {
		return array(
			'logistica',
			'logistica-conversiones',
			'logistica-inventario-bodega',
			'logistica-cierre-ordenes',
			'logistica-planeacion-impresion',
			'logistica-planeacion-formado',
			'logistica-cierre-caracteristicas',
			'logistica-ayuda',
		);
	}

	/**
	 * Slugs que se pueden elegir para el panel público (sin Configuración).
	 *
	 * @return array<string, string> slug => etiqueta.
	 */
	public static function frontend_menu_choices() {
		return self::get_operations_menu_order_with_labels();
	}

	/**
	 * Pestañas visibles en el menú del frontend.
	 *
	 * @return list<string>
	 */
	public static function get_frontend_menu_tabs() {
		$saved = get_option( self::OPTION_FRONTEND_MENU, array() );

		if ( ! is_array( $saved ) ) {
			$saved = array();
		}

		$choices = self::frontend_menu_choices();
		$valid   = array();

		foreach ( $saved as $slug ) {
			$slug = sanitize_key( (string) $slug );
			if ( '' !== $slug && isset( $choices[ $slug ] ) ) {
				$valid[] = $slug;
			}
		}

		if ( empty( $valid ) ) {
			return self::default_frontend_menu_tabs();
		}

		return $valid;
	}

	/**
	 * @param array<int, string>|mixed $raw Slugs desde POST.
	 * @return void
	 */
	public static function save_frontend_menu_tabs( $raw ) {
		if ( ! is_array( $raw ) ) {
			$raw = array();
		}

		$choices = self::frontend_menu_choices();
		$valid   = array();

		foreach ( $raw as $slug ) {
			$slug = sanitize_key( (string) $slug );
			if ( '' !== $slug && isset( $choices[ $slug ] ) ) {
				$valid[] = $slug;
			}
		}

		if ( empty( $valid ) ) {
			$valid = self::default_frontend_menu_tabs();
		}

		update_option( self::OPTION_FRONTEND_MENU, $valid, false );
	}

	/**
	 * ID de la pagina publica que muestra el panel de inventarios.
	 *
	 * @return int
	 */
	public static function get_frontend_page_id() {
		return max( 0, (int) get_option( self::OPTION_FRONTEND_PAGE, 0 ) );
	}

	/**
	 * @param mixed $raw_page_id ID de pagina desde POST.
	 * @return void
	 */
	public static function save_frontend_page_id( $raw_page_id ) {
		$page_id = absint( $raw_page_id );

		if ( $page_id > 0 ) {
			if ( 'page' !== get_post_type( $page_id ) ) {
				$page_id = 0;
			} elseif ( in_array( get_post_status( $page_id ), array( 'trash', false ), true ) ) {
				$page_id = 0;
			}
		}

		update_option( self::OPTION_FRONTEND_PAGE, $page_id, false );

		if ( $page_id > 0 ) {
			self::ensure_page_has_panel_shortcode( $page_id );
		}
	}

	/**
	 * Estados de cotización/compra por defecto (panel operativo).
	 *
	 * @return array<string, string>
	 */
	public static function default_compra_statuses() {
		return array(
			'pendiente'            => 'Pendiente',
			'revision_cartera'     => 'Revisión cartera',
			'pago_anticipado'      => 'Pago anticipado',
			'credito_vencido'      => 'Crédito vencido',
			'esperando_aprobacion' => 'Esperando aprobación',
			'esperando_cotizacion' => 'Esperando cotización',
			'recibido'             => 'Recibido',
		);
	}

	/**
	 * Estados configurables del select «Modificar cotización».
	 *
	 * @return array<string, string>
	 */
	public static function get_compra_statuses() {
		$saved = get_option( self::OPTION_PANEL_COMPRA_STATUSES, null );

		if ( ! is_array( $saved ) || empty( $saved ) ) {
			return self::default_compra_statuses();
		}

		$statuses = array();

		foreach ( $saved as $key => $label ) {
			$key   = sanitize_key( (string) $key );
			$label = sanitize_text_field( (string) $label );
			if ( '' === $key || '' === $label ) {
				continue;
			}
			$statuses[ $key ] = $label;
		}

		return ! empty( $statuses ) ? self::ensure_pendiente_compra_status_first( $statuses ) : self::default_compra_statuses();
	}

	/**
	 * Asegura que «Pendiente» exista como primer estado en listas guardadas.
	 *
	 * @param array<string, string> $statuses Estados actuales.
	 * @return array<string, string>
	 */
	private static function ensure_pendiente_compra_status_first( array $statuses ) {
		if ( isset( $statuses['pendiente'] ) ) {
			$label = $statuses['pendiente'];
			unset( $statuses['pendiente'] );

			return array_merge( array( 'pendiente' => $label ), $statuses );
		}

		return array_merge( array( 'pendiente' => 'Pendiente' ), $statuses );
	}

	/**
	 * @param mixed $raw Filas desde POST (compra_statuses[][key|label]).
	 * @return void
	 */
	public static function save_compra_statuses( $raw ) {
		if ( ! is_array( $raw ) ) {
			$raw = array();
		}

		$statuses  = array();
		$used_keys = array();

		foreach ( $raw as $row ) {
			if ( ! is_array( $row ) ) {
				continue;
			}

			$label = sanitize_text_field( (string) ( $row['label'] ?? '' ) );
			if ( '' === $label ) {
				continue;
			}

			$key = sanitize_key( (string) ( $row['key'] ?? '' ) );
			if ( '' === $key ) {
				$key = sanitize_key( remove_accents( $label ) );
			}
			if ( '' === $key ) {
				continue;
			}

			$base = $key;
			$i    = 2;
			while ( isset( $used_keys[ $key ] ) ) {
				$key = $base . '_' . $i;
				++$i;
			}

			$used_keys[ $key ] = true;
			$statuses[ $key ]  = $label;
		}

		if ( empty( $statuses ) ) {
			$statuses = self::default_compra_statuses();
		}

		update_option( self::OPTION_PANEL_COMPRA_STATUSES, $statuses, false );
	}

	/**
	 * Ajustes de festivos del checklist (panel operativo).
	 *
	 * @return array{auto_sundays:bool,colombia_calendar:bool,extra_holidays:list<array{date:string,label:string}>,excluded_dates:list<string>}
	 */
	public static function default_panel_holidays() {
		return array(
			'auto_sundays'      => true,
			'colombia_calendar' => false,
			'extra_holidays'    => array(),
			'excluded_dates'    => array(),
		);
	}

	/**
	 * @return array{auto_sundays:bool,colombia_calendar:bool,extra_holidays:list<array{date:string,label:string}>,excluded_dates:list<string>}
	 */
	public static function get_panel_holidays() {
		$saved = get_option( self::OPTION_PANEL_HOLIDAYS, array() );
		$data  = wp_parse_args( is_array( $saved ) ? $saved : array(), self::default_panel_holidays() );

		$data['auto_sundays']      = ! empty( $data['auto_sundays'] );
		$data['colombia_calendar'] = ! empty( $data['colombia_calendar'] );

		$extra = array();
		foreach ( (array) ( $data['extra_holidays'] ?? array() ) as $row ) {
			if ( ! is_array( $row ) ) {
				continue;
			}

			$date = self::sanitize_holiday_date( $row['date'] ?? '' );
			if ( ! $date ) {
				continue;
			}

			$label = sanitize_text_field( (string) ( $row['label'] ?? '' ) );
			$extra[] = array(
				'date'  => $date,
				'label' => $label,
			);
		}
		$data['extra_holidays'] = $extra;

		$excluded = array();
		foreach ( (array) ( $data['excluded_dates'] ?? array() ) as $date ) {
			$date = self::sanitize_holiday_date( $date );
			if ( $date ) {
				$excluded[] = $date;
			}
		}
		$data['excluded_dates'] = array_values( array_unique( $excluded ) );

		return $data;
	}

	/**
	 * Configuración mínima expuesta al panel frontend.
	 *
	 * @return array{auto_sundays:bool,colombia_calendar:bool}
	 */
	public static function get_panel_holidays_client_config() {
		$settings = self::get_panel_holidays();

		return array(
			'auto_sundays'      => $settings['auto_sundays'],
			'colombia_calendar' => $settings['colombia_calendar'],
		);
	}

	/**
	 * Mapa fecha => etiqueta para varios años (calendario + extras − excluidos).
	 *
	 * @param int $from_year Primer año.
	 * @param int $to_year   Último año.
	 * @return array<string, string>
	 */
	public static function get_festivo_dates_map( $from_year, $to_year ) {
		$settings = self::get_panel_holidays();
		$dates    = array();

		foreach ( $settings['extra_holidays'] as $row ) {
			$dates[ $row['date'] ] = '' !== $row['label']
				? $row['label']
				: __( 'Festivo', 'logistica' );
		}

		ksort( $dates );

		return $dates;
	}

	/**
	 * Tipo de día automático para una fecha (solo «festivo» por domingo o vacío).
	 *
	 * @param string $date Fecha Y-m-d.
	 * @return string
	 */
	public static function resolve_automatic_day_type( $date ) {
		$date = self::sanitize_holiday_date( $date );
		if ( ! $date ) {
			return '';
		}

		$settings = self::get_panel_holidays();

		if ( $settings['auto_sundays'] ) {
			$dt = DateTimeImmutable::createFromFormat( 'Y-m-d', $date, wp_timezone() );
			if ( $dt && 7 === (int) $dt->format( 'N' ) ) {
				return 'festivo';
			}
		}

		foreach ( $settings['extra_holidays'] as $row ) {
			if ( ( $row['date'] ?? '' ) === $date ) {
				return 'festivo';
			}
		}

		return '';
	}

	/**
	 * @param mixed $raw Ajustes desde POST.
	 * @return void
	 */
	public static function save_panel_holidays( $raw ) {
		if ( ! is_array( $raw ) ) {
			$raw = array();
		}

		$data = array(
			'auto_sundays'      => ! empty( $raw['auto_sundays'] ),
			'colombia_calendar' => false,
			'extra_holidays'    => array(),
			'excluded_dates'    => array(),
		);

		foreach ( (array) ( $raw['extra_holidays'] ?? array() ) as $row ) {
			if ( ! is_array( $row ) ) {
				continue;
			}

			$date = self::sanitize_holiday_date( $row['date'] ?? '' );
			if ( ! $date ) {
				continue;
			}

			$data['extra_holidays'][] = array(
				'date'  => $date,
				'label' => sanitize_text_field( (string) ( $row['label'] ?? '' ) ),
			);
		}

		update_option( self::OPTION_PANEL_HOLIDAYS, $data, false );
	}

	/**
	 * @param mixed $value Fecha Y-m-d.
	 * @return string
	 */
	private static function sanitize_holiday_date( $value ) {
		$value = sanitize_text_field( (string) $value );
		if ( ! preg_match( '/^\d{4}-\d{2}-\d{2}$/', $value ) ) {
			return '';
		}

		$dt = DateTimeImmutable::createFromFormat( 'Y-m-d', $value, wp_timezone() );
		if ( ! $dt || $dt->format( 'Y-m-d' ) !== $value ) {
			return '';
		}

		return $value;
	}

	/**
	 * Asegura que la pagina elegida incluya el shortcode del panel.
	 *
	 * @param int $page_id Page ID.
	 * @return void
	 */
	private static function ensure_page_has_panel_shortcode( $page_id ) {
		$post = get_post( $page_id );
		if ( ! $post instanceof WP_Post ) {
			return;
		}

		if ( has_shortcode( $post->post_content, 'logistica_panel' ) || has_shortcode( $post->post_content, 'latingraf_inventarios' ) ) {
			return;
		}

		$content = trim( (string) $post->post_content );
		if ( '' !== $content ) {
			$content .= "\n\n";
		}
		$content .= '[logistica_panel]';

		wp_update_post(
			array(
				'ID'           => $page_id,
				'post_content' => $content,
			)
		);
	}
}
