<?php

namespace Tests\Feature\Api;

use App\Models\User;
use App\Modules\CRM\Models\Lead;
use App\Modules\Inventory\Models\Product;
use App\Modules\Inventory\Models\Purchase;
use App\Modules\Invoice\Models\Invoice;
use App\Modules\Invoice\Models\Payment;
use App\Modules\POS\Models\Sale;
use App\Modules\Tenant\Models\Company;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;

class ReportsApiTest extends TestCase
{
    use RefreshDatabase;

    public function test_overview_report_returns_company_totals(): void
    {
        [$user, $company] = $this->createCompanyMember();
        [, $otherCompany] = $this->createCompanyMember('Other Company', 'other-company');

        Sale::query()->create([
            'company_id' => $company->id,
            'sale_number' => 'POS-2026-000001',
            'sale_date' => '2026-07-11',
            'subtotal' => 1000,
            'total' => 1000,
            'paid_total' => 1000,
        ]);
        Sale::query()->create([
            'company_id' => $otherCompany->id,
            'sale_number' => 'POS-2026-000001',
            'sale_date' => '2026-07-11',
            'subtotal' => 9999,
            'total' => 9999,
            'paid_total' => 9999,
        ]);
        $invoice = Invoice::query()->create([
            'company_id' => $company->id,
            'invoice_number' => 'INV-2026-000001',
            'issue_date' => '2026-07-11',
            'subtotal' => 1500,
            'total' => 1500,
            'paid_total' => 500,
            'due_total' => 1000,
            'status' => 'sent',
        ]);
        Payment::query()->create([
            'company_id' => $company->id,
            'invoice_id' => $invoice->id,
            'amount' => 500,
            'payment_method' => 'cash',
            'paid_at' => '2026-07-11',
        ]);
        Purchase::query()->create([
            'company_id' => $company->id,
            'purchase_number' => 'PUR-2026-000001',
            'purchase_date' => '2026-07-11',
            'subtotal' => 300,
            'total' => 300,
            'status' => 'received',
        ]);
        Product::query()->create([
            'company_id' => $company->id,
            'name' => 'Rice 5kg',
            'purchase_price' => 100,
            'current_stock' => 4,
            'low_stock_threshold' => 5,
        ]);
        Lead::query()->create([
            'company_id' => $company->id,
            'name' => 'Rahim Uddin',
            'deal_value' => 25000,
            'status' => 'open',
        ]);

        Sanctum::actingAs($user);

        $this->withHeader('X-Company-ID', (string) $company->id)
            ->getJson('/api/v1/reports/overview?start_date=2026-07-01&end_date=2026-07-31')
            ->assertOk()
            ->assertJsonPath('data.sales.count', 1)
            ->assertJsonPath('data.sales.total', '1000.00')
            ->assertJsonPath('data.invoices.total', '1500.00')
            ->assertJsonPath('data.invoices.due', '1000.00')
            ->assertJsonPath('data.payments.received', '500.00')
            ->assertJsonPath('data.purchases.total', '300.00')
            ->assertJsonPath('data.inventory.low_stock', 1)
            ->assertJsonPath('data.inventory.stock_value', '400.00')
            ->assertJsonPath('data.crm.pipeline_value', '25000.00');
    }

    public function test_sales_report_groups_by_day_and_payment_method(): void
    {
        [$user, $company] = $this->createCompanyMember();

        Sale::query()->create([
            'company_id' => $company->id,
            'sale_number' => 'POS-2026-000001',
            'sale_date' => '2026-07-11',
            'subtotal' => 1000,
            'total' => 1000,
            'paid_total' => 1000,
            'payment_method' => 'cash',
        ]);
        Sale::query()->create([
            'company_id' => $company->id,
            'sale_number' => 'POS-2026-000002',
            'sale_date' => '2026-07-11',
            'subtotal' => 500,
            'total' => 500,
            'paid_total' => 500,
            'payment_method' => 'card',
        ]);

        Sanctum::actingAs($user);

        $this->withHeader('X-Company-ID', (string) $company->id)
            ->getJson('/api/v1/reports/sales?start_date=2026-07-01&end_date=2026-07-31')
            ->assertOk()
            ->assertJsonPath('data.by_day.0.date', '2026-07-11')
            ->assertJsonPath('data.by_day.0.count', 2)
            ->assertJsonPath('data.by_day.0.total', '1500.00')
            ->assertJsonCount(2, 'data.payment_methods');
    }

    public function test_inventory_and_crm_reports_return_details(): void
    {
        [$user, $company] = $this->createCompanyMember();

        Product::query()->create([
            'company_id' => $company->id,
            'name' => 'Rice 5kg',
            'sku' => 'RICE-5KG',
            'purchase_price' => 100,
            'current_stock' => 4,
            'low_stock_threshold' => 5,
        ]);
        Lead::query()->create([
            'company_id' => $company->id,
            'name' => 'Rahim Uddin',
            'stage' => 'qualified',
            'deal_value' => 25000,
            'next_follow_up_at' => '2026-07-15',
        ]);

        Sanctum::actingAs($user);

        $this->withHeader('X-Company-ID', (string) $company->id)
            ->getJson('/api/v1/reports/inventory')
            ->assertOk()
            ->assertJsonPath('data.summary.low_stock', 1)
            ->assertJsonPath('data.low_stock_products.0.sku', 'RICE-5KG');

        $this->withHeader('X-Company-ID', (string) $company->id)
            ->getJson('/api/v1/reports/crm')
            ->assertOk()
            ->assertJsonPath('data.stages.0.stage', 'qualified')
            ->assertJsonPath('data.stages.0.value', '25000.00')
            ->assertJsonPath('data.upcoming_follow_ups.0.name', 'Rahim Uddin');
    }

    /**
     * @return array{0: User, 1: Company}
     */
    private function createCompanyMember(string $companyName = 'ABC Grocery', string $slug = 'abc-grocery'): array
    {
        $user = User::factory()->create();
        $company = Company::query()->create([
            'name' => $companyName,
            'slug' => $slug,
            'status' => 'active',
        ]);

        $company->users()->attach($user->id, [
            'role' => 'owner',
            'joined_at' => now(),
        ]);
        $this->attachActiveSubscription($company, ['reports']);

        return [$user, $company];
    }
}
