<?php
/**
 * Catálogo de rendimiento (und/h) por referencia — solo planeación formado.
 *
 * @package Logistica
 */

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

/**
 * Persistencia y cálculo de rendimiento por referencia de producto.
 */
class Logistica_Forming_Yield {

	const OPTION_KEY = 'logistica_forming_yield_catalog';

	/**
	 * @return list<array{key:string,label:string,units_per_hour:int}>
	 */
	public static function default_entries() {
		return array(
			array( 'key' => 'vaso_4_oz', 'label' => 'Vaso 4 oz', 'units_per_hour' => 1800 ),
			array( 'key' => 'vaso_6_oz', 'label' => 'Vaso 6 oz', 'units_per_hour' => 2500 ),
			array( 'key' => 'vaso_7_oz', 'label' => 'Vaso 7 oz', 'units_per_hour' => 5000 ),
			array( 'key' => 'vaso_7_oz_doble_pared', 'label' => 'Vaso 7 oz doble pared', 'units_per_hour' => 2500 ),
			array( 'key' => 'vaso_8_oz', 'label' => 'Vaso 8 oz', 'units_per_hour' => 1800 ),
			array( 'key' => 'vaso_8_oz_doble_pared', 'label' => 'Vaso 8 oz doble pared', 'units_per_hour' => 1800 ),
			array( 'key' => 'vaso_9_oz', 'label' => 'Vaso 9 oz', 'units_per_hour' => 5000 ),
			array( 'key' => 'vaso_9_oz_doble_pared', 'label' => 'Vaso 9 oz doble pared', 'units_per_hour' => 2500 ),
			array( 'key' => 'vaso_10_oz', 'label' => 'Vaso 10 oz', 'units_per_hour' => 2000 ),
			array( 'key' => 'vaso_10_oz_doble_pared', 'label' => 'Vaso 10 oz doble pared', 'units_per_hour' => 2000 ),
			array( 'key' => 'vaso_12_oz', 'label' => 'Vaso 12 oz', 'units_per_hour' => 1800 ),
			array( 'key' => 'vaso_12_oz_doble_pared', 'label' => 'Vaso 12 oz doble pared', 'units_per_hour' => 1800 ),
			array( 'key' => 'vaso_12_oz_boca_80_mm', 'label' => 'Vaso 12 oz boca 80 mm', 'units_per_hour' => 1800 ),
			array( 'key' => 'vaso_14_oz_12_oz_exp', 'label' => 'Vaso 14 oz (12 oz Exp)', 'units_per_hour' => 2000 ),
			array( 'key' => 'vaso_14_oz_doble_pared_12_oz_exp', 'label' => 'Vaso 14 oz doble pared (12 oz Exp)', 'units_per_hour' => 2000 ),
			array( 'key' => 'vaso_14_oz_bio_12_oz_exp', 'label' => 'Vaso 14 oz Bio (12 oz Exp)', 'units_per_hour' => 2000 ),
			array( 'key' => 'vaso_16_oz', 'label' => 'Vaso 16 oz', 'units_per_hour' => 2000 ),
			array( 'key' => 'vaso_16_oz_doble_pared', 'label' => 'Vaso 16 oz doble pared', 'units_per_hour' => 2000 ),
			array( 'key' => 'tazon_5_6_oz', 'label' => 'Tazón 5-6 oz', 'units_per_hour' => 1000 ),
			array( 'key' => 'tazon_8_oz', 'label' => 'Tazón 8 oz', 'units_per_hour' => 1800 ),
			array( 'key' => 'tazon_10_oz', 'label' => 'Tazón 10 oz', 'units_per_hour' => 1800 ),
			array( 'key' => 'tazon_16_oz', 'label' => 'Tazón 16 oz', 'units_per_hour' => 1800 ),
		);
	}

	/**
	 * @param string $label Etiqueta visible.
	 * @return string
	 */
	public static function key_from_label( $label ) {
		$label = remove_accents( strtolower( trim( sanitize_text_field( (string) $label ) ) ) );
		$label = preg_replace( '/[^a-z0-9]+/', '_', $label );
		$label = trim( (string) $label, '_' );

		return '' !== $label ? $label : 'referencia';
	}

	/**
	 * @param mixed $raw Lista de entradas.
	 * @return list<array{key:string,label:string,units_per_hour:int}>
	 */
	public static function sanitize_entries( $raw ) {
		if ( ! is_array( $raw ) ) {
			return array();
		}

		$clean = array();
		$keys  = array();

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

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

			$key = sanitize_key( (string) ( $entry['key'] ?? '' ) );
			if ( '' === $key ) {
				$key = self::key_from_label( $label );
			}

			$base = $key;
			$suffix = 2;
			while ( isset( $keys[ $key ] ) ) {
				$key = $base . '_' . $suffix;
				++$suffix;
			}
			$keys[ $key ] = true;

			$units = isset( $entry['units_per_hour'] ) ? (int) $entry['units_per_hour'] : 0;
			if ( $units <= 0 ) {
				continue;
			}

			$clean[] = array(
				'key'            => $key,
				'label'          => $label,
				'units_per_hour' => min( 999999, $units ),
			);
		}

		return $clean;
	}

	/**
	 * @return list<array{key:string,label:string,units_per_hour:int}>
	 */
	public static function get_entries() {
		$saved = get_option( self::OPTION_KEY, null );

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

		$clean = self::sanitize_entries( $saved );

		return ! empty( $clean ) ? $clean : self::default_entries();
	}

	/**
	 * @return array<string, string> key => label.
	 */
	public static function get_options() {
		$options = array();

		foreach ( self::get_entries() as $entry ) {
			$options[ $entry['key'] ] = $entry['label'];
		}

		return $options;
	}

	/**
	 * @param string $key Clave de referencia.
	 * @return int
	 */
	public static function get_units_per_hour( $key ) {
		$key = sanitize_key( (string) $key );
		if ( '' === $key ) {
			return 0;
		}

		foreach ( self::get_entries() as $entry ) {
			if ( $entry['key'] === $key ) {
				return (int) $entry['units_per_hour'];
			}
		}

		return 0;
	}

	/**
	 * @param list<array<string, mixed>> $entries Entradas del cliente.
	 * @return list<array{key:string,label:string,units_per_hour:int}>|\WP_Error
	 */
	public static function save_catalog( $entries ) {
		$clean = self::sanitize_entries( $entries );

		if ( empty( $clean ) ) {
			return new WP_Error( 'invalid_yield', __( 'Debe existir al menos una referencia con rendimiento válido.', 'logistica' ) );
		}

		update_option( self::OPTION_KEY, $clean, false );

		return $clean;
	}

	/**
	 * Minutos según cantidad y rendimiento und/h (solo formado con referencia).
	 *
	 * @param int|null $count          Unidades.
	 * @param string   $complexity     Complejidad.
	 * @param string   $referencia_key Clave de referencia.
	 * @return int|null
	 */
	public static function duration_from_yield( $count, $complexity, $referencia_key ) {
		if ( null === $count || $count <= 0 ) {
			return null;
		}

		$units_per_hour = self::get_units_per_hour( $referencia_key );
		if ( $units_per_hour <= 0 ) {
			return null;
		}

		$factor  = Logistica_Forming_Planning::COMPLEXITY_FACTORS[ Logistica_Forming_Planning::sanitize_complexity( $complexity ) ];
		$minutes = ( $count / $units_per_hour ) * 60 * $factor;
		$minutes = (int) ( round( $minutes / 15 ) * 15 );

		return max( 15, $minutes );
	}
}
