<?php

namespace App\Http\Requests\Admin;

use Illuminate\Foundation\Http\FormRequest;

/**
 * Product Save Request
 *
 * @property int $group_id
 * @property string $type
 * @property string|null $slug
 * @property int|null $category_id
 * @property int|null $order
 * @property string $name
 * @property string|null $description
 * @property bool $hidden
 * @property string $status
 * @property bool $require_domain
 * @property bool $stock_control
 * @property int|null $total_stock
 * @property int|null $used_stock
 * @property string $payment_type
 * @property bool $adaptive_pricing
 * @property string|null $setup_type
 * @property string|null $module
 * @property int|null $auto_suspension_days
 * @property int|null $auto_termination_days
 * @property bool $taxing
 * @property bool $affiliate_enabled
 * @property bool $is_featured
 * @property bool $free_domain_enabled
 * @property int|null $server_group
 * @property string $trial_mode
 * @property int|null $trial_period_days
 * @property bool $trial_ccsave
 * @property float|null $trial_paid_discount_percent
 * @property string|null $trial_default_period
 * @property bool $hide_setup_fees
 * @property string $auto_setup_option
 * @property string|null $welcome_email
 * @property int $setup_delay
 * @property array|null $pricing
 * @property array|null $onetime_pricing
 * @property array|null $onetime_setup_pricing
 * @property string|null $active_tab
 * @property array|null $module_config
 */
class ProductSaveRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Prepare the data for validation.
     */
    protected function prepareForValidation(): void
    {
        // Checkbox alanları için özel kontrol (seçili değilse false olarak ayarla)
        $checkboxFields = [
            'adaptive_pricing',
            'adaptive_term_pricing',
            'hide_setup_fees',
            'hidden',
            'require_domain',
            'stock_control',
            'is_featured',
            'tax_excluded',
            'affiliate_enabled',
            'free_domain_enabled',
            'trial_ccsave',
            // PRC-812 — yenilemeyi-kapat (default true; checkbox işaretsiz = false).
            'allow_renewal',
        ];

        $data = [];
        foreach ($checkboxFields as $field) {
            $data[$field] = $this->has($field) && $this->input($field);
        }

        // PRC-544 — trial_paid_discount_periods her zaman normalize edilir:
        // - Hiç checkbox işaretli değil veya key yok → NULL (= tüm periyotlar, geri-uyumlu).
        // - Bir veya daha fazla işaretli → int dizisi (tekil, sıralı).
        // NULL'a düşürmezsek "tümünü sil" davranışı kullanıcı için gizli bug üretir:
        // checkbox'ları kaldırıyor ama DB önceki listede kalıyor.
        $paidPeriods = $this->input('trial_paid_discount_periods');
        if (! is_array($paidPeriods) || empty($paidPeriods)) {
            $data['trial_paid_discount_periods'] = null;
        } else {
            $data['trial_paid_discount_periods'] = array_values(array_unique(array_map('intval', $paidPeriods)));
        }

        // PRC-697 — proration_enabled tri-state normalize: '' (miras) → null,
        // '1' → true, '0' → false. billing_anchor_day '' → null.
        $prorationEnabled = $this->input('proration_enabled');
        if ($prorationEnabled === '' || $prorationEnabled === null) {
            $data['proration_enabled'] = null;
        } else {
            $data['proration_enabled'] = (string) $prorationEnabled === '1';
        }

        $anchorDay = $this->input('billing_anchor_day');
        $data['billing_anchor_day'] = ($anchorDay === '' || $anchorDay === null)
            ? null
            : (int) $anchorDay;

        // PRC-812 — boş "müşteri başına maks. sipariş" = sınırsız (NULL). Boş string
        // gönderilirse integer cast'i 0'a düşürmesin diye açıkça NULL'a normalize et.
        $maxOrders = $this->input('max_orders_per_client');
        if ($maxOrders === '' || $maxOrders === null) {
            $data['max_orders_per_client'] = null;
        }

        $this->merge($data);
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        $rules = [
            'group_id' => ['required', 'integer', 'exists:product_groups,id'],
            // PRC-558 — SSL ürünleri için domain MANDATORY: require_domain=true zorunlu.
            // Provisioning AbstractSsl::createAccount() common_name'siz fail eder.
            'type' => ['required', 'string', 'in:hosting,server,ssl,software,license', function ($attr, $value, $fail) {
                if ($value === 'ssl' && ! $this->boolean('require_domain')) {
                    $fail(__('admin/products.validation_ssl_requires_domain'));
                }
            }],
            'slug' => ['nullable', 'string', 'max:255'],
            'category_id' => ['nullable', 'integer', 'exists:categories,id'],
            'order' => ['nullable', 'integer', 'min:0'],
            'name' => ['required', 'string', 'max:255'],
            'description' => ['nullable', 'string'],
            'hidden' => ['boolean'],
            'status' => ['required', 'string', 'in:active,inactive'],
            'require_domain' => ['boolean'],
            'stock_control' => ['boolean'],
            'total_stock' => ['nullable', 'integer', 'min:0'],
            'used_stock' => ['nullable', 'integer', 'min:0'],
            // PRC-812 — free/trial suistimal kontrolleri
            'max_orders_per_client' => ['nullable', 'integer', 'min:1'],
            'allow_renewal' => ['boolean'],
            'payment_type' => ['required', 'string', 'in:free,onetime,recurring'],
            'adaptive_pricing' => ['boolean'],
            'adaptive_term_pricing' => ['boolean'],
            // PRC-697 — pro-rata (ilk sipariş / ortak anchor). Tri-state:
            // prepareForValidation'da '' → null / '1' → true / '0' → false normalize edilir.
            'proration_enabled' => ['nullable', 'boolean'],
            'billing_anchor_day' => ['nullable', 'integer', 'min:1', 'max:31'],
            'setup_type' => ['nullable', 'string', 'in:free,onetime'],
            'module' => ['nullable', 'string'],
            'auto_suspension_days' => ['nullable', 'integer', 'min:0'],
            'auto_termination_days' => ['nullable', 'integer', 'min:0'],
            'tax_excluded' => ['boolean'],
            'affiliate_enabled' => ['boolean'],
            'is_featured' => ['boolean'],
            'free_domain_enabled' => ['boolean'],
            'server_group' => ['nullable', 'integer'],
            'trial_mode' => ['required', 'in:none,free,paid'],
            'trial_period_days' => ['nullable', 'integer', 'min:0'],
            'trial_ccsave' => ['boolean'],
            'trial_paid_discount_percent' => ['nullable', 'numeric', 'min:0', 'max:100'],
            // PRC-544 — null/eksik = tüm periyotlar (geri-uyumlu); dizi = sadece bu period (ay) değerleri.
            'trial_paid_discount_periods' => ['nullable', 'array'],
            'trial_paid_discount_periods.*' => ['integer', 'min:1', 'max:120'],
            // PRC-583 — trial_default_period UI'dan kaldırıldı; validated()'a girmesin ki
            // update() mevcut DB değerini sessizce null'lamasın. Kolon + null-safe
            // backend fallback (TrialService/CheckoutController) korundu.
            'hide_setup_fees' => ['boolean'],
            'auto_setup_option' => ['required', 'string', 'in:order,payment,manual,none'],
            'welcome_email' => ['nullable', 'string'],
            'setup_delay' => ['nullable', 'integer', 'min:0', 'max:1440'],
            'active_tab' => ['nullable', 'string', 'in:details,pricing,setup,module-settings,custom-fields,configurable-options,upgrades,contracts,trial,other'],

            // Recurring pricing validation - Laravel dokümantasyonuna uygun syntax
            'pricing' => ['nullable', 'array'],
            'pricing.*' => ['nullable', 'array'],
            'pricing.*.*' => ['nullable', 'array'],
            'pricing.*.*.active' => ['nullable', 'boolean'],
            'pricing.*.*.amount' => ['nullable', 'numeric', 'min:0'],
            'pricing.*.*.setup_amount' => ['nullable', 'numeric', 'min:0'],

            // Onetime pricing validation - Laravel dokümantasyonuna uygun syntax
            'onetime_pricing' => ['nullable', 'array'],
            'onetime_pricing.*' => ['nullable', 'array'],
            'onetime_pricing.*.active' => ['nullable', 'boolean'],
            'onetime_pricing.*.amount' => ['nullable', 'numeric', 'min:0'],

            // Onetime setup pricing validation - Laravel dokümantasyonuna uygun syntax
            'onetime_setup_pricing' => ['nullable', 'array'],
            'onetime_setup_pricing.*' => ['nullable', 'array'],
            'onetime_setup_pricing.*.amount' => ['nullable', 'numeric', 'min:0'],

            // Module configuration validation
            'module_config' => ['nullable', 'array'],
            'module_config.*' => ['nullable'],

            // Configurable option groups selection
            'config_option_group_ids' => ['nullable', 'array'],
            'config_option_group_ids.*' => ['integer', 'exists:product_config_option_groups,id'],

            // Upgrade / downgrade tab settings
            'allow_upgrade' => ['nullable', 'boolean'],
            'upgrade_fee' => ['nullable', 'numeric', 'min:0'],
            'downgrade_credit_mode' => ['nullable', 'in:balance_only,gateway_first,none'],

            // Contracts tab — product↔contract pivot (P3-T2)
            'contracts' => ['nullable', 'array'],
            'contracts.*.attached' => ['nullable', 'boolean'],
            'contracts.*.required' => ['nullable', 'boolean'],

            // PRC-382 / M4 — Late fee override (inherit / custom / disabled)
            'late_fee_mode' => ['nullable', 'string', 'in:inherit,custom,disabled'],
            'late_fee_type' => ['nullable', 'string', 'in:fixed,percentage'],
            'late_fee_amount' => ['nullable', 'numeric', 'min:0'],
            'late_fee_minimum' => ['nullable', 'numeric', 'min:0'],
        ];

        return $rules;
    }

    /**
     * Get custom messages for validator errors.
     *
     * @return array<string, string>
     */
    public function messages(): array
    {
        return [
            'group_id.required' => __('admin/products.validation.group_required'),
            'group_id.exists' => __('admin/products.validation.group_exists'),
            'name.required' => __('admin/products.validation.name_required'),
            'name.max' => __('admin/products.validation.name_max'),
            'type.required' => __('admin/products.validation.type_required'),
            'type.in' => __('admin/products.validation.type_in'),
            'payment_type.required' => __('admin/products.validation.payment_type_required'),
            'payment_type.in' => __('admin/products.validation.payment_type_in'),
            'status.required' => __('admin/products.validation.status_required'),
            'status.in' => __('admin/products.validation.status_in'),

            // Pricing validation messages
            'pricing.*.*.amount.numeric' => __('admin/products.validation.pricing_amount_numeric'),
            'pricing.*.*.amount.min' => __('admin/products.validation.pricing_amount_min'),
            'pricing.*.*.setup_amount.numeric' => __('admin/products.validation.setup_amount_numeric'),
            'pricing.*.*.setup_amount.min' => __('admin/products.validation.setup_amount_min'),

            'onetime_pricing.*.amount.numeric' => __('admin/products.validation.onetime_amount_numeric'),
            'onetime_pricing.*.amount.min' => __('admin/products.validation.onetime_amount_min'),

            'onetime_setup_pricing.*.amount.numeric' => __('admin/products.validation.onetime_setup_amount_numeric'),
            'onetime_setup_pricing.*.amount.min' => __('admin/products.validation.onetime_setup_amount_min'),

            // Module config validation messages
            'module_config.*.required' => __('admin/products.validation.module_config_field_required'),
        ];
    }

    /**
     * Get custom attributes for validator errors.
     *
     * @return array<string, string>
     */
    public function attributes(): array
    {
        return [
            'group_id' => __('admin/products.fields_group'),
            'name' => __('admin/products.fields_name'),
            'type' => __('admin/products.fields_type'),
            'payment_type' => __('admin/products.fields.payment_type'),
            'status' => __('admin/products.fields_status'),
            'description' => __('admin/products.fields_description'),
            'adaptive_pricing' => __('admin/products.fields_adaptive_pricing'),
            'hide_setup_fees' => __('admin/products.fields_hide_setup_fees'),
        ];
    }

    /**
     * Configure the validator instance.
     *
     * @param  \Illuminate\Validation\Validator  $validator
     * @return void
     */
    public function withValidator($validator)
    {
        $validator->after(function ($validator) {
            // PRC-492 — Create formunda pricing alanı yok; ürün shell olarak
            // oluşur, pricing edit/Pricing tab'ında girilir. Create-time'da
            // (route'ta product yok) pricing zorunluluğu atlanır; edit'te
            // korunur.
            $isCreate = ! $this->route('product');

            if (! $isCreate) {
                if ($this->payment_type === 'onetime') {
                    $this->validateOnetimePricing($validator);
                } elseif ($this->payment_type === 'recurring') {
                    $this->validateRecurringPricing($validator);
                    // PRC-810 — term-adaptive ON iken en az bir currency'de aktif monthly zorunlu
                    if ($this->boolean('adaptive_term_pricing')) {
                        $hasMonthly = collect($this->pricing ?? [])->contains(function ($periods) {
                            $m = is_array($periods) ? ($periods[1] ?? null) : null;

                            return is_array($m) && ! empty($m['active'])
                                && isset($m['amount']) && is_numeric($m['amount']) && (float) $m['amount'] > 0;
                        });
                        if (! $hasMonthly) {
                            $validator->errors()->add('adaptive_term_pricing', __('admin/products.validation_term_monthly_required'));
                        }
                    }
                }
            }
            // Free payment type için pricing kontrolü yok

            // Module config validation - sadece modül seçiliyse ve ya ilgili sekmedeyse ya da veri gönderildiyse
            if ($this->module && ($this->has('module_config') || $this->active_tab === 'module-settings')) {
                $this->validateModuleConfiguration($validator);
            }
        });
    }

    /**
     * Onetime pricing validasyonu
     */
    private function validateOnetimePricing($validator): void
    {
        if (! $this->has('onetime_pricing') || ! is_array($this->onetime_pricing)) {
            $validator->errors()->add('onetime_pricing', __('admin/products.validation.onetime_pricing_required'));

            return;
        }

        $hasActivePrice = false;

        foreach ($this->onetime_pricing as $currencyId => $priceData) {
            if (is_array($priceData) &&
                isset($priceData['active']) &&
                $priceData['active'] &&
                isset($priceData['amount']) &&
                $priceData['amount'] !== null &&
                $priceData['amount'] !== '') {
                $hasActivePrice = true;
                break;
            }
        }

        if (! $hasActivePrice) {
            $validator->errors()->add('onetime_pricing', __('admin/products.validation.onetime_pricing_at_least_one_active'));
        }
    }

    /**
     * Recurring pricing validasyonu
     */
    private function validateRecurringPricing($validator): void
    {
        if (! $this->has('pricing') || ! is_array($this->pricing)) {
            $validator->errors()->add('pricing', __('admin/products.validation_recurring_pricing_required'));

            return;
        }

        $hasActivePeriod = false;

        foreach ($this->pricing as $currencyId => $periods) {
            if (! is_array($periods)) {
                continue;
            }

            foreach ($periods as $period => $priceData) {
                if (is_array($priceData) &&
                    isset($priceData['active']) &&
                    $priceData['active'] &&
                    isset($priceData['amount']) &&
                    $priceData['amount'] !== null &&
                    $priceData['amount'] !== '') {
                    $hasActivePeriod = true;
                    break 2; // İç ve dış döngüden çık
                }
            }
        }

        if (! $hasActivePeriod) {
            $validator->errors()->add('pricing', __('admin/products.validation.recurring_pricing_at_least_one_active'));
        }
    }

    /**
     * Module configuration validation
     */
    private function validateModuleConfiguration($validator): void
    {
        // Modül seçili değilse validation yapmayız
        if (! $this->module) {
            return;
        }

        try {
            // ProductController'daki getModuleFields metodunu kullanarak modül field'larını al
            $controller = app(\App\Http\Controllers\Admin\ProductController::class);
            $moduleFieldsResponse = $controller->getModuleFields(request()->merge(['module' => $this->module]));
            $moduleFieldsData = $moduleFieldsResponse->getData(true);

            if (! $moduleFieldsData['success'] || ! isset($moduleFieldsData['fields'])) {
                return; // Modül field'ları alınamazsa validation yapmayız
            }

            $moduleFields = $moduleFieldsData['fields'];
            $moduleConfig = $this->module_config ?? [];

            // Her required field için kontrol yap
            foreach ($moduleFields as $fieldKey => $fieldData) {
                if (isset($fieldData['required']) && $fieldData['required']) {
                    $fieldValue = $moduleConfig[$fieldKey] ?? null;

                    // Required alan boş ise hata ekle
                    if (empty($fieldValue) && $fieldValue !== '0' && $fieldValue !== 0) {
                        $fieldName = $fieldData['name'] ?? $fieldKey;
                        $validator->errors()->add(
                            "module_config.{$fieldKey}",
                            __('admin/products.validation_module_config_required', ['field' => $fieldName])
                        );
                    }
                }
            }
        } catch (\Exception $e) {
            // Hata durumunda log'a yaz ama validation'ı devam ettir
            \Log::error('Module configuration validation error: '.$e->getMessage());
        }
    }
}
