<?php

declare(strict_types=1);

namespace Maestro\Core\Modules\Offers\Http\Requests;

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Rule;
use Maestro\Core\Modules\Customers\Models\Contact;
use Maestro\Core\Modules\Offers\Enums\OfferDiscountType;
use Maestro\Core\Modules\Offers\Models\Offer;
use Maestro\Core\Modules\Offers\Support\OfferDocumentBackgroundCatalog;

class UpdateOfferRequest extends StoreOfferRequest
{
    /**
     * @return array<string, mixed>
     */
    public function rules(): array
    {
        return array_merge([
            'is_template' => ['sometimes', 'boolean'],
            'template_name' => ['nullable', 'string', 'max:255'],
            'subject' => ['sometimes', 'string', 'max:255'],
            'customer_id' => ['sometimes', 'nullable', 'exists:customers,id'],
            'contact_id' => ['sometimes', 'nullable', 'exists:contacts,id'],
            'intro_html' => ['sometimes', 'nullable', 'string'],
            'valid_until' => ['sometimes', 'nullable', 'date'],
            'discount_type' => ['sometimes', 'string', Rule::enum(OfferDiscountType::class)],
            'discount_value' => ['sometimes', 'numeric', 'min:0'],
            'document_background_url' => [
                'sometimes',
                'nullable',
                'string',
                'max:2048',
                function (string $attribute, mixed $value, \Closure $fail): void {
                    if ($value === null || $value === '') {
                        return;
                    }
                    if (! is_string($value) || ! OfferDocumentBackgroundCatalog::isAllowed($value)) {
                        $fail('The selected document background is not allowed.');
                    }
                },
            ],
            'sections' => ['sometimes', 'array'],
        ], parent::sectionRowRules());
    }

    public function withValidator(Validator $validator): void
    {
        parent::withValidator($validator);

        $validator->after(function (Validator $v): void {
            /** @var Offer|null $offer */
            $offer = $this->route('offer');

            $custSource = array_key_exists('customer_id', $this->all())
                ? $this->input('customer_id')
                : optional($offer)->customer_id;
            $contSource = array_key_exists('contact_id', $this->all())
                ? $this->input('contact_id')
                : optional($offer)->contact_id;
            if ($custSource === null || $contSource === null) {
                return;
            }
            $ok = Contact::query()
                ->whereKey((int) $contSource)
                ->where('customer_id', (int) $custSource)
                ->exists();
            if (! $ok) {
                $v->errors()->add('contact_id', 'Contact does not belong to the selected customer.');
            }
        });
    }
}
