<?php

namespace Database\Seeders\Demo;

use App\Models\Customers\Customer;
use App\Models\Lookups\Status;
use App\Models\Sales\Invoice;
use App\Services\CreditNoteService;
use App\Services\PaymentService;
use Database\Seeders\Demo\Concerns\GeneratesDemoData;
use Illuminate\Database\Seeder;
use RuntimeException;

/**
 * Manual credit notes beyond the ones auto-issued by returns/overpayments:
 * a couple left draft, several issued, one claimed against a real unpaid
 * invoice, and one voided.
 */
class CreditNoteSeeder extends Seeder
{
    use GeneratesDemoData;

    public function run(): void
    {
        $creditNotes = app(CreditNoteService::class);
        $customers = Customer::inRandomOrder()->limit(8)->get();

        if ($customers->count() < 8) {
            return;
        }

        // Draft — never issued.
        foreach ($customers->slice(0, 2) as $customer) {
            $cn = $creditNotes->createManualDraft($customer->id, fake()->randomFloat(2, 500, 3000), 'Pending manager approval.');
            $this->backdate($cn, $this->recentDate(2));
        }

        // Issued — funded into the customer credit pool, available to claim.
        foreach ($customers->slice(2, 4) as $customer) {
            $cn = $creditNotes->createManualDraft($customer->id, fake()->randomFloat(2, 300, 2500), 'Goodwill adjustment.');
            $creditNotes->issue($cn);
            $this->backdate($cn, $this->recentDate(2));
        }

        // Claimed — actually applied to a real unpaid invoice via a credit split.
        $claimCustomer = $customers[6];
        $claimCn = $creditNotes->createManualDraft($claimCustomer->id, 400, 'Compensation for delayed delivery.');
        $creditNotes->issue($claimCn);

        $unpaidId = Status::idOf(Status::CTX_INVOICE_PAYMENT, Status::UNPAID);
        $target = Invoice::where('customer_id', $claimCustomer->id)
            ->where('payment_status_id', $unpaidId)
            ->where('balance', '>=', 400)
            ->first();

        if ($target) {
            try {
                app(PaymentService::class)->settleInvoice($target, [[
                    'method' => 'credit', 'amount' => 400, 'credit_note_id' => $claimCn->id,
                ]]);
            } catch (RuntimeException) {
                // Leave it issued-but-unclaimed if settlement couldn't apply cleanly.
            }
        }
        $this->backdate($claimCn->fresh(), $this->recentDate(2));

        // Voided — created as a draft, then withdrawn.
        $voidCustomer = $customers[7];
        $voidCn = $creditNotes->createManualDraft($voidCustomer->id, 250, 'Issued in error.');
        $creditNotes->void($voidCn, 'Duplicate entry — amount already refunded via return.');
        $this->backdate($voidCn, $this->recentDate(2));
    }
}
