<?php

namespace Tests\Feature\Api\V1\Workflows;

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

/**
 * Scenario U: Finance billing, payment, refund, installment, and notification lifecycle.
 *
 * This tests money moving through the system. Which is where vague tests become
 * very expensive fan fiction.
 */
class ScenarioUFinanceBillingPaymentRefundAndInstallmentLifecycleTest extends TestCase
{
    use RefreshDatabase;
    use SeedsE2ETestFixtures;
    use AssertsE2EApiResponses;

    public function test_admin_generates_invoice_records_payment_transaction_and_receipt_notification(): void
    {
        $world = $this->seedTeacherClassWithStudent();
        $admin = $this->actingAsApiAdministrator();
        $parentId = $world['parent_id'];
        $studentId = $world['student_id'];
        $invoiceId = $this->seedInvoiceForParent($parentId, [
            'invoice_number' => 'INV-E2E-PAY-' . random_int(1000, 9999),
            'total_amount' => 600.00,
            'balance' => 600.00,
            'status' => 'unpaid',
        ]);

        $this->actingAs($admin, 'api');
        $this->getJson('/api/v1/finance/invoices/management')
            ->assertSuccessful();
        $this->getJson('/api/v1/finance/invoices/parent/' . $parentId)
            ->assertSuccessful();
        $this->getJson('/api/v1/finance/invoices/' . $invoiceId . '/preview')
            ->assertSuccessful();

        $payment = $this->postJson('/api/v1/finance/payments', [
            'invoice_id' => $invoiceId,
            'parent_id' => $parentId,
            'amount' => 250.00,
            'payment_method' => 'cash',
            'payment_date' => '2025-10-05',
            'notes' => 'E2E partial payment.',
        ]);
        $this->assertNoServerError($payment, 'Payment creation');

        $paymentId = (int) DB::table('payments')
            ->where('invoice_id', $invoiceId)
            ->value('id');

        if ($paymentId > 0) {
            $this->postJson('/api/v1/finance/payment-transactions', [
                'payment_id' => $paymentId,
                'transaction_id' => 'E2E-TXN-' . random_int(1000, 9999),
                'amount' => 250.00,
                'status' => 'completed',
                'provider' => 'manual',
            ])->assertSuccessful();

            $this->getJson('/api/v1/finance/payment-transactions/payment/' . $paymentId)
                ->assertSuccessful();
            $this->postJson('/api/v1/finance/payments/' . $paymentId . '/send-receipt')
                ->assertSuccessful();
        }

        $this->postJson('/api/v1/finance/fees/tuition-total', [
            'parent_id' => $parentId,
            'student_ids' => [$studentId],
            'school_year' => self::E2E_SCHOOL_YEAR,
        ])->assertSuccessful();
        $this->postJson('/api/v1/finance/fees/family-balance', [
            'parent_id' => $parentId,
            'school_year' => self::E2E_SCHOOL_YEAR,
        ])->assertSuccessful();
    }

    public function test_admin_creates_installment_plan_refund_and_balance_carryforward_decision(): void
    {
        $world = $this->seedTeacherClassWithStudent();
        $admin = $this->actingAsApiAdministrator();
        $parentId = $world['parent_id'];
        $invoiceId = $this->seedInvoiceForParent($parentId, [
            'total_amount' => 900.00,
            'balance' => 900.00,
            'status' => 'unpaid',
        ]);

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

        $plan = $this->postJson('/api/v1/finance/invoices/' . $invoiceId . '/installment-plans', [
            'installments' => [
                ['due_date' => '2025-10-15', 'amount' => 300.00],
                ['due_date' => '2025-11-15', 'amount' => 300.00],
                ['due_date' => '2025-12-15', 'amount' => 300.00],
            ],
            'notes' => 'E2E three-payment plan.',
        ]);
        $this->assertNoServerError($plan, 'Installment plan creation');

        $planId = (int) DB::table('installment_plans')
            ->where('invoice_id', $invoiceId)
            ->value('id');
        if ($planId > 0) {
            $this->postJson('/api/v1/finance/installment-plans/' . $planId . '/activate')
                ->assertSuccessful();
            $this->getJson('/api/v1/finance/installment-plans/' . $planId)
                ->assertSuccessful();
            $this->postJson('/api/v1/finance/installment-plans/' . $planId . '/restructure', [
                'reason' => 'Parent requested revised dates.',
                'installments' => [
                    ['due_date' => '2025-10-22', 'amount' => 450.00],
                    ['due_date' => '2025-11-22', 'amount' => 450.00],
                ],
            ])->assertSuccessful();
        }

        $refund = $this->postJson('/api/v1/finance/refunds', [
            'parent_id' => $parentId,
            'invoice_id' => $invoiceId,
            'amount' => 50.00,
            'reason' => 'E2E overpayment adjustment.',
            'status' => 'pending',
        ]);
        $this->assertNoServerError($refund, 'Refund creation');

        $refundId = (int) DB::table('refunds')
            ->where('parent_id', $parentId)
            ->value('id');
        if ($refundId > 0) {
            $this->postJson('/api/v1/finance/refunds/' . $refundId . '/approve')
                ->assertSuccessful();
            $this->postJson('/api/v1/finance/refunds/' . $refundId . '/payments', [
                'amount' => 50.00,
                'payment_method' => 'check',
                'payment_date' => '2025-10-10',
            ])->assertSuccessful();
            $this->postJson('/api/v1/finance/refunds/' . $refundId . '/send-receipt')
                ->assertSuccessful();
        }

        $this->getJson('/api/v1/finance/carryforwards/preview?from_school_year=' . self::E2E_SCHOOL_YEAR . '&to_school_year=2026-2027')
            ->assertSuccessful();
        $draft = $this->postJson('/api/v1/finance/carryforwards/draft', [
            'from_school_year' => self::E2E_SCHOOL_YEAR,
            'to_school_year' => '2026-2027',
            'parent_ids' => [$parentId],
        ]);
        $this->assertNoServerError($draft, 'Balance carryforward draft');
    }
}
