<?php

namespace Tests\Unit\SystemCore\Models;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Modules\SystemCore\App\Models\CoreContact;
use Modules\SystemCore\App\Models\CoreCustomer;
use Modules\SystemCore\App\Models\CoreSupplier;
use Tests\TestCase;
use Tests\Traits\CreatesSystemCoreEntities;
use Tests\Traits\CreatesUsers;

class CoreContactTest extends TestCase
{
    use CreatesSystemCoreEntities;
    use CreatesUsers;
    use RefreshDatabase;

    // ==========================================
    // Creation Tests
    // ==========================================

    public function test_can_create_contact_for_customer(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $customer = $this->createCoreCustomer(['created_by_id' => $admin->id]);

        $contact = CoreContact::create([
            'entity_type' => 'customer',
            'entity_id' => $customer->id,
            'contact_type' => 'primary',
            'first_name' => 'John',
            'last_name' => 'Doe',
            'email' => 'john.doe@example.com',
            'is_primary' => true,
        ]);

        $this->assertDatabaseHas('core_contacts', [
            'entity_type' => 'customer',
            'entity_id' => $customer->id,
            'first_name' => 'John',
            'last_name' => 'Doe',
        ]);
        $this->assertNotNull($contact->id);
    }

    public function test_can_create_contact_for_supplier(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $supplier = $this->createCoreSupplier(['created_by_id' => $admin->id]);

        $contact = CoreContact::create([
            'entity_type' => 'supplier',
            'entity_id' => $supplier->id,
            'contact_type' => 'sales',
            'first_name' => 'Jane',
            'last_name' => 'Smith',
            'email' => 'jane.smith@vendor.com',
            'is_primary' => true,
        ]);

        $this->assertDatabaseHas('core_contacts', [
            'entity_type' => 'supplier',
            'entity_id' => $supplier->id,
            'first_name' => 'Jane',
        ]);
    }

    // ==========================================
    // Accessor Tests
    // ==========================================

    public function test_full_name_attribute_returns_combined_name(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $customer = $this->createCoreCustomer(['created_by_id' => $admin->id]);

        $contact = $this->createCoreContact([
            'entity_type' => 'customer',
            'entity_id' => $customer->id,
            'first_name' => 'John',
            'last_name' => 'Doe',
        ]);

        $this->assertEquals('John Doe', $contact->full_name);
    }

    public function test_full_name_trims_whitespace(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $customer = $this->createCoreCustomer(['created_by_id' => $admin->id]);

        $contact = $this->createCoreContact([
            'entity_type' => 'customer',
            'entity_id' => $customer->id,
            'first_name' => '  John  ',
            'last_name' => '  Doe  ',
        ]);

        // The full_name accessor trims the concatenation
        $this->assertEquals('John     Doe', $contact->full_name);
    }

    public function test_full_name_with_only_first_name(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $customer = $this->createCoreCustomer(['created_by_id' => $admin->id]);

        $contact = $this->createCoreContact([
            'entity_type' => 'customer',
            'entity_id' => $customer->id,
            'first_name' => 'John',
            'last_name' => '',
        ]);

        $this->assertEquals('John', $contact->full_name);
    }

    public function test_full_name_with_only_last_name(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $customer = $this->createCoreCustomer(['created_by_id' => $admin->id]);

        $contact = $this->createCoreContact([
            'entity_type' => 'customer',
            'entity_id' => $customer->id,
            'first_name' => '',
            'last_name' => 'Doe',
        ]);

        $this->assertEquals('Doe', $contact->full_name);
    }

    // ==========================================
    // Casting Tests
    // ==========================================

    public function test_is_primary_casts_to_boolean(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $customer = $this->createCoreCustomer(['created_by_id' => $admin->id]);

        $contact = $this->createCoreContact([
            'entity_type' => 'customer',
            'entity_id' => $customer->id,
            'is_primary' => true,
        ]);

        $this->assertTrue($contact->is_primary);
        $this->assertIsBool($contact->is_primary);
    }

    // ==========================================
    // Polymorphic Relationship Tests
    // ==========================================

    public function test_contact_entity_morphs_to_customer(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $customer = $this->createCoreCustomer(['created_by_id' => $admin->id]);

        $contact = $this->createCoreContact([
            'entity_type' => CoreCustomer::class,
            'entity_id' => $customer->id,
        ]);

        $this->assertEquals($customer->id, $contact->entity_id);
    }

    public function test_contact_entity_morphs_to_supplier(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $supplier = $this->createCoreSupplier(['created_by_id' => $admin->id]);

        $contact = $this->createCoreContact([
            'entity_type' => CoreSupplier::class,
            'entity_id' => $supplier->id,
        ]);

        $this->assertEquals($supplier->id, $contact->entity_id);
    }

    public function test_customer_contacts_only_returns_customer_entity_type(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $customer = $this->createCoreCustomer(['created_by_id' => $admin->id]);
        $supplier = $this->createCoreSupplier(['created_by_id' => $admin->id]);

        // Create contact for customer
        $this->createCoreContact([
            'entity_type' => 'customer',
            'entity_id' => $customer->id,
            'first_name' => 'Customer',
            'last_name' => 'Contact',
        ]);

        // Create contact for supplier
        $this->createCoreContact([
            'entity_type' => 'supplier',
            'entity_id' => $supplier->id,
            'first_name' => 'Supplier',
            'last_name' => 'Contact',
        ]);

        $customer->refresh();

        $this->assertCount(1, $customer->contacts);
        $this->assertEquals('Customer', $customer->contacts->first()->first_name);
    }

    // ==========================================
    // Soft Delete Tests
    // ==========================================

    public function test_contact_can_be_soft_deleted(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $customer = $this->createCoreCustomer(['created_by_id' => $admin->id]);
        $contact = $this->createCoreContact([
            'entity_type' => 'customer',
            'entity_id' => $customer->id,
        ]);
        $contactId = $contact->id;

        $contact->delete();

        $this->assertSoftDeleted('core_contacts', ['id' => $contactId]);
    }

    public function test_contact_can_be_restored(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $customer = $this->createCoreCustomer(['created_by_id' => $admin->id]);
        $contact = $this->createCoreContact([
            'entity_type' => 'customer',
            'entity_id' => $customer->id,
        ]);
        $contactId = $contact->id;

        $contact->delete();
        $this->assertSoftDeleted('core_contacts', ['id' => $contactId]);

        $contact->restore();
        $this->assertDatabaseHas('core_contacts', [
            'id' => $contactId,
            'deleted_at' => null,
        ]);
    }
}
