<?php

namespace Tests\Feature;

use App\Models\CashDrawerTransaction;
use App\Models\Product;
use App\Models\StockLevel;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ReturnApiTest extends TestCase
{
    use RefreshDatabase;

    public function test_return_processing_restocks_inventory_and_marks_order_as_partially_refunded(): void
    {
        ['company' => $company, 'user' => $user, 'branch' => $branch] = $this->createUserWithPermissions([
            'shifts.manage',
            'orders.manage',
            'payments.manage',
            'returns.manage',
            'returns.view',
        ]);

        $paymentMethod = $this->createPaymentMethod($company);
        $product = Product::factory()->create([
            'company_id' => $company->id,
            'name' => 'Rice 1kg',
            'sku' => 'RICE1KG',
            'cost_price' => 90,
            'selling_price' => 140,
        ]);

        StockLevel::create([
            'branch_id' => $branch->id,
            'product_id' => $product->id,
            'quantity' => 10,
            'reserved_quantity' => 0,
        ]);

        $this->actingAsApi($user, $branch->id)
            ->postJson('/api/v1/shifts/open', [
                'opening_float' => 300,
            ])
            ->assertCreated();

        $order = $this->actingAsApi($user, $branch->id)
            ->postJson('/api/v1/orders', [
                'items' => [
                    [
                        'product_id' => $product->id,
                        'quantity' => 3,
                    ],
                ],
                'payments' => [
                    [
                        'payment_method_id' => $paymentMethod->id,
                        'amount' => 420,
                    ],
                ],
            ])
            ->assertCreated();

        $orderId = $order->json('data.id');
        $orderItemId = $order->json('data.items.0.id');

        $response = $this->actingAsApi($user, $branch->id)
            ->postJson('/api/v1/returns', [
                'original_order_id' => $orderId,
                'reason' => 'wrong_item',
                'refund_method' => 'cash',
                'restocked' => true,
                'items' => [
                    [
                        'order_item_id' => $orderItemId,
                        'quantity' => 1,
                        'condition' => 'resellable',
                    ],
                ],
            ]);

        $response->assertCreated()
            ->assertJsonPath('data.original_order_id', $orderId)
            ->assertJsonPath('data.status', 'completed')
            ->assertJsonPath('data.items.0.quantity', '1.0000');

        $stock = StockLevel::query()
            ->where('branch_id', $branch->id)
            ->where('product_id', $product->id)
            ->firstOrFail();

        $this->assertSame('8.0000', $stock->quantity);

        $this->assertDatabaseHas('orders', [
            'id' => $orderId,
            'status' => 'partially_refunded',
        ]);

        $this->assertDatabaseHas('order_items', [
            'id' => $orderItemId,
            'returned_quantity' => 1,
        ]);

        $this->assertDatabaseHas('returns', [
            'original_order_id' => $orderId,
            'refund_method' => 'cash',
        ]);

        $refundDrawerEntry = CashDrawerTransaction::query()
            ->where('type', 'refund')
            ->latest('id')
            ->first();

        $this->assertNotNull($refundDrawerEntry);
        $this->assertSame('-140.00', $refundDrawerEntry->amount);

        $listing = $this->actingAsApi($user, $branch->id)
            ->getJson('/api/v1/returns');

        $listing->assertOk()
            ->assertJsonPath('data.0.original_order_id', $orderId);
    }
}
