<?php
/**
 * Historial global de logos de texto e imagen para etiquetas de producción.
 *
 * @package Logistica
 */

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

/**
 * Persistencia del historial de logos usados al imprimir o guardar ajustes.
 */
class Logistica_Label_Logo_History {

	public const OPTION_KEY   = 'logistica_label_logo_history';
	public const MAX_ENTRIES  = 8;

	/**
	 * @return array{image: array<int, array<string, string>>, text: array<int, array<string, string>>}
	 */
	public static function get_all() {
		$stored = get_option( self::OPTION_KEY, array() );
		if ( ! is_array( $stored ) ) {
			$stored = array();
		}

		return array(
			'image' => self::normalize_image_entries( $stored['image'] ?? array() ),
			'text'  => self::normalize_text_entries( $stored['text'] ?? array() ),
		);
	}

	/**
	 * @return array{image: array<int, array<string, string>>, text: array<int, array<string, string>>}
	 */
	public static function client_format() {
		return self::get_all();
	}

	/**
	 * @param array<string, mixed> $settings Ajustes de Logistica_Label_Print.
	 * @return array{image: array<int, array<string, string>>, text: array<int, array<string, string>>}
	 */
	public static function save_from_settings( $settings ) {
		if ( ! is_array( $settings ) ) {
			return self::get_all();
		}

		$mode = Logistica_Label_Print::sanitize_logo_mode( $settings[ Logistica_Label_Print::OPTION_LOGO_MODE ] ?? 'image' );

		if ( 'image' === $mode ) {
			$url = esc_url_raw( (string) ( $settings[ Logistica_Label_Print::OPTION_LOGO_URL ] ?? '' ) );
			if ( '' !== $url ) {
				self::save_image( $url );
			}
		} else {
			self::save_text(
				(string) ( $settings[ Logistica_Label_Print::OPTION_LOGO_TEXT_LINE1 ] ?? '' ),
				(string) ( $settings[ Logistica_Label_Print::OPTION_LOGO_TEXT_LINE2 ] ?? '' )
			);
		}

		return self::get_all();
	}

	/**
	 * @param string $url URL de imagen.
	 * @return array{image: array<int, array<string, string>>, text: array<int, array<string, string>>}|WP_Error
	 */
	public static function save_image( $url ) {
		$url = esc_url_raw( trim( (string) $url ) );
		if ( '' === $url ) {
			return new WP_Error( 'invalid_url', __( 'Indica una URL de imagen válida.', 'logistica' ) );
		}

		if ( self::is_default_logo_url( $url ) ) {
			return self::get_all();
		}

		$entry = array(
			'url'          => $url,
			'label'        => self::image_label( $url ),
			'last_used_at' => current_time( 'mysql', true ),
		);

		$history = self::get_all();
		$history['image'] = self::push_entry(
			$history['image'],
			$entry,
			static function ( $item ) use ( $url ) {
				return (string) ( $item['url'] ?? '' ) === $url;
			}
		);

		self::persist( $history );

		return $history;
	}

	/**
	 * @param string $line1 Línea principal.
	 * @param string $line2 Línea secundaria.
	 * @return array{image: array<int, array<string, string>>, text: array<int, array<string, string>>}|WP_Error
	 */
	public static function save_text( $line1, $line2 ) {
		$line1 = sanitize_text_field( (string) $line1 );
		$line2 = sanitize_text_field( (string) $line2 );

		if ( '' === $line1 && '' === $line2 ) {
			return new WP_Error( 'invalid_text', __( 'Indica al menos una línea de texto.', 'logistica' ) );
		}

		$entry = array(
			'line1'        => $line1,
			'line2'        => $line2,
			'label'        => self::text_label( $line1, $line2 ),
			'last_used_at' => current_time( 'mysql', true ),
		);

		$history = self::get_all();
		$history['text'] = self::push_entry(
			$history['text'],
			$entry,
			static function ( $item ) use ( $line1, $line2 ) {
				return (string) ( $item['line1'] ?? '' ) === $line1 && (string) ( $item['line2'] ?? '' ) === $line2;
			}
		);

		self::persist( $history );

		return $history;
	}

	/**
	 * @param string $mode Modo image|text.
	 * @param string $logo_url URL imagen.
	 * @param string $line1 Línea 1.
	 * @param string $line2 Línea 2.
	 * @return array{image: array<int, array<string, string>>, text: array<int, array<string, string>>}|WP_Error
	 */
	public static function save_from_payload( $mode, $logo_url, $line1, $line2 ) {
		if ( 'image' === Logistica_Label_Print::sanitize_logo_mode( $mode ) ) {
			return self::save_image( $logo_url );
		}

		return self::save_text( $line1, $line2 );
	}

