<?php

namespace Tests\Feature;

use App\Models\Category;
use App\Models\Transaction;
use App\Models\User;
use App\Models\Vendor;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
use Tests\TestCase;

class AdminReportsSummaryTest extends TestCase
{
    use RefreshDatabase;

    public function test_reports_default_range_is_today(): void
    {
        Carbon::setTestNow('2026-03-08 10:00:00');

        $admin = User::factory()->create();
        $dataCategory = Category::query()->create(['name' => 'Data SME', 'slug' => 'data_sme']);

        Transaction::query()->create([
            'user_id' => $admin->id,
            'category_id' => $dataCategory->id,
            'internal_reference' => 'RPT-TODAY-001',
            'amount_charged' => 400,
            'vendor_cost' => 350,
            'profit' => 50,
            'status' => 'success',
            'created_at' => Carbon::parse('2026-03-08 08:00:00'),
            'updated_at' => Carbon::parse('2026-03-08 08:00:00'),
        ]);

        Transaction::query()->create([
            'user_id' => $admin->id,
            'category_id' => $dataCategory->id,
            'internal_reference' => 'RPT-YDAY-001',
            'amount_charged' => 100,
            'vendor_cost' => 90,
            'profit' => 10,
            'status' => 'success',
            'created_at' => Carbon::parse('2026-03-07 19:00:00'),
            'updated_at' => Carbon::parse('2026-03-07 19:00:00'),
        ]);

        $response = $this->withoutMiddleware()
            ->actingAs($admin)
            ->get(route('admin.reports.index'));

        $response->assertOk();
        $page = $response->viewData('page');
        $props = (array) ($page['props'] ?? []);
        $summary = (array) ($props['summary'] ?? []);
        $filters = (array) ($props['filters'] ?? []);

        $this->assertSame('today', (string) ($filters['range'] ?? ''));
        $this->assertSame(1, (int) ($summary['total_transactions'] ?? 0));
        $this->assertSame(400.0, (float) ($summary['gross_sales'] ?? 0));

        Carbon::setTestNow();
    }

    public function test_reports_use_selected_date_range_and_service_summary_is_correct(): void
    {
        Carbon::setTestNow('2026-03-08 10:00:00');

        $admin = User::factory()->create();
        $dataCategory = Category::query()->create(['name' => 'Data SME', 'slug' => 'data_sme']);
        $airtimeCategory = Category::query()->create(['name' => 'Airtime VTU', 'slug' => 'airtime_vtu']);

        $vendor = new Vendor([
            'name' => 'Report Vendor',
            'type' => 'msorg',
            'base_url' => 'https://vendor-report.test',
            'auth_type' => 'token',
            'status' => 'active',
            'timeout_seconds' => 30,
            'webhook_enabled' => false,
        ]);
        $vendor->secret = 'report-secret';
        $vendor->save();

        Transaction::query()->create([
            'user_id' => $admin->id,
            'category_id' => $dataCategory->id,
            'vendor_id' => $vendor->id,
            'internal_reference' => 'RPT-IN-001',
            'amount_charged' => 400,
            'vendor_cost' => 350,
            'profit' => 50,
            'status' => 'success',
            'created_at' => Carbon::parse('2026-03-07 08:00:00'),
            'updated_at' => Carbon::parse('2026-03-07 08:00:00'),
        ]);

        Transaction::query()->create([
            'user_id' => $admin->id,
            'category_id' => $airtimeCategory->id,
            'vendor_id' => $vendor->id,
            'internal_reference' => 'RPT-IN-002',
            'amount_charged' => 100,
            'vendor_cost' => 100,
            'profit' => 0,
            'status' => 'reversed',
            'created_at' => Carbon::parse('2026-03-08 09:00:00'),
            'updated_at' => Carbon::parse('2026-03-08 09:00:00'),
        ]);

        Transaction::query()->create([
            'user_id' => $admin->id,
            'category_id' => $dataCategory->id,
            'vendor_id' => $vendor->id,
            'internal_reference' => 'RPT-OUT-001',
            'amount_charged' => 999,
            'vendor_cost' => 900,
            'profit' => 99,
            'status' => 'success',
            'created_at' => Carbon::parse('2026-01-10 10:00:00'),
            'updated_at' => Carbon::parse('2026-01-10 10:00:00'),
        ]);

        $response = $this->withoutMiddleware()
            ->actingAs($admin)
            ->get(route('admin.reports.index', [
                'range' => 'custom',
                'start_date' => '2026-03-07',
                'end_date' => '2026-03-08',
                'group_by' => 'day',
            ]));

        $response->assertOk();

        $page = $response->viewData('page');
        $props = (array) ($page['props'] ?? []);
        $summary = (array) ($props['summary'] ?? []);

        $this->assertSame(2, (int) ($summary['total_transactions'] ?? 0));
        $this->assertSame(500.0, (float) ($summary['gross_sales'] ?? 0));
        $this->assertSame(450.0, (float) ($summary['vendor_cost_total'] ?? 0));
        $this->assertSame(50.0, (float) ($summary['total_profit'] ?? 0));
        $this->assertSame(1, (int) ($summary['success_count'] ?? 0));
        $this->assertSame(1, (int) ($summary['failed_count'] ?? 0));

        $services = collect((array) ($props['serviceSummary'] ?? []))
            ->keyBy('service_key');

        $this->assertSame(1, (int) data_get($services->get('data'), 'total_transactions'));
        $this->assertSame(1, (int) data_get($services->get('airtime'), 'total_transactions'));

        $timeline = (array) ($props['timeline'] ?? []);
        $this->assertCount(2, $timeline);

        Carbon::setTestNow();
    }

