<?php

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

class AIEO_Option_Groups_Pricing {

	
	public static function resolve( array $config, array $selected_option_ids ) {
		$groups = isset( $config['groups'] ) ? $config['groups'] : array();
		$rules  = isset( $config['rules'] ) ? $config['rules'] : array();

		$selected = array();
		foreach ( $selected_option_ids as $oid ) { $selected[ (int) $oid ] = true; }

		
		$opt_index    = array();
		$sel_by_group = array();
		foreach ( $groups as $gid => $g ) {
			$sel_by_group[ $gid ] = array();
			foreach ( $g['options'] as $oid => $o ) {
				$opt_index[ $oid ] = $o;
				if ( isset( $selected[ $oid ] ) ) { $sel_by_group[ $gid ][] = $oid; }
			}
		}

		
		$resolved = array();
		foreach ( array_keys( $selected ) as $oid ) {
			if ( ! isset( $opt_index[ $oid ] ) ) { continue; } 
			$o             = $opt_index[ $oid ];
			$assignment_id = isset( $groups[ $o['group_id'] ] ) ? (int) $groups[ $o['group_id'] ]['assignment_id'] : 0;
			$resolved[ $oid ] = self::resolve_option_price( $o, isset( $rules[ $oid ] ) ? $rules[ $oid ] : array(), $assignment_id, $selected );
		}

		
		$lines = array();
		$total = 0.0;
		foreach ( $groups as $gid => $g ) {
			$sel = $sel_by_group[ $gid ];
			if ( empty( $sel ) ) { continue; }

			$free_n = (int) $g['included_free'];
			$policy = ( 'cheapest_free' === $g['free_policy'] ) ? 'cheapest_free' : 'expensive_free';

			
			$pool = array();
			foreach ( $sel as $oid ) {
				if ( empty( $opt_index[ $oid ]['exclude_from_allowance'] ) ) { $pool[] = $oid; }
			}
			$free_set = array();
			if ( $free_n > 0 && $pool ) {
				usort( $pool, function ( $a, $b ) use ( $resolved, $policy ) {
					$pa = isset( $resolved[ $a ] ) ? $resolved[ $a ] : 0;
					$pb = isset( $resolved[ $b ] ) ? $resolved[ $b ] : 0;
					return ( 'cheapest_free' === $policy ) ? ( $pa <=> $pb ) : ( $pb <=> $pa );
				} );
				foreach ( array_slice( $pool, 0, $free_n ) as $oid ) { $free_set[ $oid ] = true; }
			}

			foreach ( $sel as $oid ) {
				$rd      = isset( $resolved[ $oid ] ) ? $resolved[ $oid ] : 0.0;
				$is_free = isset( $free_set[ $oid ] );
				$charged = $is_free ? 0.0 : $rd;
				$total  += $charged;
				$lines[] = array(
					'option_id'      => $oid,
					'group_id'       => $gid,
					'label'          => $opt_index[ $oid ]['label'],
					'resolved_delta' => round( $rd, 4 ),
					'charged_delta'  => round( $charged, 4 ),
					'free'           => $is_free,
				);
			}
		}

		$errors = self::validate( $groups, $sel_by_group, $opt_index );

		return array(
			'total_delta' => round( $total, 4 ),
			'lines'       => $lines,
			'valid'       => empty( $errors ),
			'errors'      => $errors,
		);
	}

	
	private static function resolve_option_price( array $option, array $rules, $assignment_id, array $selected ) {
		$best       = null;
		$best_score = -1;
		foreach ( $rules as $r ) {
			$scope = (int) $r['scope_assignment_id'];
			if ( 0 !== $scope && $scope !== (int) $assignment_id ) { continue; } 

			$wg = (int) $r['when_group_id'];
			if ( 0 !== $wg ) {
				$wo = (int) $r['when_option_id'];
				if ( 0 === $wo || ! isset( $selected[ $wo ] ) ) { continue; } 
			}

			$score = ( 0 !== $scope ? 2 : 0 ) + ( 0 !== $wg ? 1 : 0 );
			if ( $score > $best_score ) {
				$best       = $r;
				$best_score = $score;
			}
		}
		return null !== $best ? (float) $best['price_delta'] : (float) $option['price_delta'];
	}

	
	private static function validate( array $groups, array $sel_by_group, array $opt_index ) {
		$errors = array();
		foreach ( $groups as $gid => $g ) {
			$n   = isset( $sel_by_group[ $gid ] ) ? count( $sel_by_group[ $gid ] ) : 0;
			$min = (int) $g['min_select'];
			$max = (int) $g['max_select'];
			if ( $min > 0 && $n < $min ) {
				
				$errors[] = sprintf( _n( 'Choose at least %1$d option for “%2$s”.', 'Choose at least %1$d options for “%2$s”.', $min, 'ai-eshop-optimizer' ), $min, $g['name'] );
			}
			if ( $max > 0 && $n > $max ) {
				
				$errors[] = sprintf( _n( 'Choose at most %1$d option for “%2$s”.', 'Choose at most %1$d options for “%2$s”.', $max, 'ai-eshop-optimizer' ), $max, $g['name'] );
			}
			$sel = isset( $sel_by_group[ $gid ] ) ? $sel_by_group[ $gid ] : array();
			foreach ( $sel as $oid ) {
				if ( isset( $opt_index[ $oid ] ) && empty( $opt_index[ $oid ]['available'] ) ) {
					
					$errors[] = sprintf( __( '“%s” is sold out.', 'ai-eshop-optimizer' ), $opt_index[ $oid ]['label'] );
				}
			}
		}
		return $errors;
	}
}
