<?php
/**
 * Conteo de uso de opciones de catálogo en productos EAN.
 *
 * @package Logistica
 */

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

/**
 * Consultas sobre la tabla etiqueta_productos.
 */
class Logistica_Label_Etiqueta_Option_Usage {

	/**
	 * @return string
	 */
	private static function catalog_table() {
		return (string) Logistica_Database::table( 'etiqueta_productos' );
	}

	/**
	 * @param string $key Clave de tipo normalizada.
	 * @return int
	 */
	public static function count_tipo( $key ) {
		global $wpdb;

		$key   = Logistica_Label_Etiqueta_Tipos::normalize_key( $key );
		$table = self::catalog_table();

		if ( '' === $key || '' === $table ) {
			return 0;
		}

		return (int) $wpdb->get_var(
			$wpdb->prepare(
				"SELECT COUNT(*) FROM {$table} WHERE tipo_producto = %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
				$key
			)
		);
	}

	/**
	 * @param string $key Clave de mercado normalizada.
	 * @return int
	 */
	public static function count_mercado( $key ) {
		global $wpdb;

		$key   = Logistica_Label_Etiqueta_Mercados::normalize_key( $key );
		$table = self::catalog_table();

		if ( '' === $key || '' === $table ) {
			return 0;
		}

		return (int) $wpdb->get_var(
			$wpdb->prepare(
				"SELECT COUNT(*) FROM {$table} WHERE mercado = %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
				$key
			)
		);
	}

	/**
	 * @param mixed $label Tamaño visible.
	 * @return int
	 */
	public static function count_tamano( $label ) {
		global $wpdb;

		$label = Logistica_Label_Etiqueta_Tamanos::normalize_label( $label );
		$table = self::catalog_table();

		if ( '' === $label || '' === $table ) {
			return 0;
		}

		return (int) $wpdb->get_var(
			$wpdb->prepare(
				"SELECT COUNT(*) FROM {$table} WHERE tamano = %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
				$label
			)
		);
	}

	/**
	 * @param string $kind tipo|mercado|tamano.
	 * @param string $key  Clave o etiqueta según el tipo.
	 * @return int
	 */
	public static function count_for_kind( $kind, $key ) {
		switch ( (string) $kind ) {
			case 'tipo':
				return self::count_tipo( $key );
			case 'mercado':
				return self::count_mercado( $key );
			case 'tamano':
				return self::count_tamano( $key );
			default:
				return 0;
		}
	}

	/**
	 * @param string $kind tipo|mercado|tamano.
	 * @param string $key  Clave o etiqueta según el tipo.
	 * @return string
	 */
	public static function usage_message( $kind, $key ) {
		$usage = self::count_for_kind( $kind, $key );

		if ( $usage <= 0 ) {
			return '';
		}

		return sprintf(
			/* translators: %d: number of catalog products */
			_n(
				'Esta opción se usa en %d producto del catálogo.',
				'Esta opción se usa en %d productos del catálogo.',
				$usage,
				'logistica'
			),
			$usage
		);
	}

	/**
	 * @param string $kind tipo|mercado|tamano.
	 * @param string $key  Clave o etiqueta según el tipo.
	 * @return bool
	 */
	public static function is_hidden_kind( $kind, $key ) {
		switch ( (string) $kind ) {
			case 'tipo':
				return Logistica_Label_Etiqueta_Tipos::is_hidden( $key );
			case 'mercado':
				return Logistica_Label_Etiqueta_Mercados::is_hidden( $key );
			case 'tamano':
				return Logistica_Label_Etiqueta_Tamanos::is_hidden( $key );
			default:
				return false;
		}
	}

	/**
	 * @param string $kind tipo|mercado|tamano.
	 * @param string $key  Clave o etiqueta según el tipo.
	 * @return string
	 */
	public static function hidden_option_label( $kind, $key ) {
		$key = trim( (string) $key );

		if ( '' === $key || ! self::is_hidden_kind( $kind, $key ) ) {
			return $key;
		}

		switch ( (string) $kind ) {
			case 'tipo':
				$hidden = Logistica_Label_Etiqueta_Tipos::get_hidden();
				$key    = Logistica_Label_Etiqueta_Tipos::normalize_key( $key );
				$label  = trim( (string) ( $hidden[ $key ]['label'] ?? '' ) );
				if ( '' !== $label ) {
					return $label;
				}
				$base = Logistica_Label_Barcode::base_product_type_options();
				return isset( $base[ $key ] ) ? (string) $base[ $key ] : ucwords( strtolower( str_replace( '_', ' ', $key ) ) );
			case 'mercado':
				$hidden = Logistica_Label_Etiqueta_Mercados::get_hidden();
				$key    = Logistica_Label_Etiqueta_Mercados::normalize_key( $key );
				$label  = trim( (string) ( $hidden[ $key ]['label'] ?? '' ) );
				if ( '' !== $label ) {
					return $label;
				}
				$built_in = Logistica_Label_Etiqueta_Mercados::get_built_in();
				return isset( $built_in[ $key ] ) ? (string) $built_in[ $key ]['label'] : $key;
			case 'tamano':
				return Logistica_Label_Etiqueta_Tamanos::normalize_label( $key );
			default:
				return $key;
		}
	}

