<?php

namespace Tests\Feature\Api\V1\Workflows;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Tests\Concerns\SeedsE2ETestFixtures;
use Tests\TestCase;

/**
 * Scenario O: Inventory, finance, and audit controls.
 *
 * This covers the unglamorous back office: materials are created, adjusted,
 * distributed, billed, paid, and then reported. Not glamorous. Still where money
 * leaks if tests are just decorative plants.
 */
class ScenarioOInventoryFinanceAndAuditControlsTest extends TestCase
{
    use RefreshDatabase;
    use SeedsE2ETestFixtures;

    public function test_admin_tracks_inventory_item_from_creation_to_adjustment_and_summary(): void
    {
        $this->seedE2EConfiguration();
        $admin = $this->actingAsApiAdministrator();
        $this->actingAs($admin, 'api');

        $categoryId = DB::table('inventory_categories')->insertGetId([
            'type' => 'classroom',
            'name' => 'E2E Classroom Supplies',
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        $this->postJson('/api/v1/inventory/items', [
            'type' => 'classroom',
            'category_id' => $categoryId,
            'name' => 'Dry erase markers',
            'quantity' => 12,
            'condition' => 'good',
            'semester' => self::E2E_SEMESTER,
            'school_year' => self::E2E_SCHOOL_YEAR,
        ])->assertCreated();

        $itemId = (int) DB::table('inventory_items')
            ->where('name', 'Dry erase markers')
            ->value('id');
        $this->assertGreaterThan(0, $itemId);

        $this->postJson('/api/v1/inventory/items/' . $itemId . '/adjust', [
            'mode' => 'out',
            'quantity' => 2,
            'reason' => 'Issued to teacher cart',
        ])->assertOk()->assertJsonPath('status', true);

        $this->postJson('/api/v1/inventory/items/' . $itemId . '/audit', [
            'needs_repair_qty' => 1,
            'need_replace_qty' => 0,
            'cannot_find_qty' => 0,
        ])->assertOk()->assertJsonPath('status', true);

        $this->assertDatabaseHas('inventory_movements', [
            'item_id' => $itemId,
            'movement_type' => 'out',
        ]);
        $this->assertDatabaseHas('inventory_items', [
            'id' => $itemId,
            'needs_repair_qty' => 1,
        ]);

        $this->getJson('/api/v1/inventory/summary/classroom')
            ->assertOk()
            ->assertJsonPath('status', true);
    }

    public function test_finance_followup_records_notes_promises_and_resolution_for_unpaid_parent(): void
    {
        $world = $this->seedTeacherClassWithStudent();
        $admin = $this->actingAsApiAdministrator();
        $parentId = $world['parent_id'];
        $invoiceId = $this->seedInvoiceForParent($parentId, [
            'balance' => 300.00,
            'paid_amount' => 200.00,
            'status' => 'partial',
        ]);

        $this->actingAs($admin, 'api');

        $this->getJson('/api/v1/finance/parent-payment-followups')
            ->assertOk()
            ->assertJsonPath('ok', true);

        $this->postJson('/api/v1/finance/parent-payment-followups/' . $parentId . '/note', [
            'note' => 'Left voicemail about remaining balance.',
            'invoice_id' => $invoiceId,
        ])->assertSuccessful();

        $this->postJson('/api/v1/finance/parent-payment-followups/' . $parentId . '/promise-to-pay', [
            'invoice_id' => $invoiceId,
            'amount' => 300.00,
            'promise_date' => '2025-10-20',
            'note' => 'Parent promised to pay next Sunday.',
        ])->assertSuccessful();

        $this->postJson('/api/v1/finance/parent-payment-followups/' . $parentId . '/mark-contacted', [
            'invoice_id' => $invoiceId,
            'contacted_at' => '2025-10-06 12:00:00',
        ])->assertSuccessful();

        $this->postJson('/api/v1/finance/parent-payment-followups/' . $parentId . '/resolve', [
            'invoice_id' => $invoiceId,
            'resolution_note' => 'Resolved after payment arrangement.',
        ])->assertSuccessful();
    }
}
