<?php

namespace Tests\Feature\Api;

use App\Models\User;
use App\Modules\CRM\Models\Lead;
use App\Modules\Tenant\Models\Company;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;

class CrmApiTest extends TestCase
{
    use RefreshDatabase;

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

        Sanctum::actingAs($user);

        $leadId = $this->withHeader('X-Company-ID', (string) $company->id)
            ->postJson('/api/v1/crm/leads', [
                'name' => 'Rahim Uddin',
                'company_name' => 'Rahim Traders',
                'email' => 'rahim@example.com',
                'phone' => '01700000000',
                'source' => 'facebook',
                'deal_value' => 25000,
            ])
            ->assertCreated()
            ->assertJsonPath('data.stage', 'new')
            ->assertJsonPath('data.status', 'open')
            ->json('data.id');

        $this->withHeader('X-Company-ID', (string) $company->id)
            ->patchJson("/api/v1/crm/leads/{$leadId}", [
                'stage' => 'qualified',
            ])
            ->assertOk()
            ->assertJsonPath('data.stage', 'qualified');

        $this->withHeader('X-Company-ID', (string) $company->id)
            ->getJson('/api/v1/crm/summary')
            ->assertOk()
            ->assertJsonPath('data.total_leads', 1)
            ->assertJsonPath('data.open_leads', 1)
            ->assertJsonPath('data.pipeline_value', '25000.00');
    }

    public function test_user_can_add_activity_and_follow_up_date(): void
    {
        [$user, $company] = $this->createCompanyMember();
        $lead = Lead::query()->create([
            'company_id' => $company->id,
            'name' => 'Rahim Uddin',
            'deal_value' => 25000,
        ]);

        Sanctum::actingAs($user);

        $this->withHeader('X-Company-ID', (string) $company->id)
            ->postJson("/api/v1/crm/leads/{$lead->id}/activities", [
                'type' => 'call',
                'subject' => 'Initial call',
                'description' => 'Asked for package details.',
                'activity_date' => '2026-07-11',
                'next_follow_up_at' => '2026-07-15',
            ])
            ->assertCreated()
            ->assertJsonPath('data.type', 'call')
            ->assertJsonPath('data.next_follow_up_at', '2026-07-15');

        $this->assertDatabaseHas('crm_leads', [
            'id' => $lead->id,
            'next_follow_up_at' => '2026-07-15',
        ]);
    }

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

        foreach (['Rahim Uddin', 'Karim Ahmed', 'Nusrat Jahan'] as $name) {
            Lead::query()->create([
                'company_id' => $company->id,
                'name' => $name,
                'deal_value' => 1000,
            ]);
        }

        Sanctum::actingAs($user);

        $this->withHeader('X-Company-ID', (string) $company->id)
            ->getJson('/api/v1/crm/leads?page=1&per_page=2')
            ->assertOk()
            ->assertJsonCount(2, 'data.data')
            ->assertJsonPath('data.meta.current_page', 1)
            ->assertJsonPath('data.meta.per_page', 2)
            ->assertJsonPath('data.meta.total', 3);
    }

    public function test_user_can_convert_lead_to_customer(): void
    {
        [$user, $company] = $this->createCompanyMember();
        $lead = Lead::query()->create([
            'company_id' => $company->id,
            'name' => 'Rahim Uddin',
            'email' => 'rahim@example.com',
            'phone' => '01700000000',
            'company_name' => 'Rahim Traders',
            'deal_value' => 25000,
        ]);

        Sanctum::actingAs($user);

        $this->withHeader('X-Company-ID', (string) $company->id)
            ->postJson("/api/v1/crm/leads/{$lead->id}/convert")
            ->assertOk()
            ->assertJsonPath('data.name', 'Rahim Uddin')
            ->assertJsonPath('data.email', 'rahim@example.com');

        $this->assertDatabaseHas('customers', [
            'company_id' => $company->id,
            'name' => 'Rahim Uddin',
        ]);

        $this->assertDatabaseHas('crm_leads', [
            'id' => $lead->id,
            'stage' => 'won',
            'status' => 'closed',
        ]);
    }

    public function test_lead_from_another_company_cannot_be_updated(): void
    {
        [$firstUser, $firstCompany] = $this->createCompanyMember('First Company', 'first-company');
        [$secondUser, $secondCompany] = $this->createCompanyMember('Second Company', 'second-company');
        $lead = Lead::query()->create([
            'company_id' => $firstCompany->id,
            'name' => 'Rahim Uddin',
        ]);

        Sanctum::actingAs($secondUser);

        $this->withHeader('X-Company-ID', (string) $secondCompany->id)
            ->patchJson("/api/v1/crm/leads/{$lead->id}", [
                'stage' => 'qualified',
            ])
            ->assertNotFound();

        $this->assertDatabaseHas('crm_leads', [
            'id' => $lead->id,
            'stage' => 'new',
        ]);
    }

    /**
     * @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, ['crm']);

        return [$user, $company];
    }
}
