<?php

namespace Tests\Feature;

use App\Console\Commands\GenerateInvoices;
use App\Mail\InvoiceNotification;
use App\Tier;
use Carbon\Carbon;
use Database\Seeders\Global\PrimaryBillableSeed;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Mail;
use Mtc\MercuryDataModels\Billable;
use Mtc\MercuryDataModels\Invoice;
use Mtc\MercuryDataModels\Tenant;
use Mtc\MercuryDataModels\TenantBillable;
use Mtc\MercuryDataModels\TenantBillingDetail;
use Tests\TestCase;

class GenerateInvoicesTest extends TestCase
{
    use RefreshDatabase;

    protected bool $tenancy_make_databases = false;

    public function testNoInvoicesToGenerate()
    {
        Mail::fake();
        $this->artisan(GenerateInvoices::class);

        Mail::assertNothingSent();
        $this->assertEquals(0, Invoice::query()->count());
    }

    public function testSingleInvoiceGeneration()
    {
        $this->seed(PrimaryBillableSeed::class);
        $tenant = Tenant::factory()->create([
            'next_invoice_due_at' => Carbon::now()->startOfDay()
        ]);

        TenantBillingDetail::factory()->create([
            'tenant_id' => $tenant->id,
        ]);

        TenantBillable::factory()->create([
            'tenant_id' => $tenant->id,
            'billable_id' => Billable::query()->inRandomOrder()->first()->id,
        ]);


        Mail::fake();
        $this->artisan(GenerateInvoices::class);

        Mail::assertQueued(InvoiceNotification::class);
    }

    /**
     * @runInSeparateProcess
     * @preserveGlobalState disabled
     */
    public function testBillingChangeBeforeInvoiceGeneration()
    {
        \Mockery::mock('alias:Mtc\MercuryDataModels\Setting')
            ->shouldReceive('query->whereIn->where->where->update')
            ->andReturnNull();


        $this->seed(PrimaryBillableSeed::class);
        $tenant = Tenant::factory()->create();
        $tenant->change_tier_on_next_invoice_to = Tier::STANDARD->value;
        $tenant->update([
            'next_invoice_due_at' => Carbon::now()->startOfDay(),
            'tier' => Tier::PRO->value,
        ]);

        TenantBillingDetail::factory()->create([
            'tenant_id' => $tenant->id,
        ]);

        TenantBillable::factory()->create([
            'tenant_id' => $tenant->id,
            'billable_id' => Billable::query()->inRandomOrder()->first()->id,
        ]);


        Mail::fake();
        $this->artisan(GenerateInvoices::class);

        Mail::assertQueued(InvoiceNotification::class);
        $tenant->refresh();

        $this->assertEquals(Tier::STANDARD->value, $tenant->tier);
        $this->assertNull($tenant->change_tier_on_next_invoice_to);
    }
}
