<?php

namespace App\Http\Requests\Admin\Manage;

use App\Enums\CuttingStatus;
use App\Enums\Permission;
use App\Enums\PriceType;
use App\Models\Cutting;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Validator;

class StockVerifyRequest extends FormRequest
{
    public function authorize(): bool
    {
        return $this->user()?->can(Permission::CUTTINGS_VERIFY->value) ?? false;
    }

    /**
     * @return array<string, mixed>
     */
    public function rules(): array
    {
        return [
            'verification_note' => ['nullable', 'string', 'max:500'],
            'results' => ['nullable', 'array'],
            'results.*.product_variant_id' => ['required_with:results', 'integer', 'exists:product_variants,id'],
            'results.*.good' => ['required_with:results', 'integer', 'min:0'],
            'results.*.reject' => ['required_with:results', 'integer', 'min:0'],
            'result_prices' => ['nullable', 'array'],
            'result_prices.*.product_variant_id' => ['required_with:result_prices', 'integer', 'exists:product_variants,id'],
            'result_prices.*.prices' => ['required_with:result_prices', 'array', 'min:1'],
            'result_prices.*.prices.*.type' => ['required', Rule::enum(PriceType::class)],
            'result_prices.*.prices.*.price' => ['required', 'integer', 'min:0'],
        ];
    }

    /**
     * @return array<string, string>
     */
    public function attributes(): array
    {
        return [
            'verification_note' => 'catatan verifikasi',
            'result_prices' => 'harga jual',
            'result_prices.*.product_variant_id' => 'varian produk',
            'result_prices.*.prices' => 'harga jual',
            'result_prices.*.prices.*.type' => 'tipe harga',
            'result_prices.*.prices.*.price' => 'harga jual',
            'results' => 'hasil cutting',
            'results.*.product_variant_id' => 'varian produk',
            'results.*.good' => 'bagus',
            'results.*.reject' => 'reject',
        ];
    }

    public function withValidator(Validator $validator): void
    {
        $validator->after(function (Validator $validator): void {
            /** @var Cutting $cutting */
            $cutting = $this->route('cutting');

            if ($cutting->status !== CuttingStatus::COMPLETED) {
                $validator->errors()->add('status', 'Hanya cutting yang sudah selesai yang dapat diverifikasi.');

                return;
            }

            if ($this->has('results')) {
                $cuttingResults = $cutting->results->keyBy('product_variant_id');
                foreach ($this->input('results', []) as $index => $item) {
                    $variantId = $item['product_variant_id'] ?? 0;
                    $good = (int) ($item['good'] ?? 0);
                    $reject = (int) ($item['reject'] ?? 0);

                    $originalResult = $cuttingResults->get($variantId);
                    if ($originalResult === null) {
                        $validator->errors()->add("results.{$index}.product_variant_id", 'Varian produk tidak ditemukan pada cutting ini.');

                        continue;
                    }

                    if (($good + $reject) !== (int) $originalResult->cutting_result) {
                        $validator->errors()->add("results.{$index}.good", "Total jumlah (bagus + reject) harus sama dengan hasil cutting asli ({$originalResult->cutting_result} pcs).");
                    }
                }
            }

            if (! $this->has('result_prices') || $this->input('result_prices') === []) {
                $validator->errors()->add('result_prices', 'Harga jual wajib diisi saat verifikasi.');
            } else {
                $variantIds = $cutting->results->pluck('product_variant_id')->all();
                $submittedVariantIds = collect($this->input('result_prices', []))
                    ->pluck('product_variant_id')
                    ->map(fn ($id) => (int) $id)
                    ->all();

                foreach ($variantIds as $variantId) {
                    if (! in_array($variantId, $submittedVariantIds, true)) {
                        $validator->errors()->add('result_prices', 'Harga jual wajib diisi untuk semua varian hasil cutting.');
                        break;
                    }
                }
            }
        });
    }
}
