<?php

declare(strict_types=1);

use App\Models\Invoice;
use App\Models\PaymentTransaction;
use App\Models\User;
use Database\Seeders\RoleAndPermissionSeeder;
use Laravel\Cashier\Subscription;

beforeEach(function (): void {
    $this->seed(RoleAndPermissionSeeder::class);
    $this->adminUrl = 'http://'.config('app.domains.admin');
});

// ---------------------------------------------------------------------------
// Reports Index
// ---------------------------------------------------------------------------
describe('Reports Index', function (): void {
    it('loads the reports index page for admin', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->get($this->adminUrl.'/reports')
            ->assertOk()
            ->assertInertia(fn ($page) => $page->component('Admin/Reports/Index'));
    });

    it('denies customer access to reports', function (): void {
        $customer = User::factory()->customer()->create();

        $this->actingAs($customer)
            ->get($this->adminUrl.'/reports')
            ->assertForbidden();
    });
});

// ---------------------------------------------------------------------------
// Revenue Report
// ---------------------------------------------------------------------------
describe('Revenue Report', function (): void {
    it('returns correct structure for revenue report', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'revenue',
                'start_date' => now()->subMonth()->toDateString(),
                'end_date' => now()->toDateString(),
            ])
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->component('Admin/Reports/Show')
                ->where('reportType', 'revenue')
                ->has('reportData.total_revenue')
                ->has('reportData.by_period')
                ->has('reportData.by_service_type')
                ->has('reportData.by_gateway')
                ->has('reportData.by_plan')
                ->has('reportMeta.title')
                ->has('reportMeta.generated_at')
            );
    });

    it('filters revenue by date range', function (): void {
        $admin = User::factory()->admin()->create();
        $customer = User::factory()->customer()->create();

        // Create transactions in different months (use forceCreate to bypass $fillable for created_at)
        PaymentTransaction::forceCreate([
            'user_id' => $customer->id,
            'gateway' => 'stripe',
            'amount' => 100.00,
            'currency' => 'USD',
            'status' => 'succeeded',
            'created_at' => now()->subDays(5),
        ]);

        PaymentTransaction::forceCreate([
            'user_id' => $customer->id,
            'gateway' => 'stripe',
            'amount' => 200.00,
            'currency' => 'USD',
            'status' => 'succeeded',
            'created_at' => now()->subMonths(3),
        ]);

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'revenue',
                'start_date' => now()->subDays(10)->toDateString(),
                'end_date' => now()->toDateString(),
            ])
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->where('reportData.total_revenue', 100)
            );
    });

    it('filters revenue by service type', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'revenue',
                'start_date' => now()->subMonth()->toDateString(),
                'end_date' => now()->toDateString(),
                'service_type' => 'vps',
            ])
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->component('Admin/Reports/Show')
                ->where('reportType', 'revenue')
                ->where('reportMeta.service_type', 'vps')
            );
    });
});

// ---------------------------------------------------------------------------
// Profit & Loss Report
// ---------------------------------------------------------------------------
describe('Profit & Loss Report', function (): void {
    it('returns correct structure for profit loss report', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'profit_loss',
                'start_date' => now()->subMonth()->toDateString(),
                'end_date' => now()->toDateString(),
            ])
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->component('Admin/Reports/Show')
                ->where('reportType', 'profit_loss')
                ->has('reportData.revenue')
                ->has('reportData.refunds')
                ->has('reportData.gateway_fees')
                ->has('reportData.infrastructure_cost')
                ->has('reportData.net_profit')
                ->has('reportData.margin_percentage')
            );
    });
});

// ---------------------------------------------------------------------------
// Tax Report
// ---------------------------------------------------------------------------
describe('Tax Report', function (): void {
    it('returns correct structure for tax report', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'tax',
                'start_date' => now()->subMonth()->toDateString(),
                'end_date' => now()->toDateString(),
            ])
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->component('Admin/Reports/Show')
                ->where('reportType', 'tax')
                ->has('reportData.total_tax')
                ->has('reportData.by_country')
                ->has('reportData.by_region')
            );
    });
});

// ---------------------------------------------------------------------------
// Aging Report
// ---------------------------------------------------------------------------
describe('Aging Report', function (): void {
    it('returns correct structure for aging report', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'aging',
            ])
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->component('Admin/Reports/Show')
                ->where('reportType', 'aging')
                ->has('reportData.current')
                ->has('reportData.days_31_60')
                ->has('reportData.days_61_90')
                ->has('reportData.days_90_plus')
                ->has('reportData.total')
                ->has('reportData.invoices')
            );
    });

    it('works without date range parameters', function (): void {
        $admin = User::factory()->admin()->create();
        $customer = User::factory()->customer()->create();

        Invoice::factory()->create([
            'user_id' => $customer->id,
            'status' => 'overdue',
            'due_date' => now()->subDays(45),
        ]);

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'aging',
            ])
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->where('reportData.total.count', 1)
            );
    });
});