	/**
	 * @param mixed $entries Entradas crudas.
	 * @return array<int, array<string, string>>
	 */
	private static function normalize_image_entries( $entries ) {
		if ( ! is_array( $entries ) ) {
			return array();
		}

		$normalized = array();
		foreach ( $entries as $entry ) {
			if ( ! is_array( $entry ) ) {
				continue;
			}
			$url = esc_url_raw( (string) ( $entry['url'] ?? '' ) );
			if ( '' === $url || self::is_default_logo_url( $url ) ) {
				continue;
			}
			$normalized[] = array(
				'url'          => $url,
				'label'        => self::image_label( $url, (string) ( $entry['label'] ?? '' ) ),
				'last_used_at' => sanitize_text_field( (string) ( $entry['last_used_at'] ?? '' ) ),
			);
		}

		return array_slice( $normalized, 0, self::MAX_ENTRIES );
	}

	/**
	 * @param mixed $entries Entradas crudas.
	 * @return array<int, array<string, string>>
	 */
	private static function normalize_text_entries( $entries ) {
		if ( ! is_array( $entries ) ) {
			return array();
		}

		$normalized = array();
		foreach ( $entries as $entry ) {
			if ( ! is_array( $entry ) ) {
				continue;
			}
			$line1 = sanitize_text_field( (string) ( $entry['line1'] ?? '' ) );
			$line2 = sanitize_text_field( (string) ( $entry['line2'] ?? '' ) );
			if ( '' === $line1 && '' === $line2 ) {
				continue;
			}
			$normalized[] = array(
				'line1'        => $line1,
				'line2'        => $line2,
				'label'        => self::text_label( $line1, $line2, (string) ( $entry['label'] ?? '' ) ),
				'last_used_at' => sanitize_text_field( (string) ( $entry['last_used_at'] ?? '' ) ),
			);
		}

		return array_slice( $normalized, 0, self::MAX_ENTRIES );
	}

	/**
	 * @param array<int, array<string, string>> $entries Lista actual.
	 * @param array<string, string>             $entry Nueva entrada.
	 * @param callable                          $matcher Comparador de duplicados.
	 * @return array<int, array<string, string>>
	 */
	private static function push_entry( $entries, $entry, $matcher ) {
		$entries = is_array( $entries ) ? $entries : array();
		$entries = array_values(
			array_filter(
				$entries,
				static function ( $item ) use ( $matcher ) {
					return ! $matcher( $item );
				}
			)
		);

		array_unshift( $entries, $entry );

		return array_slice( $entries, 0, self::MAX_ENTRIES );
	}

	/**
	 * @param array{image: array<int, array<string, string>>, text: array<int, array<string, string>>} $history Historial.
	 * @return void
	 */
	private static function persist( $history ) {
		update_option(
			self::OPTION_KEY,
			array(
				'image' => self::normalize_image_entries( $history['image'] ?? array() ),
				'text'  => self::normalize_text_entries( $history['text'] ?? array() ),
			),
			false
		);
	}

	/**
	 * @param string $url URL.
	 * @return bool
	 */
	private static function is_default_logo_url( $url ) {
		return untrailingslashit( (string) $url ) === untrailingslashit( Logistica_Label_Print::default_logo_url() );
	}

	/**
	 * @param string $url URL.
	 * @param string $fallback Etiqueta previa.
	 * @return string
	 */
	private static function image_label( $url, $fallback = '' ) {
		if ( '' !== $fallback ) {
			return $fallback;
		}

		$path = wp_parse_url( $url, PHP_URL_PATH );
		if ( is_string( $path ) && '' !== $path ) {
			$basename = basename( $path );
			if ( '' !== $basename ) {
				return $basename;
			}
		}

		return wp_html_excerpt( $url, 48, '…' );
	}

	/**
	 * @param string $line1 Línea 1.
	 * @param string $line2 Línea 2.
	 * @param string $fallback Etiqueta previa.
	 * @return string
	 */
	private static function text_label( $line1, $line2, $fallback = '' ) {
		if ( '' !== $fallback ) {
			return $fallback;
		}

		if ( '' !== $line1 && '' !== $line2 ) {
			return $line1 . ' · ' . $line2;
		}

		return '' !== $line1 ? $line1 : $line2;
	}
}
