<?php

namespace App\Services;

use App\Http\Resources\MiscIssueResource;
use App\Models\InventoryMovement;
use App\Models\Item;
use App\Models\MiscIssue;
use App\Models\MiscIssueItem;
use Illuminate\Support\Facades\Auth;

class MiscIssueService
{
    protected $inventoryService;
    protected $auditTrail;
    protected DocumentNumberService $documentNumberService;

    public function __construct(
        InventoryService $inventoryService,
        AuditTrailService $auditTrail,
        DocumentNumberService $documentNumberService
    ) {
        $this->inventoryService = $inventoryService;
        $this->auditTrail = $auditTrail;
        $this->documentNumberService = $documentNumberService;
    }

    public function getAll()
    {
        $farmId = Auth::user()->farm_id;
        $userId = Auth::id();

        $miscIssue = MiscIssue::with('miscIssueItem.item')
            ->where('farm_id', $farmId)
            ->where('user_id', $userId)
            ->useFilters()
            ->dynamicPaginate();

        return $miscIssue;
    }

    public function getById(int $id)
    {
        $miscIssue = MiscIssue::with('miscIssueItem.item')->find($id);

        if (!$miscIssue) {
            return null;
        }

        return new MiscIssueResource($miscIssue);
    }

    public function create(array $data)
    {
        $farmId = Auth::user()->farm_id;

        $documentNo = $this->documentNumberService->generate(
            prefix: 'MSI',
            table: 'misc_issues',
        );

        $issue = MiscIssue::create([
            'document_no' => $documentNo,
            'farm_id' => $farmId,
            'transaction_date' => $data['transaction_date'],
            'transaction_type' => $data['transaction_type'],
            'remarks' => $data['remarks'] ?? null,
            'user_id' => Auth::id(),
        ]);

        foreach ($data['items'] as $row) {

            $item = Item::findOrFail($row['item_id']);

            // 🔥 STOCK VALIDATION
            // if ($item->soh < $row['quantity']) {
            //     throw new Exception("Insufficient stock for {$item->name}");
            // }

            MiscIssueItem::create([
                'misc_issue_id' => $issue->id,
                'item_id' => $item->id,
                'quantity' => $row['quantity'],
                'item_code_snapshot' => $item->code,
                'item_name_snapshot' => $item->name,
            ]);

            // 🔥 STOCK OUT (warehouse)
            $this->inventoryService->outMiscIssue([
                'farm_id'      => $farmId,
                'item_id'      => $item->id,
                'quantity'     => $row['quantity'],
                'reference_id' => $issue->id,
                'remarks'      => $data['remarks'] ?? null,
                'user_id'      => Auth::id(),
            ]);
        }

        $this->auditTrail->log(
            __("models.transaction"),
            __("models.misc_issue"),
            $issue->id,
            __("models.lc_created"),
            $issue,
            null,
            $data
        );

        return new MiscIssueResource(
            $issue->load('miscIssueItem.item')
        );
    }

    public function update(array $data, int $id)
    {
        $farmId = Auth::user()->farm_id;

        $issue = MiscIssue::findOrFail($id);

        $issue->update([
            'transaction_date' => $data['transaction_date'],
            'transaction_type' => $data['transaction_type'],
            'remarks'          => $data['remarks'] ?? null,
        ]);

        $submittedItemIds = collect($data['items'])->pluck('item_id')->toArray();

        // Remove items not in the request and reverse their inventory movement
        $issue->miscIssueItem()
            ->whereNotIn('item_id', $submittedItemIds)
            ->each(function ($miscIssueItem) use ($farmId) {
                // Reverse the OUT movement for this item
                InventoryMovement::where('reference_type', 'misc_issue')
                    ->where('reference_id', $miscIssueItem->misc_issue_id)
                    ->where('item_id', $miscIssueItem->item_id)
                    ->where('farm_id', $farmId)
                    ->delete();

                $this->inventoryService->syncItemSOH($miscIssueItem->item_id);

                $miscIssueItem->delete();
            });

        foreach ($data['items'] as $row) {

            $item = Item::findOrFail($row['item_id']);

            // Get existing before updateOrCreate
            $existing = MiscIssueItem::where('misc_issue_id', $issue->id)
                ->where('item_id', $item->id)
                ->first();

            MiscIssueItem::updateOrCreate(
                [
                    'misc_issue_id' => $issue->id,
                    'item_id'       => $item->id,
                ],
                [
                    'quantity'           => $row['quantity'],
                    'item_code_snapshot' => $item->code,
                    'item_name_snapshot' => $item->name,
                ]
            );

            if ($existing) {
                // Item already existed — update the inventory movement
                $this->inventoryService->outMiscIssueUpdate([
                    'farm_id'      => $farmId,
                    'item_id'      => $item->id,
                    'quantity'     => $row['quantity'],
                    'reference_id' => $issue->id,
                    'remarks'      => $data['remarks'] ?? null,
                ]);
            } else {
                // Newly added item — create a new OUT movement
                $this->inventoryService->outMiscIssue([
                    'farm_id'      => $farmId,
                    'item_id'      => $item->id,
                    'quantity'     => $row['quantity'],
                    'reference_id' => $issue->id,
                    'remarks'      => $data['remarks'] ?? null,
                    'user_id'      => Auth::id(),
                ]);
            }
        }

        $this->auditTrail->log(
            __("models.transaction"),
            __("models.misc_issue"),
            $issue->id,
            __("models.lc_updated"),
            $issue,
            null,
            $data
        );

        return new MiscIssueResource(
            $issue->load('miscIssueItem.item')
        );
    }

    public function toggleArchive(int $id) {}
}