    public function test_reports_export_csv_generates_csv_payload(): void
    {
        Carbon::setTestNow('2026-03-08 10:00:00');

        $admin = User::factory()->create();
        $dataCategory = Category::query()->create(['name' => 'Data SME', 'slug' => 'data_sme']);

        Transaction::query()->create([
            'user_id' => $admin->id,
            'category_id' => $dataCategory->id,
            'internal_reference' => 'RPT-CSV-001',
            'amount_charged' => 350,
            'vendor_cost' => 300,
            'profit' => 50,
            'status' => 'success',
            'created_at' => Carbon::parse('2026-03-08 08:00:00'),
            'updated_at' => Carbon::parse('2026-03-08 08:00:00'),
        ]);

        $response = $this->withoutMiddleware()
            ->actingAs($admin)
            ->get(route('admin.reports.export-csv', [
                'range' => 'today',
                'group_by' => 'day',
            ]));

        $response->assertOk();
        $this->assertStringContainsString(
            'text/csv',
            strtolower((string) $response->headers->get('content-type'))
        );

        $csv = $response->streamedContent();
        $this->assertStringContainsString('REPORT META', $csv);
        $this->assertStringContainsString('SUMMARY', $csv);
        $this->assertStringContainsString('SERVICE SUMMARY', $csv);
        $this->assertStringContainsString('VENDOR PERFORMANCE', $csv);
        $this->assertStringContainsString('350', $csv);

        Carbon::setTestNow();
    }

    public function test_reports_summary_separates_realized_profit_from_failure_impact(): void
    {
        Carbon::setTestNow('2026-03-08 10:00:00');

        $admin = User::factory()->create();
        $dataCategory = Category::query()->create(['name' => 'Data SME', 'slug' => 'data_sme']);

        Transaction::query()->create([
            'user_id' => $admin->id,
            'category_id' => $dataCategory->id,
            'internal_reference' => 'RPT-RZ-001',
            'amount_charged' => 500,
            'vendor_cost' => 450,
            'profit' => 50,
            'status' => 'success',
            'created_at' => Carbon::parse('2026-03-08 08:00:00'),
            'updated_at' => Carbon::parse('2026-03-08 08:00:00'),
        ]);

        Transaction::query()->create([
            'user_id' => $admin->id,
            'category_id' => $dataCategory->id,
            'internal_reference' => 'RPT-RZ-002',
            'amount_charged' => 100,
            'vendor_cost' => 108,
            'profit' => -8,
            'status' => 'reversed',
            'created_at' => Carbon::parse('2026-03-08 08:30:00'),
            'updated_at' => Carbon::parse('2026-03-08 08:30:00'),
        ]);

        Transaction::query()->create([
            'user_id' => $admin->id,
            'category_id' => $dataCategory->id,
            'internal_reference' => 'RPT-RZ-003',
            'amount_charged' => 200,
            'vendor_cost' => null,
            'profit' => null,
            'status' => 'pending',
            'created_at' => Carbon::parse('2026-03-08 09:00:00'),
            'updated_at' => Carbon::parse('2026-03-08 09:00:00'),
        ]);

        $response = $this->withoutMiddleware()
            ->actingAs($admin)
            ->get(route('admin.reports.index', [
                'range' => 'today',
                'group_by' => 'day',
            ]));

        $response->assertOk();

        $page = $response->viewData('page');
        $props = (array) ($page['props'] ?? []);
        $summary = (array) ($props['summary'] ?? []);

        $this->assertSame(50.0, (float) ($summary['realized_profit'] ?? 0));
        $this->assertSame(-8.0, (float) ($summary['failure_impact'] ?? 0));
        $this->assertSame(42.0, (float) ($summary['net_profit'] ?? 0));
        $this->assertSame(50.0, (float) ($summary['total_profit'] ?? 0));

        Carbon::setTestNow();
    }
}
