<?php

namespace App\Http\Requests\Syncing;

use App\Models\Batches;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;

class SyncTransactionsRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        return [
            // Root level - must be an array of transactions
            '*'                          => ['required', 'array'],

            // Per-transaction fields
            '*.synced_id'                => ['required', 'integer'],
            '*.synced_at'                => ['required', 'date_format:Y-m-d'],
            '*.synced_status'            => ['required', 'string', 'in:synced,pending,failed'],
            '*.loading_date'             => ['required', 'date_format:Y-m-d'],
            '*.farm_id'                  => ['required', 'integer', 'exists:farms,id'],
            '*.farm_name'                => ['required', 'string', 'max:255'],
            '*.building_id'              => ['required', 'integer', 'exists:buildings,id'],
            '*.building_name'            => ['required', 'string', 'max:255'],
            '*.batch_no'                 => ['required', 'string', 'max:100', "distinct"],
            '*.batch_sequence'           => ['required', 'integer', 'min:1'],
            '*.caretaker_id'             => ['required', 'integer', 'exists:users,id'],
            '*.lead_man_id'              => ['required', 'integer', 'exists:users,id'],

            // Totals
            '*.total_initial'            => ['required', 'integer', 'min:0'],
            '*.total_reject'             => ['required', 'integer', 'min:0'],
            '*.total_doa'                => ['required', 'integer', 'min:0'],
            '*.total_net'                => ['required', 'integer', 'min:0'],
            '*.sample_count'             => ['required', 'integer', 'min:0'],

            // Lines
            '*.lines'                    => ['required', 'array', 'min:1'],
            '*.lines.*.synced_id'        => ['required', 'integer'],
            '*.lines.*.breeder_id'       => ['required', 'integer', 'exists:breeders,id'],
            '*.lines.*.breeder_name'     => ['required', 'string', 'max:255'],
            '*.lines.*.class_id'         => ['required', 'integer', 'exists:classes,id'],
            '*.lines.*.class_name'       => ['required', 'string', 'max:255'],
            '*.lines.*.initial_population' => ['required', 'integer', 'min:0'],
            '*.lines.*.reject'           => ['required', 'integer', 'min:0'],
            '*.lines.*.doa'              => ['required', 'integer', 'min:0'],
            '*.lines.*.loaded_at'        => ['required', 'date_format:H:i'],
        ];
    }

    public function messages(): array
    {
        return [
            '*.synced_id.required'                      => 'Each transaction must have a synced_id.',
            '*.synced_id.integer'                       => 'synced_id must be an integer.',
            '*.synced_at.required'                      => 'synced_at is required.',
            '*.synced_at.date_format'                   => 'synced_at must be in Y-m-d format.',
            '*.loading_date.required'                   => 'loading_date is required.',
            '*.loading_date.date_format'                => 'loading_date must be in Y-m-d format.',
            '*.farm_id.required'                        => 'farm_id is required.',
            '*.farm_id.exists'                          => 'The specified farm does not exist.',
            '*.building_id.required'                    => 'building_id is required.',
            '*.building_id.exists'                      => 'The specified building does not exist.',
            '*.batch_no.required'                       => 'batch_no is required.',
            '*.batch_sequence.required'                 => 'batch_sequence is required.',
            '*.batch_sequence.integer'                  => 'batch_sequence must be an integer.',
            '*.caretaker_id.required'                   => 'caretaker_id is required.',
            '*.caretaker_id.exists'                     => 'The specified caretaker does not exist.',
            '*.lead_man_id.exists'                      => 'The specified lead man does not exist.',
            '*.total_initial.required'                  => 'total_initial is required.',
            '*.total_initial.min'                       => 'total_initial cannot be negative.',
            '*.total_reject.required'                   => 'total_reject is required.',
            '*.total_reject.min'                        => 'total_reject cannot be negative.',
            '*.total_doa.required'                      => 'total_doa is required.',
            '*.total_doa.min'                           => 'total_doa cannot be negative.',
            '*.total_net.required'                      => 'total_net is required.',
            '*.total_net.min'                           => 'total_net cannot be negative.',
            '*.sample_count.required'                   => 'sample_count is required.',
            '*.lines.required'                          => 'Each transaction must have at least one line.',
            '*.lines.*.synced_id.required'              => 'synced_id is required for each line.',
            '*.lines.*.synced_id.integer'               => 'synced_id must be an integer.',
            '*.lines.min'                               => 'Each transaction must have at least one line.',
            '*.lines.*.breeder_id.required'             => 'breeder_id is required for each line.',
            '*.lines.*.breeder_id.exists'               => 'The specified breeder does not exist.',
            '*.lines.*.class_id.required'               => 'class_id is required for each line.',
            '*.lines.*.class_id.exists'                 => 'The specified class does not exist.',
            '*.lines.*.initial_population.required'     => 'initial_population is required for each line.',
            '*.lines.*.initial_population.min'          => 'initial_population cannot be negative.',
            '*.lines.*.reject.required'                 => 'reject is required for each line.',
            '*.lines.*.reject.min'                      => 'reject cannot be negative.',
            '*.lines.*.doa.required'                    => 'doa is required for each line.',
            '*.lines.*.doa.min'                         => 'doa cannot be negative.',
            '*.lines.*.loaded_at.required'              => 'loaded_at is required for each line.',
            '*.lines.*.loaded_at.date_format'           => 'loaded_at must be in H:i format (e.g. 08:30).',
        ];
    }

    public function withValidator(Validator $validator): void
    {
        $validator->after(function ($validator) {
            foreach ($this->all() as $index => $transaction) {
                $farmId     = $transaction['farm_id'] ?? null;
                $buildingId = $transaction['building_id'] ?? null;
                $syncedId   = $transaction['synced_id'] ?? null;

                $exists = Batches::where('building_id', $buildingId)
                    ->where('farm_id', $farmId)
                    ->where('status', 'active')
                    ->where('synced_id', '!=', $syncedId)
                    ->exists();

                if ($exists) {
                    $validator->errors()->add(
                        "{$index}.building_id",
                        "Building '{$transaction['building_name']}' already has an active batch on farm '{$transaction['farm_name']}'."
                    );
                }
            }
        });
    }
}
