<?php

namespace App\Http\Requests;

use App\Models\LaundrySaleProduct;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class UpdateLaundrySaleProductRequest extends FormRequest
{
    public function authorize(): bool
    {
        $p = $this->route('laundrySaleProduct');

        return $p && $this->user()?->can('update', $p);
    }

    /**
     * @return array<string, mixed>
     */
    public function rules(): array
    {
        $id = $this->route('laundrySaleProduct')?->id;

        return [
            'laundry_sale_category_id' => ['sometimes', 'required', 'integer', 'exists:laundry_sale_categories,id'],
            'code' => ['sometimes', 'required', 'string', 'max:64', Rule::unique('laundry_sale_products', 'code')->ignore($id)],
            'name' => ['sometimes', 'required', 'string', 'max:255'],
            'tipo' => ['sometimes', 'required', 'string', Rule::in([LaundrySaleProduct::TIPO_SERVICIO, LaundrySaleProduct::TIPO_PRODUCTO])],
            'description' => ['nullable', 'string'],
            'default_etapa_id' => ['nullable', 'integer', 'exists:etapas,id'],
            'default_load_type_id' => ['nullable', 'integer', 'exists:load_types,id'],
            'default_tipo_servicio_id' => ['nullable', 'integer', 'exists:tipos_servicio,id'],
            'billing_unit' => ['sometimes', 'required', 'string', Rule::in([LaundrySaleProduct::BILLING_UNIT_PIECE, LaundrySaleProduct::BILLING_UNIT_KG])],
            'unit_price' => ['sometimes', 'required', 'numeric', 'min:0'],
            'extra_cost' => ['nullable', 'numeric', 'min:0'],
            'sort_order' => ['nullable', 'integer', 'min:0'],
            'is_active' => ['sometimes', 'boolean'],
            'inventory_product_id' => ['nullable', 'integer', 'exists:inventory_products,id'],
            'tracks_stock' => ['sometimes', 'boolean'],
            'stock_quantity' => ['nullable', 'integer', 'min:0', Rule::requiredIf(fn () => $this->boolean('tracks_stock'))],
            'service_prices' => ['sometimes', 'nullable', 'array'],
            'service_prices.*.etapa_id' => ['required', 'integer', 'exists:etapas,id'],
            'service_prices.*.amount' => ['required', 'numeric', 'min:0'],
        ];
    }

    public function withValidator($validator): void
    {
        $validator->after(function (\Illuminate\Validation\Validator $validator): void {
            $product = $this->route('laundrySaleProduct');
            $tipo = (string) $this->input('tipo', $product?->tipo ?? LaundrySaleProduct::TIPO_SERVICIO);
            if ($tipo === LaundrySaleProduct::TIPO_SERVICIO && $this->boolean('tracks_stock')) {
                $validator->errors()->add('tracks_stock', 'Solo los artículos tipo «producto» pueden controlar existencias.');
            }
            if ($this->boolean('tracks_stock')) {
                $unit = $this->input('billing_unit', $product?->billing_unit);
                if ($unit !== LaundrySaleProduct::BILLING_UNIT_PIECE) {
                    $validator->errors()->add('tracks_stock', 'El inventario por piezas solo aplica con unidad de cobro «por pieza».');
                }
            }

            $rows = $this->input('service_prices');
            if (! is_array($rows)) {
                return;
            }
            $seen = [];
            foreach ($rows as $row) {
                $id = isset($row['etapa_id']) ? (int) $row['etapa_id'] : 0;
                if ($id <= 0) {
                    continue;
                }
                if (isset($seen[$id])) {
                    $validator->errors()->add('service_prices', 'El tipo de servicio está duplicado en precios por servicio.');

                    return;
                }
                $seen[$id] = true;
            }
        });
    }
}