// ---------------------------------------------------------------------------
// Refund Report
// ---------------------------------------------------------------------------
describe('Refund Report', function (): void {
    it('returns correct structure for refund report', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'refund',
                'start_date' => now()->subMonth()->toDateString(),
                'end_date' => now()->toDateString(),
            ])
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->component('Admin/Reports/Show')
                ->where('reportType', 'refund')
                ->has('reportData.total_refunds')
                ->has('reportData.refund_count')
                ->has('reportData.by_gateway')
                ->has('reportData.by_month')
            );
    });
});

// ---------------------------------------------------------------------------
// Subscription Report
// ---------------------------------------------------------------------------
describe('Subscription Report', function (): void {
    it('returns correct structure for subscription report', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'subscription',
                'start_date' => now()->subMonth()->toDateString(),
                'end_date' => now()->toDateString(),
            ])
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->component('Admin/Reports/Show')
                ->where('reportType', 'subscription')
                ->has('reportData.new_subscriptions')
                ->has('reportData.cancelled_subscriptions')
                ->has('reportData.churn_rate')
                ->has('reportData.mrr_start')
                ->has('reportData.mrr_end')
                ->has('reportData.mrr_change')
                ->has('reportData.by_plan')
            );
    });
});

// ---------------------------------------------------------------------------
// Export
// ---------------------------------------------------------------------------
describe('Report Export', function (): void {
    it('exports PDF with correct content type', function (): void {
        $admin = User::factory()->admin()->create();

        $response = $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/export', [
                'report_type' => 'revenue',
                'start_date' => now()->subMonth()->toDateString(),
                'end_date' => now()->toDateString(),
                'format' => 'pdf',
            ]);

        $response->assertOk();
        expect($response->headers->get('content-type'))->toContain('pdf');
    });

    it('exports CSV with correct content type', function (): void {
        $admin = User::factory()->admin()->create();

        $response = $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/export', [
                'report_type' => 'profit_loss',
                'start_date' => now()->subMonth()->toDateString(),
                'end_date' => now()->toDateString(),
                'format' => 'csv',
            ]);

        $response->assertOk();
        expect($response->headers->get('content-type'))->toContain('text/csv');
    });

    it('exports JSON with correct content type', function (): void {
        $admin = User::factory()->admin()->create();

        $response = $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/export', [
                'report_type' => 'aging',
                'format' => 'json',
            ]);

        $response->assertOk();
        $response->assertJsonStructure([
            'report_type',
            'meta',
            'data',
        ]);
    });
});

// ---------------------------------------------------------------------------
// Validation
// ---------------------------------------------------------------------------
describe('Validation', function (): void {
    it('rejects invalid report type', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'invalid_type',
                'start_date' => now()->subMonth()->toDateString(),
                'end_date' => now()->toDateString(),
            ])
            ->assertSessionHasErrors('report_type');
    });

    it('rejects end date before start date', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'revenue',
                'start_date' => now()->toDateString(),
                'end_date' => now()->subMonth()->toDateString(),
            ])
            ->assertSessionHasErrors('end_date');
    });

    it('requires start and end date for non-aging reports', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'revenue',
            ])
            ->assertSessionHasErrors(['start_date', 'end_date']);
    });
});

// ---------------------------------------------------------------------------
// Empty Data
// ---------------------------------------------------------------------------
describe('Empty Data', function (): void {
    it('returns zeros not errors with no data', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'revenue',
                'start_date' => now()->subMonth()->toDateString(),
                'end_date' => now()->toDateString(),
            ])
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->where('reportData.total_revenue', 0)
                ->where('reportData.by_period', [])
                ->where('reportData.by_service_type', [])
                ->where('reportData.by_gateway', [])
                ->where('reportData.by_plan', [])
            );
    });

    it('returns zero profit loss with no transactions', function (): void {
        $admin = User::factory()->admin()->create();

        $this->actingAs($admin)
            ->post($this->adminUrl.'/reports/generate', [
                'report_type' => 'profit_loss',
                'start_date' => now()->subMonth()->toDateString(),
                'end_date' => now()->toDateString(),
            ])
            ->assertOk()
            ->assertInertia(fn ($page) => $page
                ->where('reportData.revenue', 0)
                ->where('reportData.refunds', 0)
                ->where('reportData.gateway_fees', 0)
                ->where('reportData.net_profit', 0)
                ->where('reportData.margin_percentage', 0)
            );
    });
});
