<?php

declare(strict_types=1);

namespace Tests\Unit\Services;

use App\Services\ProductService;
use App\Services\DashboardService;
use App\Services\LeadService;
use Tests\TestCase;

class ProductDashboardServiceTest extends TestCase
{
    private ProductService $productService;
    private DashboardService $dashboardService;
    private LeadService $leadService;
    private int $userId;
    private int $adminId;
    private int $eventId;

    protected function setUp(): void
    {
        parent::setUp();
        $this->productService = new ProductService();
        $this->dashboardService = new DashboardService();
        $this->leadService = new LeadService();
        $this->userId = $this->createTestUser('gestor@test.com', 'comercial_manager', 'active');
        $this->adminId = $this->createTestUser('admin@test.com', 'super_admin', 'active');
        $this->eventId = $this->createTestEvent('Feria Products', $this->userId);
    }

    private function createLead(string $email = 'lead@test.com'): int
    {
        $lead = $this->leadService->createManual([
            'first_name' => 'Lead', 'last_name' => 'Test', 'email' => $email,
        ], $this->userId, $this->eventId);
        return $lead['id'];
    }

    public function testCreateProduct(): void
    {
        $product = $this->productService->createProduct([
            'name' => 'Suplemento Bovino',
            'description' => 'Suplemento nutricional',
            'category' => 'Nutrición',
        ]);

        $this->assertEquals('Suplemento Bovino', $product['name']);
        $this->assertEquals('Nutrición', $product['category']);
        $this->assertEquals('active', $product['status']);
    }

    public function testGetProducts(): void
    {
        $this->productService->createProduct(['name' => 'Producto A', 'category' => 'Cat A']);
        $this->productService->createProduct(['name' => 'Producto B', 'category' => 'Cat B']);

        $result = $this->productService->getProducts();
        $this->assertGreaterThanOrEqual(2, $result['total']);
    }

    public function testGetProductsWithSearch(): void
    {
        $this->productService->createProduct(['name' => 'Vacuna Triple', 'category' => 'Sanidad']);
        $this->productService->createProduct(['name' => 'Antibiótico', 'category' => 'Sanidad']);

        $result = $this->productService->getProducts(['search' => 'Vacuna']);
        $this->assertEquals(1, $result['total']);
    }

    public function testGetProduct(): void
    {
        $created = $this->productService->createProduct(['name' => 'Detalle Producto']);
        $product = $this->productService->getProduct($created['id']);
        $this->assertEquals('Detalle Producto', $product['name']);
    }

    public function testGetProductNotFound(): void
    {
        $this->expectException(\RuntimeException::class);
        $this->productService->getProduct(9999);
    }

    public function testUpdateProduct(): void
    {
        $created = $this->productService->createProduct(['name' => 'Original', 'category' => 'Test']);

        $updated = $this->productService->updateProduct($created['id'], [
            'name' => 'Actualizado',
            'description' => 'Nueva desc',
        ]);

        $this->assertEquals('Actualizado', $updated['name']);
        $this->assertEquals('Nueva desc', $updated['description']);
        $this->assertEquals('Test', $updated['category']);
    }

    public function testDeleteProduct(): void
    {
        $created = $this->productService->createProduct(['name' => 'Para Eliminar']);
        $this->productService->deleteProduct($created['id']);

        $this->expectException(\RuntimeException::class);
        $this->productService->getProduct($created['id']);
    }

    public function testToggleStatus(): void
    {
        $created = $this->productService->createProduct(['name' => 'Toggle']);

        $toggled = $this->productService->toggleStatus($created['id']);
        $this->assertEquals('inactive', $toggled['status']);

        $toggledBack = $this->productService->toggleStatus($created['id']);
        $this->assertEquals('active', $toggledBack['status']);
    }

    public function testAttachToLead(): void
    {
        $product = $this->productService->createProduct(['name' => 'Producto Lead']);
        $leadId = $this->createLead();

        $result = $this->productService->attachToLead($leadId, $product['id']);
        $this->assertCount(1, $result);
        $this->assertEquals('Producto Lead', $result[0]['name']);
    }

    public function testAttachDuplicate(): void
    {
        $product = $this->productService->createProduct(['name' => 'Duplicado']);
        $leadId = $this->createLead();

        $this->productService->attachToLead($leadId, $product['id']);
        $result = $this->productService->attachToLead($leadId, $product['id']);
        $this->assertCount(1, $result);
    }

    public function testDetachFromLead(): void
    {
        $product = $this->productService->createProduct(['name' => 'Desasociar']);
        $leadId = $this->createLead();

        $this->productService->attachToLead($leadId, $product['id']);
        $result = $this->productService->detachFromLead($leadId, $product['id']);
        $this->assertCount(0, $result);
    }

    public function testMultipleProductsPerLead(): void
    {
        $p1 = $this->productService->createProduct(['name' => 'P1']);
        $p2 = $this->productService->createProduct(['name' => 'P2']);
        $p3 = $this->productService->createProduct(['name' => 'P3']);
        $leadId = $this->createLead();

        $this->productService->attachToLead($leadId, $p1['id']);
        $this->productService->attachToLead($leadId, $p2['id']);
        $this->productService->attachToLead($leadId, $p3['id']);

        $products = $this->productService->getLeadProducts($leadId);
        $this->assertCount(3, $products);
    }

    public function testDashboardKPIs(): void
    {
        $kpis = $this->dashboardService->getKPIs($this->userId, 'comercial_manager', $this->eventId);

        $this->assertArrayHasKey('leads_captados_hoy', $kpis);
        $this->assertArrayHasKey('leads_calientes', $kpis);
        $this->assertArrayHasKey('leads_pendientes', $kpis);
        $this->assertArrayHasKey('leads_ganados', $kpis);
        $this->assertArrayHasKey('leads_perdidos', $kpis);
        $this->assertArrayHasKey('productos_top', $kpis);
    }

    public function testDashboardWithLeads(): void
    {
        $leadId = $this->createLead();
        $product = $this->productService->createProduct(['name' => 'Test KPI']);
        $this->productService->attachToLead($leadId, $product['id']);

        $this->leadService->changeStatus($leadId, 'calificado', null, null, $this->userId);

        $kpis = $this->dashboardService->getKPIs($this->userId, 'comercial_manager', $this->eventId);

        $this->assertEquals(1, $kpis['leads_captados_hoy']);
        $this->assertEquals(1, $kpis['leads_calientes']);
        $this->assertGreaterThanOrEqual(1, count($kpis['productos_top']));
    }

    public function testDashboardSoftScoping(): void
    {
        $this->createLead('gestor-lead@test.com');

        $this->leadService->createManual([
            'first_name' => 'Admin', 'last_name' => 'Lead', 'email' => 'admin-lead@test.com',
        ], $this->adminId, $this->eventId);

        $kpisGestor = $this->dashboardService->getKPIs($this->userId, 'comercial_manager', $this->eventId);
        $this->assertEquals(1, $kpisGestor['leads_pendientes']);

        $kpisAdmin = $this->dashboardService->getKPIs($this->adminId, 'super_admin', $this->eventId);
        $this->assertGreaterThanOrEqual(2, $kpisAdmin['leads_pendientes']);
    }
}
