<?php

namespace Tests\Feature\Integration;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use Tests\Traits\CreatesSystemCoreEntities;
use Tests\Traits\CreatesUsers;

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

    // ==========================================
    // Core Model Graceful Degradation Tests
    // ==========================================

    public function test_sales_order_warehouse_returns_null_when_wms_disabled(): void
    {
        if (moduleExists('WMSInventoryCore')) {
            $this->markTestSkipped('WMSInventoryCore is enabled - testing disabled scenario');
        }

        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $salesOrder = $this->createCoreSalesOrder([
            'warehouse_id' => null,
            'created_by_id' => $admin->id,
        ]);

        // Should return null without throwing error
        $this->assertNull($salesOrder->warehouse);
    }

    public function test_sales_order_accounting_transaction_returns_null_when_accounting_disabled(): void
    {
        if (moduleExists('AccountingCore')) {
            $this->markTestSkipped('AccountingCore is enabled - testing disabled scenario');
        }

        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $salesOrder = $this->createCoreSalesOrder([
            'created_by_id' => $admin->id,
        ]);

        // Should return null without throwing error
        $this->assertNull($salesOrder->accountingTransaction);
    }

    public function test_purchase_order_warehouse_returns_null_when_wms_disabled(): void
    {
        if (moduleExists('WMSInventoryCore')) {
            $this->markTestSkipped('WMSInventoryCore is enabled - testing disabled scenario');
        }

        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $purchaseOrder = $this->createCorePurchaseOrder([
            'warehouse_id' => null,
            'created_by_id' => $admin->id,
        ]);

        // Should return null without throwing error
        $this->assertNull($purchaseOrder->warehouse);
    }

    // ==========================================
    // moduleExists Helper Tests
    // ==========================================

    public function test_module_exists_returns_bool(): void
    {
        $result = moduleExists('SystemCore');

        $this->assertIsBool($result);
    }

    public function test_module_exists_for_non_existent_module(): void
    {
        $result = moduleExists('NonExistentModule12345');

        $this->assertFalse($result);
    }

    public function test_module_exists_for_system_core(): void
    {
        // SystemCore should always exist for these tests to run
        if (! moduleExists('SystemCore')) {
            $this->markTestSkipped('SystemCore module is required');
        }

        $result = moduleExists('SystemCore');

        $this->assertTrue($result);
    }

    // ==========================================
    // Relationship Guard Tests
    // ==========================================

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

        // Creating an order without warehouse_id should not throw
        $salesOrder = $this->createCoreSalesOrder([
            'warehouse_id' => null,
            'created_by_id' => $admin->id,
        ]);

        $this->assertNull($salesOrder->warehouse_id);

        // Accessing warehouse relationship should not throw
        $warehouse = $salesOrder->warehouse;
        $this->assertNull($warehouse);
    }

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

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

        $this->assertNull($customer->company_id);
    }

    // ==========================================
    // Conditional Feature Tests
    // ==========================================

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

        // Customer code generation should work regardless of other modules
        $customer = $this->createCoreCustomer(['created_by_id' => $admin->id]);
        $this->assertNotNull($customer->customer_code);

        // Product code generation should work
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);
        $this->assertNotNull($product->product_code);

        // Order number generation should work
        $salesOrder = $this->createCoreSalesOrder(['created_by_id' => $admin->id]);
        $this->assertNotNull($salesOrder->order_number);
    }

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

        $salesOrder = $this->createPaidSalesOrder(['created_by_id' => $admin->id]);

        $this->assertTrue($salesOrder->isFullyPaid());
        $this->assertEquals(0, $salesOrder->remaining_balance);
    }

    // ==========================================
    // Safe Relationship Access Tests
    // ==========================================

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

        // Create order and reload to ensure fresh model behavior
        $salesOrderId = $this->createCoreSalesOrder(['created_by_id' => $admin->id])->id;

        $freshOrder = \Modules\SystemCore\App\Models\CoreSalesOrder::find($salesOrderId);

        // These should not throw even on fresh model
        $freshOrder->customer;
        $freshOrder->user;
        $freshOrder->paymentTerm;
        $freshOrder->warehouse;
        $freshOrder->accountingTransaction;

        $this->assertTrue(true); // If we got here, no exceptions were thrown
    }

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

        $purchaseOrderId = $this->createCorePurchaseOrder(['created_by_id' => $admin->id])->id;

        $freshOrder = \Modules\SystemCore\App\Models\CorePurchaseOrder::find($purchaseOrderId);

        // These should not throw even on fresh model
        $freshOrder->supplier;
        $freshOrder->user;
        $freshOrder->paymentTerm;
        $freshOrder->warehouse;
        $freshOrder->accountingTransaction;

        $this->assertTrue(true);
    }

    // ==========================================
    // TaskSystem Module Graceful Degradation Tests
    // ==========================================

    public function test_crmcore_lead_model_loads_without_task_system(): void
    {
        if (! moduleExists('CRMCore')) {
            $this->markTestSkipped('CRMCore module is required');
        }

        $admin = $this->createAdmin();
        $this->actingAs($admin);

        // Creating a Lead should work regardless of TaskSystem status
        $lead = \Modules\CRMCore\App\Models\Lead::create([
            'title' => 'Test Lead',
            'contact_name' => 'Test Contact',
            'contact_email' => 'test@example.com',
            'created_by_id' => $admin->id,
            'lead_status_id' => \Modules\CRMCore\App\Models\LeadStatus::first()?->id ?? $this->createLeadStatus()->id,
        ]);

        $this->assertNotNull($lead);
        $this->assertEquals('Test Lead', $lead->title);
    }

    public function test_safe_has_tasks_trait_returns_empty_collection_when_task_system_disabled(): void
    {
        if (! moduleExists('CRMCore')) {
            $this->markTestSkipped('CRMCore module is required');
        }

        if (moduleExists('TaskSystem')) {
            $this->markTestSkipped('TaskSystem is enabled - testing disabled scenario');
        }

        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $lead = \Modules\CRMCore\App\Models\Lead::create([
            'title' => 'Test Lead for Tasks',
            'contact_name' => 'Test Contact',
            'created_by_id' => $admin->id,
            'lead_status_id' => \Modules\CRMCore\App\Models\LeadStatus::first()?->id ?? $this->createLeadStatus()->id,
        ]);

        // These should return empty results without throwing errors
        $tasks = $lead->tasks;
        $this->assertCount(0, $tasks);

        $pendingTasks = $lead->pendingTasks;
        $this->assertCount(0, $pendingTasks);

        $completedTasks = $lead->completedTasks;
        $this->assertCount(0, $completedTasks);
    }

    public function test_safe_has_tasks_attributes_return_zero_when_task_system_disabled(): void
    {
        if (! moduleExists('CRMCore')) {
            $this->markTestSkipped('CRMCore module is required');
        }

        if (moduleExists('TaskSystem')) {
            $this->markTestSkipped('TaskSystem is enabled - testing disabled scenario');
        }

        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $lead = \Modules\CRMCore\App\Models\Lead::create([
            'title' => 'Test Lead for Task Counts',
            'contact_name' => 'Test Contact',
            'created_by_id' => $admin->id,
            'lead_status_id' => \Modules\CRMCore\App\Models\LeadStatus::first()?->id ?? $this->createLeadStatus()->id,
        ]);

        // These should return 0/false without throwing errors
        $this->assertEquals(0, $lead->pending_tasks_count);
        $this->assertEquals(0, $lead->completed_tasks_count);
        $this->assertFalse($lead->hasPendingTasks());
        $this->assertFalse($lead->hasOverdueTasks());
    }

    public function test_crmcore_deal_model_works_without_task_system(): void
    {
        if (! moduleExists('CRMCore')) {
            $this->markTestSkipped('CRMCore module is required');
        }

        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $pipeline = \Modules\CRMCore\App\Models\DealPipeline::first() ?? $this->createDealPipeline();
        $stage = \Modules\CRMCore\App\Models\DealStage::where('pipeline_id', $pipeline->id)->first()
            ?? $this->createDealStage($pipeline->id);

        $deal = \Modules\CRMCore\App\Models\Deal::create([
            'title' => 'Test Deal',
            'value' => 1000,
            'pipeline_id' => $pipeline->id,
            'deal_stage_id' => $stage->id,
            'created_by_id' => $admin->id,
        ]);

        $this->assertNotNull($deal);
        $this->assertEquals('Test Deal', $deal->title);

        // tasks() should work without errors
        $tasks = $deal->tasks;
        $this->assertNotNull($tasks);
    }

    public function test_crmcore_company_model_works_without_task_system(): void
    {
        if (! moduleExists('CRMCore')) {
            $this->markTestSkipped('CRMCore module is required');
        }

        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $company = \Modules\CRMCore\App\Models\Company::create([
            'name' => 'Test Company',
            'is_active' => true,
            'created_by_id' => $admin->id,
        ]);

        $this->assertNotNull($company);
        $this->assertEquals('Test Company', $company->name);

        // tasks() should work without errors
        $tasks = $company->tasks;
        $this->assertNotNull($tasks);
    }

    /**
     * Helper to create a LeadStatus for testing
     */
    protected function createLeadStatus(): \Modules\CRMCore\App\Models\LeadStatus
    {
        return \Modules\CRMCore\App\Models\LeadStatus::create([
            'name' => 'Test Status',
            'color' => '#000000',
            'position' => 1,
            'is_default' => true,
        ]);
    }

    /**
     * Helper to create a DealPipeline for testing
     */
    protected function createDealPipeline(): \Modules\CRMCore\App\Models\DealPipeline
    {
        return \Modules\CRMCore\App\Models\DealPipeline::create([
            'name' => 'Test Pipeline',
            'position' => 1,
            'is_default' => true,
        ]);
    }

    /**
     * Helper to create a DealStage for testing
     */
    protected function createDealStage(int $pipelineId): \Modules\CRMCore\App\Models\DealStage
    {
        return \Modules\CRMCore\App\Models\DealStage::create([
            'name' => 'Test Stage',
            'pipeline_id' => $pipelineId,
            'position' => 1,
            'color' => '#000000',
            'is_default_for_pipeline' => true,
        ]);
    }
}
