<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;

class ServicePackageRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        $rules = [
            'client_id'                => ['sometimes', 'integer', 'exists:clients,id'],
            'provider_id'              => ['sometimes', 'integer', 'exists:providers,id'],
            'address_id'               => ['sometimes', 'integer', 'exists:addresses,id'],
            'date'                     => ['nullable', 'date', 'after_or_equal:today'],
            'dates'                    => ['nullable', 'array'],
            'dates.*'                  => ['date', 'after_or_equal:today'],
            'schedules'                => ['nullable', 'array'],
            'schedules.*.provider_id'  => ['sometimes', 'integer', 'exists:providers,id'],
            'schedules.*.date'         => ['required', 'date', 'after_or_equal:today'],
            'schedules.*.period_type'  => ['required', 'in:2,4,6,8'],
            'schedules.*.start_time'   => ['required', 'date_format:H:i'],
            'schedules.*.end_time'     => ['required', 'date_format:H:i', 'after:schedules.*.start_time'],
            'schedules.*.total_amount' => ['required', 'numeric', 'min:0'],
            'schedules.*.offers_meal'  => ['nullable', 'boolean'],
            'offers_meal'              => ['sometimes', 'nullable', 'boolean'],
            'period_type'              => ['sometimes', 'in:2,4,6,8'],
            'start_time'               => ['sometimes', 'date_format:H:i'],
            'end_time'                 => ['sometimes', 'date_format:H:i', 'after:start_time'],
            'total_amount'             => ['sometimes', 'numeric', 'min:0'],
            'schedule_type'            => ['sometimes', 'in:default,custom'],
        ];

        if ($this->isMethod('POST')) {
            $rules['client_id'] = ['required', 'integer', 'exists:clients,id'];

            if ($this->hasSchedulePayload()) {
                $rules['provider_id']              = ['required_without:schedules', 'integer', 'exists:providers,id'];
                $rules['address_id']               = ['required', 'integer', 'exists:addresses,id'];
                $rules['date']                     = ['required_without_all:dates,schedules', 'nullable', 'date', 'after_or_equal:today'];
                $rules['dates']                    = ['nullable', 'array'];
                $rules['dates.*']                  = ['date', 'after_or_equal:today'];
                $rules['schedules']                = ['nullable', 'array', 'min:1'];
                $rules['schedules.*.provider_id']  = ['required_without:provider_id', 'integer', 'exists:providers,id'];
                $rules['schedules.*.date']         = ['required', 'date', 'after_or_equal:today'];
                $rules['schedules.*.period_type']  = ['required', 'in:2,4,6,8'];
                $rules['schedules.*.start_time']   = ['required', 'date_format:H:i'];
                $rules['schedules.*.end_time']     = ['required', 'date_format:H:i', 'after:schedules.*.start_time'];
                $rules['schedules.*.total_amount'] = ['required', 'numeric', 'min:0'];
                $rules['period_type']              = ['required_without:schedules', 'in:2,4,6,8'];
                $rules['start_time']               = ['required_without:schedules', 'date_format:H:i'];
                $rules['end_time']                 = ['required_without:schedules', 'date_format:H:i', 'after:start_time'];
                $rules['total_amount']             = ['required_without:schedules', 'numeric', 'min:0'];
            }
        }

        return $rules;
    }

    public function after(): array
    {
        return [function (Validator $validator): void {
            if (! $this->hasSchedulePayload()) {
                return;
            }

            $rootProviderId = $this->integer('provider_id') ?: null;

            $providerIds = collect($this->input('schedules', []))
                ->map(fn (array $schedule) => data_get($schedule, 'provider_id', $rootProviderId))
                ->when(
                    ! $this->filled('schedules') && $rootProviderId,
                    fn ($ids) => $ids->push($rootProviderId),
                )
                ->filter()
                ->unique()
                ->values();

            if ($providerIds->count() > 1) {
                $validator->errors()->add(
                    'schedules',
                    __('messages.service_package_same_provider'),
                );
            }
        }];
    }

    private function hasSchedulePayload(): bool
    {
        return $this->filled('date')
            || $this->filled('dates')
            || $this->filled('schedules');
    }

    /**
    * Add custom messages when needed
    * public function messages(): array
    * {
    *   return [
    *        'field.required' => __('message.algo'),
    *    ];
    * }
    */
}
