<?php

namespace App\Livewire\Inventory;

use App\Domain\Inventory\Models\Kit;
use App\Domain\Inventory\Models\Product;
use App\Domain\Inventory\Services\KitService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Shared\Traits\UsesBranchScope;
use Illuminate\Validation\Rule;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('الأطقم')]
class KitForm extends Component
{
    use UsesBranchScope;

    public ?Kit $kit = null;
    public bool $editing = false;

    public string $name_ar = '';
    public string $name = '';
    public string $sku = '';
    public string $selling_price = '';
    public string $description_ar = '';
    public string $assembly_instructions = '';
    public bool $is_active = true;

    /** @var array<int, array{product_id: string, quantity: string}> */
    public array $components = [];

    public function mount(?Kit $kit = null): void
    {
        $this->authorize('inventory.manage');

        if ($kit && $kit->exists) {
            $this->kit = $kit;
            $this->editing = true;

            $this->name_ar = $kit->name_ar ?? '';
            $this->name = $kit->name ?? '';
            $this->sku = $kit->sku ?? '';
            $this->selling_price = $kit->selling_price ? (string) ($kit->selling_price / 100) : '';
            $this->description_ar = $kit->description_ar ?? '';
            $this->assembly_instructions = $kit->assembly_instructions ?? '';
            $this->is_active = $kit->is_active;

            $kit->load('components');
            foreach ($kit->components as $component) {
                $this->components[] = [
                    'product_id' => (string) $component->product_id,
                    'quantity' => (string) $component->quantity,
                ];
            }
        }

        // Always have at least one empty row
        if (empty($this->components)) {
            $this->components[] = ['product_id' => '', 'quantity' => '1'];
        }
    }

    public function addComponent(): void
    {
        $this->components[] = ['product_id' => '', 'quantity' => '1'];
    }

    public function removeComponent(int $index): void
    {
        unset($this->components[$index]);
        $this->components = array_values($this->components);

        // Keep at least one row
        if (empty($this->components)) {
            $this->components[] = ['product_id' => '', 'quantity' => '1'];
        }
    }

    public function rules(): array
    {
        // unique:/exists: run raw table queries — they see neither the academy
        // scope nor the branch scope. kits.sku is unique(academy_id, sku), so
        // that rule is academy-scoped; the component products are this
        // branch's own, so theirs is branch-exact.
        $academyId = app('current_academy')->id;
        $branchId = $this->getActiveBranchId();

        $uniqueSku = Rule::unique('kits', 'sku')->where('academy_id', $academyId);

        if ($this->editing) {
            $uniqueSku = $uniqueSku->ignore($this->kit->id);
        }

        return [
            'name_ar' => 'required|string|max:255',
            'name' => 'nullable|string|max:255',
            'sku' => ['required', 'string', 'max:50', $uniqueSku],
            'selling_price' => 'required|numeric|min:0',
            'description_ar' => 'nullable|string|max:1000',
            'assembly_instructions' => 'nullable|string|max:2000',
            'is_active' => 'boolean',
            'components' => 'required|array|min:1',
            // $components is a plain public array: without this the browser could
            // build a kit out of another branch's exclusive product, and
            // assembling it would then consume that branch's stock.
            'components.*.product_id' => [
                'required',
                Rule::exists('products', 'id')
                    ->where('academy_id', $academyId)
                    ->whereNull('deleted_at')
                    ->when($branchId !== null, fn ($rule) => $rule->where(
                        fn ($q) => $q->where('branch_id', $branchId)
                    )),
            ],
            'components.*.quantity' => 'required|integer|min:1',
        ];
    }

    public function messages(): array
    {
        return [
            'name_ar.required' => 'اسم الطقم بالعربية مطلوب',
            'name_ar.max' => 'اسم الطقم يجب ألا يتجاوز 255 حرف',
            'sku.required' => 'رمز الطقم (SKU) مطلوب',
            'sku.unique' => 'رمز الطقم مستخدم بالفعل',
            'sku.max' => 'رمز الطقم يجب ألا يتجاوز 50 حرف',
            'selling_price.required' => 'سعر البيع مطلوب',
            'selling_price.numeric' => 'سعر البيع يجب أن يكون رقمًا',
            'selling_price.min' => 'سعر البيع يجب ألا يكون سالبًا',
            'components.required' => 'يجب إضافة مكون واحد على الأقل',
            'components.min' => 'يجب إضافة مكون واحد على الأقل',
            'components.*.product_id.required' => 'يجب اختيار المنتج',
            'components.*.product_id.exists' => 'المنتج غير موجود',
            'components.*.quantity.required' => 'الكمية مطلوبة',
            'components.*.quantity.integer' => 'الكمية يجب أن تكون عددًا صحيحًا',
            'components.*.quantity.min' => 'الكمية يجب أن تكون 1 على الأقل',
        ];
    }

    public function save(KitService $kitService): void
    {
        $this->validate();

        try {
            $data = [
                'academy_id' => app('current_academy')->id,
                'name_ar' => $this->name_ar,
                'name' => $this->name ?: null,
                'sku' => $this->sku,
                'selling_price' => (int) round((float) $this->selling_price * 100),
                'description_ar' => $this->description_ar ?: null,
                'assembly_instructions' => $this->assembly_instructions ?: null,
                'is_active' => $this->is_active,
            ];

            $componentData = collect($this->components)
                ->filter(fn ($c) => !empty($c['product_id']))
                ->map(fn ($c, $i) => [
                    'product_id' => (int) $c['product_id'],
                    'quantity' => (int) $c['quantity'],
                    'sort_order' => $i,
                ])
                ->values()
                ->all();

            if ($this->editing) {
                $kitService->update($this->kit, $data, $componentData);
                session()->flash('success', __('تم تحديث الطقم بنجاح'));
            } else {
                $kitService->create($data, $componentData, auth()->user());
                session()->flash('success', __('تم إنشاء الطقم بنجاح'));
            }

            $this->redirect(route('inventory.kits'), navigate: true);
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function render()
    {
        $branchId = $this->getActiveBranchId();
        return view('livewire.inventory.kit-form', [
            'products' => Product::where('is_active', true)
                ->when($branchId, fn ($q) => $q->where(fn ($b) => $b->whereNull('branch_id')->orWhere('branch_id', $branchId)))
                ->orderBy('name_ar')
                ->get(['id', 'name_ar', 'name', 'sku']),
        ]);
    }
}
