<?php

namespace App\Http\Requests\Purchase;

use App\Http\Requests\BaseFormRequest;
use Illuminate\Contracts\Validation\Validator;

class StorePurchaseInvoiceRequest extends BaseFormRequest
{
    public function rules(): array
    {
        return [
            'purchase_order_id' => 'nullable|integer',
            'purchase_order_date' => 'nullable|date',
            'purchase_no' => 'required|string|max:100',
            'vendor_email' => 'nullable|email|max:255',
            'invoice_no' => 'required|string|max:100|unique:purchases,purchase_no',
            'invoice_date' => 'required|date|before_or_equal:today',
            'purchase_id' => 'required|integer|exists:customer_vendors,id',
            'vendor_reference_no' => 'nullable|string|max:100',
            'payment_terms' => 'nullable|integer|min:0|max:365',
            'company_gstn' => 'required|string|max:20',
            'company_address' => 'required|string|max:500',
            'company_phone' => 'required|string|max:20',
            'description' => 'nullable|string|max:2000',
            'delivery_terms' => 'nullable|string|max:500',
            'items' => 'required|array|min:1',
            'items.*.sl_no' => 'required|integer|min:1',
            'items.*.item_id' => 'required|integer|exists:stock_items,id',
            'items.*.description' => 'nullable|string|max:500',
            'items.*.quantity' => 'required|numeric|min:0.01',
            'items.*.uom' => 'required|string|max:20',
            'items.*.rate' => 'required|numeric|min:0',
            'items.*.tds' => 'nullable|numeric|min:0|max:100',
            'items.*.discount' => 'nullable|numeric|min:0|max:100',
            'items.*.value' => 'nullable|numeric|min:0',
            'items.*.sgst' => 'nullable|numeric|min:0|max:50',
            'items.*.cgst' => 'nullable|numeric|min:0|max:50',
            'items.*.igst' => 'nullable|numeric|min:0|max:50',
            'items.*.amount' => 'nullable|numeric|min:0',
            'additional_charges' => 'nullable|numeric|min:0',
            'total_tds' => 'nullable|numeric|min:0',
            'sub_total' => 'required|numeric|min:0',
            'total_amount' => 'required|numeric|min:0',
            'paid_amount' => 'nullable|numeric|min:0',
            'balance_amount' => 'nullable|numeric|min:0',
            'payment_mode' => 'nullable|string|max:50',
            'payment_reference' => 'nullable|string|max:100',
            'payment_reason' => 'nullable|string|max:500',
            'note' => 'nullable|string|max:2000',
        ];
    }

    /**
     * Configure the validator instance.
     */
    public function withValidator(Validator $validator): void
    {
        $validator->after(function (Validator $validator) {
            $this->validateGstRules($validator);
            $this->validatePaymentAmount($validator);
        });
    }

    /**
     * Validate GST rules (IGST mutually exclusive with CGST/SGST)
     */
    protected function validateGstRules(Validator $validator): void
    {
        $items = $this->input('items', []);

        foreach ($items as $index => $item) {
            $sgst = floatval($item['sgst'] ?? 0);
            $cgst = floatval($item['cgst'] ?? 0);
            $igst = floatval($item['igst'] ?? 0);

            // IGST and CGST+SGST are mutually exclusive
            if ($igst > 0 && ($cgst > 0 || $sgst > 0)) {
                $validator->errors()->add(
                    "items.{$index}.igst",
                    "Item #" . ($index + 1) . ": IGST cannot be applied together with CGST/SGST."
                );
            }

            // CGST and SGST must be equal
            if (($cgst > 0 || $sgst > 0) && abs($cgst - $sgst) > 0.01) {
                $validator->errors()->add(
                    "items.{$index}.cgst",
                    "Item #" . ($index + 1) . ": CGST and SGST rates must be equal."
                );
            }

            // Validate GST rates (common rates: 0, 5, 12, 18, 28)
            $validGstRates = [0, 5, 12, 18, 28];
            if ($igst > 0 && !in_array($igst, $validGstRates)) {
                $validator->errors()->add(
                    "items.{$index}.igst",
                    "Item #" . ($index + 1) . ": IGST rate must be one of: 0%, 5%, 12%, 18%, or 28%."
                );
            }
            if (($cgst > 0 || $sgst > 0) && !in_array($cgst, array_map(fn($r) => $r/2, $validGstRates))) {
                // CGST/SGST is half of total GST
                $totalGst = $cgst + $sgst;
                if (!in_array($totalGst, $validGstRates)) {
                    $validator->errors()->add(
                        "items.{$index}.cgst",
                        "Item #" . ($index + 1) . ": Combined GST rate (CGST+SGST) must be one of: 0%, 5%, 12%, 18%, or 28%."
                    );
                }
            }
        }
    }

    /**
     * Validate payment amount doesn't exceed total
     */
    protected function validatePaymentAmount(Validator $validator): void
    {
        $totalAmount = floatval($this->input('total_amount', 0));
        $paidAmount = floatval($this->input('paid_amount', 0));

        if ($paidAmount > $totalAmount) {
            $validator->errors()->add(
                'paid_amount',
                'Paid amount cannot exceed the total invoice amount.'
            );
        }
    }

    public function attributes(): array
    {
        return [
            'purchase_id' => 'Vendor',
            'invoice_no' => 'Purchase Invoice Number',
            'invoice_date' => 'Invoice Date',
            'company_gstn' => 'GSTIN',
            'items.*.item_id' => 'Item',
            'items.*.quantity' => 'Quantity',
            'items.*.rate' => 'Rate',
            'items.*.uom' => 'Unit of Measure',
        ];
    }

    public function messages(): array
    {
        return [
            'invoice_date.before_or_equal' => 'Invoice date cannot be in the future.',
            'items.required' => 'At least one item is required.',
            'items.min' => 'At least one item is required.',
            'purchase_id.exists' => 'The selected vendor does not exist.',
        ];
    }
}
