<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use App\Models\User;
use App\Models\Store;
use App\Models\Menu;
use App\Models\QadSyncLog;

class QadSyncTest extends TestCase
{
    use RefreshDatabase;

    protected $user;

    protected function setUp(): void
    {
        parent::setUp();
        
        // Create test user
        $this->user = User::factory()->create([
            'name' => 'Test User',
            'email' => 'test@example.com',
        ]);
    }

    /** @test */
    public function user_can_access_qad_sync_dashboard()
    {
        $response = $this->actingAs($this->user)
            ->get(route('qad_sync.index'));

        $response->assertStatus(200);
        $response->assertViewIs('qad-sync.index');
        $response->assertSee('QAD Synchronization Dashboard');
    }

    /** @test */
    public function user_can_test_qad_connection()
    {
        $response = $this->actingAs($this->user)
            ->post(route('qad_sync.test_connection'));

        $response->assertStatus(200);
        $response->assertJson([
            'success' => true,
            'message' => 'QAD API connection successful (simulated)',
        ]);
    }

    /** @test */
    public function user_can_sync_stores_from_qad()
    {
        $response = $this->actingAs($this->user)
            ->post(route('qad_sync.sync_stores'));

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'success',
            'message',
            'total_from_qad',
            'inserted',
            'updated',
            'errors',
            'details'
        ]);

        // Check if stores were created
        $this->assertDatabaseHas('m_stores', [
            'name' => 'Bakmi GM Senayan City'
        ]);

        // Check if sync log was created
        $this->assertDatabaseHas('t_qad_sync_logs', [
            'sync_type' => 'stores',
            'triggered_by' => $this->user->id
        ]);
    }

    /** @test */
    public function user_can_sync_menus_from_qad()
    {
        $response = $this->actingAs($this->user)
            ->post(route('qad_sync.sync_menus'));

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'success',
            'message',
            'total_from_qad',
            'inserted',
            'updated',
            'errors',
            'details'
        ]);

        // Check if menus were created
        $this->assertDatabaseHas('m_menus', [
            'name' => 'Bakmi GM Special'
        ]);

        // Check if sync log was created
        $this->assertDatabaseHas('t_qad_sync_logs', [
            'sync_type' => 'menus',
            'triggered_by' => $this->user->id
        ]);
    }

    /** @test */
    public function user_can_sync_all_data_from_qad()
    {
        $response = $this->actingAs($this->user)
            ->post(route('qad_sync.sync_all'));

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'success',
            'stores' => [
                'success',
                'inserted',
                'updated',
                'errors'
            ],
            'menus' => [
                'success',
                'inserted',
                'updated',
                'errors'
            ],
            'summary' => [
                'total_inserted',
                'total_updated',
                'total_errors'
            ]
        ]);

        // Check if both stores and menus were created
        $this->assertDatabaseHas('m_stores', [
            'name' => 'Bakmi GM Senayan City'
        ]);
        
        $this->assertDatabaseHas('m_menus', [
            'name' => 'Bakmi GM Special'
        ]);
    }

    /** @test */
    public function sync_updates_existing_records_instead_of_creating_duplicates()
    {
        // First sync
        $this->actingAs($this->user)
            ->post(route('qad_sync.sync_stores'));

        $initialCount = Store::count();

        // Second sync (should update, not insert)
        $response = $this->actingAs($this->user)
            ->post(route('qad_sync.sync_stores'));

        $response->assertStatus(200);
        
        // Count should remain the same
        $this->assertEquals($initialCount, Store::count());
        
        // Check that update count is greater than 0
        $responseData = $response->json();
        $this->assertGreaterThan(0, $responseData['updated']);
    }

    /** @test */
    public function user_can_get_sync_history()
    {
        // Create some sync logs first
        QadSyncLog::create([
            'sync_type' => 'stores',
            'status' => 'Success',
            'started_at' => now(),
            'completed_at' => now(),
            'total_inserted' => 3,
            'total_updated' => 0,
            'total_errors' => 0,
            'trigger_type' => 'manual',
            'triggered_by' => $this->user->id,
            'created_by' => $this->user->id,
        ]);

        $response = $this->actingAs($this->user)
            ->get(route('qad_sync.sync_history'));

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'success',
            'logs',
            'statistics',
            'total'
        ]);
    }

    /** @test */
    public function user_can_get_sync_statistics()
    {
        $response = $this->actingAs($this->user)
            ->get(route('qad_sync.sync_statistics'));

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'success',
            'statistics' => [
                'total_syncs',
                'successful_syncs',
                'failed_syncs',
                'partial_syncs',
                'avg_duration',
                'total_records_synced'
            ]
        ]);
    }

    /** @test */
    public function sync_creates_proper_audit_trail()
    {
        $this->actingAs($this->user)
            ->post(route('qad_sync.sync_stores'));

        // Check sync log was created with proper details
        $syncLog = QadSyncLog::where('sync_type', 'stores')->first();
        
        $this->assertNotNull($syncLog);
        $this->assertEquals('stores', $syncLog->sync_type);
        $this->assertEquals('Success', $syncLog->status);
        $this->assertEquals($this->user->id, $syncLog->triggered_by);
        $this->assertEquals('manual', $syncLog->trigger_type);
        $this->assertNotNull($syncLog->started_at);
        $this->assertNotNull($syncLog->completed_at);
    }

    /** @test */
    public function qad_code_is_properly_stored_in_description()
    {
        $this->actingAs($this->user)
            ->post(route('qad_sync.sync_stores'));

        $store = Store::where('name', 'Bakmi GM Senayan City')->first();
        
        $this->assertNotNull($store);
        $this->assertStringContains('[QAD:QAD001]', $store->description);
    }

    /** @test */
    public function guest_cannot_access_qad_sync_endpoints()
    {
        $response = $this->get(route('qad_sync.index'));
        $response->assertRedirect(route('login'));

        $response = $this->post(route('qad_sync.sync_stores'));
        $response->assertRedirect(route('login'));
    }

    /** @test */
    public function sync_handles_errors_gracefully()
    {
        // Test that the error structure is properly handled
        $response = $this->actingAs($this->user)
            ->post(route('qad_sync.sync_stores'));

        $response->assertStatus(200);
        
        $responseData = $response->json();
        $this->assertArrayHasKey('errors', $responseData);
        $this->assertIsArray($responseData['errors']);
    }

    /** @test */
    public function sync_logs_include_request_details()
    {
        $this->actingAs($this->user)
            ->post(route('qad_sync.sync_stores'));

        $syncLog = QadSyncLog::where('sync_type', 'stores')->first();
        
        $this->assertNotNull($syncLog);
        $this->assertNotNull($syncLog->request_details);
        $this->assertIsArray($syncLog->request_details);
        
        // Check request details structure
        $this->assertArrayHasKey('method', $syncLog->request_details);
        $this->assertArrayHasKey('url', $syncLog->request_details);
        $this->assertArrayHasKey('headers', $syncLog->request_details);
        $this->assertArrayHasKey('timeout', $syncLog->request_details);
        $this->assertArrayHasKey('timestamp', $syncLog->request_details);
    }

    /** @test */
    public function sync_handles_duplicate_plu_codes_gracefully()
    {
        // First sync to create menus
        $this->actingAs($this->user)
            ->post(route('qad_sync.sync_menus'));

        // Second sync should update existing menus, not fail
        $response = $this->actingAs($this->user)
            ->post(route('qad_sync.sync_menus'));

        $response->assertStatus(200);
        
        $responseData = $response->json();
        $this->assertTrue($responseData['success']);
        $this->assertGreaterThan(0, $responseData['updated']);
        
        // Should not have duplicate PLU codes
        $pluCount = Menu::where('plu_code', 'PLU001')->count();
        $this->assertEquals(1, $pluCount);
    }
}