<?php

namespace GriffinForms\Frontend\Security\FieldValidations;

use GriffinForms\Includes\Helpers\Currency;
use GriffinForms\Settings;

class Payment extends \GriffinForms\Frontend\Security\FieldValidations\Format
{
    protected function customValidate($value, $iteration_index)
    {
        $entries = $value;
        if (isset($value['items']) && is_array($value['items'])) {
            $entries = $value['items'];
        }

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

        $products = $this->getProductsMap();
        if (empty($products)) {
            $this->addError(__('The selected product is no longer available.', 'griffinforms-form-builder'), $iteration_index);
            return;
        }

        foreach ($entries as $entry) {
            $product_id = $entry['product_id'] ?? '';
            if (empty($product_id) || !isset($products[$product_id])) {
                $this->addError(__('Invalid payment selection.', 'griffinforms-form-builder'), $iteration_index);
                continue;
            }

            $product = $products[$product_id];
            $quantity = absint($entry['quantity'] ?? 0);
            $min_qty = max(1, absint($product['min_qty'] ?? 1));
            $max_qty = max($min_qty, absint($product['max_qty'] ?? $min_qty));

            if ($quantity < $min_qty || $quantity > $max_qty) {
                $this->addError(__('Selected quantity is out of range.', 'griffinforms-form-builder'), $iteration_index);
            }

            $unit_price = (float) ($product['price'] ?? 0);
            $submitted_price = isset($entry['unit_price']) ? (float) $entry['unit_price'] : null;

            if ($submitted_price === null || abs($submitted_price - $unit_price) > 0.01) {
                $this->addError(__('The submitted amount does not match the configured price.', 'griffinforms-form-builder'), $iteration_index);
            }
        }
    }

    protected function transformSanitizedValues(array $values)
    {
        $products = $this->getProductsMap();
        $settings = Settings::getInstance();
        $currency_helper = Currency::getInstance();
        $currency = $currency_helper->sanitizeCurrency($settings->getOption('payment_currency', 'USD'));

        $flattened = [];
        $selected_gateway = '';

        foreach ($values as $entry_list) {
            $entries = $entry_list;
            $current_gateway = '';
            if (isset($entry_list['items']) && is_array($entry_list['items'])) {
                $entries = $entry_list['items'];
                $current_gateway = sanitize_key($entry_list['gateway'] ?? '');
            }

            if (!is_array($entries)) {
                continue;
            }

            if ($selected_gateway === '' && $current_gateway !== '') {
                $selected_gateway = $current_gateway;
            }

            foreach ($entries as $entry) {
                $product_id = $entry['product_id'] ?? '';
                if (empty($product_id) || !isset($products[$product_id])) {
                    continue;
                }

                $product = $products[$product_id];
                $quantity = absint($entry['quantity'] ?? $product['default_qty'] ?? 1);
                $min_qty = max(1, absint($product['min_qty'] ?? 1));
                $max_qty = max($min_qty, absint($product['max_qty'] ?? $min_qty));
                $quantity = max($min_qty, min($quantity, $max_qty));
                $unit_price = (float) ($product['price'] ?? 0);

                $flattened[] = array(
                    'product_id'   => sanitize_text_field($product_id),
                    'product_name' => sanitize_text_field($product['name'] ?? ''),
                    'quantity'     => $quantity,
                    'unit_price'   => $unit_price,
                    'total'        => $unit_price * $quantity,
                    'currency'     => $currency,
                );
            }
        }

        $this->enforceSelectionLimits(count($flattened));

        return array(
            'items' => $flattened,
            'gateway' => $selected_gateway,
        );
    }

    private function enforceSelectionLimits(int $selected_count): void
    {
        $settings = $this->field->getProp('field_settings') ?? [];
        $min_select = isset($settings['min_select']) ? max(0, (int) $settings['min_select']) : 0;
        $max_select = isset($settings['max_select']) ? max(0, (int) $settings['max_select']) : 0;

        if ($min_select > 0 && $selected_count < $min_select) {
            $this->addError(sprintf(__('Please select at least %d product(s).', 'griffinforms-form-builder'), $min_select));
        }

        if ($max_select > 0 && $selected_count > $max_select) {
            $this->addError(sprintf(__('You can select up to %d product(s).', 'griffinforms-form-builder'), $max_select));
        }
    }

    private function getProductsMap(): array
    {
        $options = $this->field->getProp('field_options');
        if (!is_array($options) || empty($options)) {
            return [];
        }

        $map = [];
        foreach ($options as $product) {
            if (!is_array($product)) {
                continue;
            }
            $product_id = $product['id'] ?? '';
            if ($product_id === '') {
                continue;
            }
            $map[$product_id] = $product;
        }

        return $map;
    }
}
