<?php

namespace Tests\Unit\SystemCore\Models;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Modules\SystemCore\App\Models\CoreProduct;
use Modules\SystemCore\App\Models\CoreProductCategory;
use Tests\TestCase;
use Tests\Traits\CreatesSystemCoreEntities;
use Tests\Traits\CreatesUsers;

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

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

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

        $category = CoreProductCategory::create([
            'name' => 'Test Category',
            'code' => 'TEST-CAT',
            'is_active' => true,
            'created_by_id' => $admin->id,
        ]);

        $this->assertDatabaseHas('core_product_categories', [
            'name' => 'Test Category',
            'code' => 'TEST-CAT',
        ]);
        $this->assertNotNull($category->id);
    }

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

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

        $category = $this->createCoreProductCategory([
            'is_active' => true,
            'created_by_id' => $admin->id,
        ]);

        $this->assertTrue($category->is_active);
        $this->assertIsBool($category->is_active);
    }

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

        $category = $this->createCoreProductCategory([
            'display_order' => 5,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals(5, $category->display_order);
        $this->assertIsInt($category->display_order);
    }

    // ==========================================
    // Scope Tests
    // ==========================================

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

        $activeCategory = $this->createCoreProductCategory([
            'is_active' => true,
            'created_by_id' => $admin->id,
        ]);

        $inactiveCategory = $this->createCoreProductCategory([
            'is_active' => false,
            'created_by_id' => $admin->id,
        ]);

        $activeCategories = CoreProductCategory::active()->get();

        $this->assertTrue($activeCategories->contains($activeCategory));
        $this->assertFalse($activeCategories->contains($inactiveCategory));
    }

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

        $rootCategory = $this->createCoreProductCategory([
            'parent_id' => null,
            'created_by_id' => $admin->id,
        ]);

        $childCategory = $this->createCoreProductCategory([
            'parent_id' => $rootCategory->id,
            'created_by_id' => $admin->id,
        ]);

        $rootCategories = CoreProductCategory::root()->get();

        $this->assertTrue($rootCategories->contains($rootCategory));
        $this->assertFalse($rootCategories->contains($childCategory));
    }

    // ==========================================
    // Relationship Tests (Self-Referencing)
    // ==========================================

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

        $parentCategory = $this->createCoreProductCategory(['created_by_id' => $admin->id]);
        $childCategory = $this->createCoreProductCategory([
            'parent_id' => $parentCategory->id,
            'created_by_id' => $admin->id,
        ]);

        $this->assertNotNull($childCategory->parent);
        $this->assertInstanceOf(CoreProductCategory::class, $childCategory->parent);
        $this->assertEquals($parentCategory->id, $childCategory->parent->id);
    }

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

        $parentCategory = $this->createCoreProductCategory(['created_by_id' => $admin->id]);

        $this->createCoreProductCategory([
            'parent_id' => $parentCategory->id,
            'created_by_id' => $admin->id,
        ]);
        $this->createCoreProductCategory([
            'parent_id' => $parentCategory->id,
            'created_by_id' => $admin->id,
        ]);

        $parentCategory->refresh();

        $this->assertCount(2, $parentCategory->children);
        $this->assertInstanceOf(CoreProductCategory::class, $parentCategory->children->first());
    }

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

        $category = $this->createCoreProductCategory(['created_by_id' => $admin->id]);

        $this->createCoreProduct([
            'category_id' => $category->id,
            'created_by_id' => $admin->id,
        ]);
        $this->createCoreProduct([
            'category_id' => $category->id,
            'created_by_id' => $admin->id,
        ]);

        $category->refresh();

        $this->assertCount(2, $category->products);
        $this->assertInstanceOf(CoreProduct::class, $category->products->first());
    }

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

        // Create 3-level hierarchy
        $grandparent = $this->createCoreProductCategory([
            'name' => 'Electronics',
            'created_by_id' => $admin->id,
        ]);

        $parent = $this->createCoreProductCategory([
            'name' => 'Phones',
            'parent_id' => $grandparent->id,
            'created_by_id' => $admin->id,
        ]);

        $child = $this->createCoreProductCategory([
            'name' => 'Smartphones',
            'parent_id' => $parent->id,
            'created_by_id' => $admin->id,
        ]);

        // Test downward navigation
        $this->assertCount(1, $grandparent->children);
        $this->assertEquals('Phones', $grandparent->children->first()->name);

        // Test upward navigation
        $this->assertEquals('Phones', $child->parent->name);
        $this->assertEquals('Electronics', $child->parent->parent->name);
    }

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

        $root = $this->createCoreProductCategory([
            'name' => 'Root',
            'parent_id' => null,
            'created_by_id' => $admin->id,
        ]);

        $level1 = $this->createCoreProductCategory([
            'name' => 'Level 1',
            'parent_id' => $root->id,
            'created_by_id' => $admin->id,
        ]);

        $level2 = $this->createCoreProductCategory([
            'name' => 'Level 2',
            'parent_id' => $level1->id,
            'created_by_id' => $admin->id,
        ]);

        // Verify structure
        $this->assertNull($root->parent_id);
        $this->assertEquals($root->id, $level1->parent_id);
        $this->assertEquals($level1->id, $level2->parent_id);

        // Verify relationships
        $this->assertNull($root->parent);
        $this->assertNotNull($level1->parent);
        $this->assertNotNull($level2->parent);
    }

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

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

        $category = $this->createCoreProductCategory(['created_by_id' => $admin->id]);
        $categoryId = $category->id;

        $category->delete();

        $this->assertSoftDeleted('core_product_categories', ['id' => $categoryId]);
    }

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

        $category = $this->createCoreProductCategory(['created_by_id' => $admin->id]);
        $categoryId = $category->id;

        $category->delete();
        $this->assertSoftDeleted('core_product_categories', ['id' => $categoryId]);

        $category->restore();
        $this->assertDatabaseHas('core_product_categories', [
            'id' => $categoryId,
            'deleted_at' => null,
        ]);
    }
}