	/**
	 * Mapa de opciones ocultas para el panel operativo (JSON en data-*).
	 *
	 * @return array{tipos: array<string, string>, mercados: array<string, string>, tamanos: array<string, string>}
	 */
	public static function hidden_options_client_map() {
		$map = array(
			'tipos'    => array(),
			'mercados' => array(),
			'tamanos'  => array(),
		);

		foreach ( Logistica_Label_Etiqueta_Tipos::get_hidden() as $key => $meta ) {
			$map['tipos'][ (string) $key ] = self::hidden_option_label( 'tipo', (string) $key );
		}

		foreach ( Logistica_Label_Etiqueta_Mercados::get_hidden() as $key => $meta ) {
			$map['mercados'][ (string) $key ] = self::hidden_option_label( 'mercado', (string) $key );
		}

		foreach ( Logistica_Label_Etiqueta_Tamanos::get_hidden() as $key => $meta ) {
			$map['tamanos'][ (string) $key ] = self::hidden_option_label( 'tamano', (string) $key );
		}

		return $map;
	}

	/**
	 * @param array<string, mixed> $row Fila del catálogo.
	 * @return list<array{kind:string,key:string,label:string,field_label:string}>
	 */
	public static function row_hidden_issues( $row ) {
		$issues = array();

		if ( ! is_array( $row ) ) {
			return $issues;
		}

		$checks = array(
			array(
				'kind'        => 'tipo',
				'field_label' => __( 'Tipo producto', 'logistica' ),
				'value'       => (string) ( $row['tipo_producto'] ?? '' ),
			),
			array(
				'kind'        => 'mercado',
				'field_label' => __( 'Mercado', 'logistica' ),
				'value'       => (string) ( $row['mercado'] ?? '' ),
			),
			array(
				'kind'        => 'tamano',
				'field_label' => __( 'Tamaño', 'logistica' ),
				'value'       => (string) ( $row['tamano'] ?? '' ),
			),
		);

		foreach ( $checks as $check ) {
			$value = trim( (string) $check['value'] );
			if ( '' === $value || ! self::is_hidden_kind( $check['kind'], $value ) ) {
				continue;
			}

			$issues[] = array(
				'kind'        => (string) $check['kind'],
				'key'         => $value,
				'label'       => self::hidden_option_label( $check['kind'], $value ),
				'field_label' => (string) $check['field_label'],
			);
		}

		return $issues;
	}

	/**
	 * Mensaje legible para filas del catálogo con opciones ocultas.
	 *
	 * @param array<string, mixed> $row Fila del catálogo o lista de issues.
	 * @return string
	 */
	public static function row_hidden_hint_message( $row ) {
		$issues = is_array( $row ) && isset( $row[0]['kind'] )
			? $row
			: self::row_hidden_issues( $row );

		if ( empty( $issues ) ) {
			return '';
		}

		$parts = array();
		foreach ( $issues as $issue ) {
			$parts[] = sprintf(
				'%s (%s)',
				(string) ( $issue['field_label'] ?? '' ),
				(string) ( $issue['label'] ?? $issue['key'] ?? '' )
			);
		}

		return sprintf(
			/* translators: %s: comma-separated list of hidden catalog fields */
			__( 'Este código usa opciones ocultas del catálogo: %s. Edítalo para restaurarlas o elegir otras disponibles.', 'logistica' ),
			implode( ', ', $parts )
		);
	}

	/**
	 * @return list<array{kind:string,key:string,label:string,meta:string,usage:int}>
	 */
	public static function hidden_catalog_entries() {
		$entries = array_merge(
			Logistica_Label_Etiqueta_Tipos::get_hidden_admin_entries(),
			Logistica_Label_Etiqueta_Mercados::get_hidden_admin_entries(),
			Logistica_Label_Etiqueta_Tamanos::get_hidden_admin_entries()
		);

		usort(
			$entries,
			static function ( $a, $b ) {
				$kind = strnatcasecmp( (string) $a['kind'], (string) $b['kind'] );
				if ( 0 !== $kind ) {
					return $kind;
				}

				return strnatcasecmp( (string) $a['label'], (string) $b['label'] );
			}
		);

		return $entries;
	}
}
