<?php

namespace Tests\Feature;

use App\Models\Worker;
use App\Models\WorkerCategory;
use App\Models\WorkerDocument;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class WorkerJourneyApiTest extends TestCase
{
    use RefreshDatabase;

    protected $category;

    protected function setUp(): void
    {
        parent::setUp();

        // Create standard General Helper category
        \Illuminate\Support\Facades\DB::table('worker_categories')->insert([
            'id' => 7,
            'name' => 'General Helper',
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        $this->category = (object) ['id' => 7];
    }

    /**
     * Test S1 Onboard: Get Config and Supported Languages.
     */
    public function test_s1_get_languages_config()
    {
        $response = $this->getJson('/api/workers/config');

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'languages' => [
                    ['code' => 'HI', 'name' => 'Hindi (हिन्दी)'],
                    ['code' => 'SW', 'name' => 'Swahili (Kiswahili)'],
                    ['code' => 'TL', 'name' => 'Tagalog (Wikang Tagalog)'],
                    ['code' => 'TA', 'name' => 'Tamil (தமிழ்)'],
                ]
            ]);
    }

    /**
     * Test Get Skills Master API.
     */
    public function test_get_skills_master_api()
    {
        // Seed some master skills
        \Illuminate\Support\Facades\DB::table('skills')->insert([
            ['name' => 'Cooking', 'created_at' => now(), 'updated_at' => now()],
            ['name' => 'Cleaning', 'created_at' => now(), 'updated_at' => now()],
        ]);

        $response = $this->getJson('/api/workers/skills');

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
            ])
            ->assertJsonStructure([
                'success',
                'skills' => [
                    '*' => ['id', 'name']
                ]
            ]);
    }

    /**
     * Test S1 Onboard: Send and Verify OTP.
     */
    public function test_s1_otp_flow()
    {
        $phone = '+971501234567';

        // 1. Send OTP
        $sendResponse = $this->postJson('/api/workers/send-otp', [
            'phone' => $phone,
        ]);

        $sendResponse->assertStatus(200)
            ->assertJson([
                'success' => true,
                'identifier' => $phone,
            ]);

        // Verify OTP is stored in cache
        $cached = Cache::get('worker_otp_' . $phone);
        $this->assertNotNull($cached);
        $this->assertEquals('111111', $cached['code']); // Dev default OTP

        // 2. Verify OTP
        $verifyResponse = $this->postJson('/api/workers/verify-otp', [
            'phone' => $phone,
            'otp' => '111111',
        ]);

        $verifyResponse->assertStatus(200)
            ->assertJson([
                'success' => true,
                'identifier' => $phone,
            ]);

        // Verify the gate cache is present
        $this->assertTrue(Cache::get('worker_otp_verified_' . $phone));
    }

    /**
     * Test S1 Onboard: Complete Basic Profile Setup.
     */
    public function test_s1_complete_basic_profile_setup()
    {
        $phone = '+971501234567';

        // Bypass OTP by seeding the cache gate
        Cache::put('worker_otp_verified_' . $phone, true, 3600);

        $response = $this->postJson('/api/workers/setup-profile', [
            'phone' => $phone,
            'name' => 'Rahul Sharma',
            'nationality' => 'India',
            'language' => 'HI',
            'gender' => 'male',
            'skills' => [],
        ]);

        $response->assertStatus(201)
            ->assertJsonStructure([
                'success',
                'message',
                'data' => [
                    'worker' => [
                        'id',
                        'name',
                        'email',
                        'phone',
                        'language',
                        'verified',
                        'status',
                    ],
                    'token',
                ]
            ]);

        $this->assertDatabaseHas('workers', [
            'name' => 'Rahul Sharma',
            'phone' => $phone,
            'language' => 'HI',
            'gender' => 'male',
            'verified' => false,
            'status' => 'active',
        ]);

        // Gate cache should be purged
        $this->assertNull(Cache::get('worker_otp_verified_' . $phone));
    }

    /**
     * Test S2 Profile: Add Experience & Preferences.
     */
    public function test_s2_update_experience_and_preferences()
    {
        $worker = Worker::create([
            'name' => 'John Swahili',
            'email' => 'john@example.com',
            'phone' => '+971509999999',
            'language' => 'SW',
            'password' => bcrypt('password'),
            'nationality' => 'Kenya',
            'age' => 22,
            'salary' => 1200,
            'availability' => 'Immediate',
            'experience' => 'None',
            'religion' => 'Christian',
            'bio' => 'New helper',
            'category_id' => $this->category->id,
            'verified' => false,
            'status' => 'active',
            'api_token' => 'test-bearer-token-123',
        ]);

        $response = $this->withHeaders([
            'Authorization' => 'Bearer test-bearer-token-123',
        ])->postJson('/api/workers/profile/update', [
                    'experience' => '3 Years Cooking & Childcare',
                    'salary' => 1800,
                    'bio' => 'Extremely experienced in Arabic and Western cooking.',
                ]);

        $response->assertStatus(200);

        $this->assertDatabaseHas('workers', [
            'id' => $worker->id,
            'experience' => '3 Years Cooking & Childcare',
            'salary' => 1800,
        ]);
    }

    /**
     * Test S2 Profile: Upload Emirates ID & PDPL Security Purge & Verified Badge Awarded.
     */
    public function test_s2_upload_emirates_id_and_pdpl_secure_purge()
    {
        Storage::fake('local');

        $worker = Worker::create([
            'name' => 'Juan Dela Cruz',
            'email' => 'juan@example.com',
            'phone' => '+971507777777',
            'language' => 'TL',
            'password' => bcrypt('password'),
            'nationality' => 'Philippines',
            'age' => 28,
            'salary' => 1500,
            'availability' => 'Immediate',
            'experience' => 'Not Specified',
            'religion' => 'Not Specified',
            'bio' => 'Looking for helper job',
            'category_id' => $this->category->id,
            'verified' => false,
            'status' => 'active',
            'api_token' => 'test-bearer-token-456',
        ]);

        $fakeIdFile = UploadedFile::fake()->create('emirates_id.jpg', 800, 'image/jpeg');

        $response = $this->withHeaders([
            'Authorization' => 'Bearer test-bearer-token-456',
        ])->postJson('/api/workers/profile/upload-emirates-id', [
                    'emirates_id_file' => $fakeIdFile,
                ]);

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'message',
                'ocr_extracted_data' => [
                    'name',
                    'emirates_id_number',
                    'expiry_date',
                ],
                'data' => [
                    'worker',
                    'document',
                ]
            ]);

        // Asserts database states
        $this->assertDatabaseHas('workers', [
            'id' => $worker->id,
            'verified' => true, // Badge awarded!
        ]);

        $this->assertDatabaseHas('worker_documents', [
            'worker_id' => $worker->id,
            'type' => 'emirates_id',
            'file_path' => '[DELETED_FOR_PDPL_COMPLIANCE]', // Image file removed for PDPL
        ]);

        // Ensure physical file is deleted and not stored in storage disk
        Storage::disk('local')->assertDirectoryEmpty('temp/documents');
    }

    /**
     * Test S3 Go Live: Status set to Active.
     */
    public function test_s3_go_live()
    {
        $worker = Worker::create([
            'name' => 'Selvi Tamil',
            'email' => 'selvi@example.com',
            'phone' => '+971508888888',
            'language' => 'TA',
            'password' => bcrypt('password'),
            'nationality' => 'Sri Lanka',
            'age' => 32,
            'salary' => 1400,
            'availability' => 'Not Available',
            'experience' => 'Not Specified',
            'religion' => 'Not Specified',
            'bio' => 'Ready to work',
            'category_id' => $this->category->id,
            'verified' => true,
            'status' => 'inactive',
            'api_token' => 'test-bearer-token-789',
        ]);

        $response = $this->withHeaders([
            'Authorization' => 'Bearer test-bearer-token-789',
        ])->postJson('/api/workers/go-live');

        $response->assertStatus(200)
            ->assertJsonPath('data.worker.status', 'active')
            ->assertJsonPath('data.worker.availability', 'Immediate');

        $this->assertDatabaseHas('workers', [
            'id' => $worker->id,
            'status' => 'active',
            'availability' => 'Immediate',
        ]);
    }

    /**
     * Test S5 Avail?: Toggle availability (Still looking?).
     */
    public function test_s5_toggle_availability_still_looking()
    {
        $worker = Worker::create([
            'name' => 'Rahul Sharma',
            'email' => 'rahul@example.com',
            'phone' => '+971501234567',
            'language' => 'HI',
            'password' => bcrypt('password'),
            'nationality' => 'India',
            'age' => 25,
            'salary' => 1500,
            'availability' => 'Immediate',
            'experience' => 'Not Specified',
            'religion' => 'Not Specified',
            'bio' => 'Test',
            'category_id' => $this->category->id,
            'verified' => true,
            'status' => 'active',
            'api_token' => 'test-bearer-token-abc',
        ]);

        // Toggle still_looking = false (NO -> Hidden)
        $response1 = $this->withHeaders([
            'Authorization' => 'Bearer test-bearer-token-abc',
        ])->postJson('/api/workers/profile/toggle-availability', [
                    'still_looking' => false,
                ]);

        $response1->assertStatus(200)
            ->assertJson([
                'success' => true,
                'still_looking' => false,
                'status' => 'hidden',
            ]);

        $this->assertDatabaseHas('workers', [
            'id' => $worker->id,
            'status' => 'hidden',
        ]);

        // Toggle still_looking = true (YES -> Visible/Active)
        $response2 = $this->withHeaders([
            'Authorization' => 'Bearer test-bearer-token-abc',
        ])->postJson('/api/workers/profile/toggle-availability', [
                    'still_looking' => true,
                ]);

        $response2->assertStatus(200)
            ->assertJson([
                'success' => true,
                'still_looking' => true,
                'status' => 'active',
            ]);

        $this->assertDatabaseHas('workers', [
            'id' => $worker->id,
            'status' => 'active',
        ]);
    }

    /**
     * Test S6 Outcome: Marked as Hired (Profile removed from search - auto-hidden).
     */
    public function test_s6_outcome_mark_hired()
    {
        $worker = Worker::create([
            'name' => 'Rahul Sharma',
            'email' => 'rahul@example.com',
            'phone' => '+971501234567',
            'language' => 'HI',
            'password' => bcrypt('password'),
            'nationality' => 'India',
            'age' => 25,
            'salary' => 1500,
            'availability' => 'Immediate',
            'experience' => 'Not Specified',
            'religion' => 'Not Specified',
            'bio' => 'Test',
            'category_id' => $this->category->id,
            'verified' => true,
            'status' => 'active',
            'api_token' => 'test-bearer-token-abc',
        ]);

        $response = $this->withHeaders([
            'Authorization' => 'Bearer test-bearer-token-abc',
        ])->postJson('/api/workers/profile/mark-hired');

        $response->assertStatus(200)
            ->assertJsonPath('data.worker.status', 'Hired');

        $this->assertDatabaseHas('workers', [
            'id' => $worker->id,
            'status' => 'Hired',
        ]);
    }

    /**
     * Test registration with new API fields.
     */
    public function test_register_with_new_api_fields()
    {
        $fakePassport = UploadedFile::fake()->create('passport.pdf', 500, 'application/pdf');

        $response = $this->postJson('/api/workers/register', [
            'name'               => 'John New Worker',
            'phone'              => '+971501111112',
            'salary'             => 2200.50,
            'password'           => 'secret123',
            'passport_file'      => $fakePassport,
            'language'           => 'HI',
            'nationality'        => 'Kenya',
            'age'                => 30,
            'experience'         => '5 Years',
            'in_country'         => 'true',
            'visa_status'        => 'Tourist Visa',
            'preferred_job_type' => 'full-time',
            'gender'             => 'male',
            'live_in_out'        => 'live_out',
            'preferred_location' => 'Dubai Marina',
        ]);

        $response->assertStatus(201);

        $this->assertDatabaseHas('workers', [
            'name'               => 'John New Worker',
            'phone'              => '+971501111112',
            'in_country'         => true,
            'visa_status'        => 'Tourist Visa',
            'preferred_job_type' => 'full-time',
            'gender'             => 'male',
            'live_in_out'        => 'live_out',
            'preferred_location' => 'Dubai Marina',
        ]);
    }

    /**
     * Test updating profile with new API fields.
     */
    public function test_update_profile_with_new_api_fields()
    {
        $worker = Worker::create([
            'name'         => 'Original Worker',
            'email'        => 'orig@example.com',
            'phone'        => '+971502222223',
            'language'     => 'SW',
            'password'     => bcrypt('password'),
            'nationality'  => 'Kenya',
            'age'          => 22,
            'salary'       => 1200,
            'availability' => 'Immediate',
            'experience'   => 'None',
            'religion'     => 'Christian',
            'bio'          => 'New helper',
            'category_id'  => $this->category->id,
            'verified'     => false,
            'status'       => 'active',
            'api_token'    => 'bearer-update-token',
        ]);

        $response = $this->withHeaders([
            'Authorization' => 'Bearer bearer-update-token',
        ])->postJson('/api/workers/profile/update', [
            'in_country'         => false,
            'visa_status'        => null,
            'preferred_job_type' => 'part-time',
            'gender'             => 'female',
            'live_in_out'        => 'live_in',
            'preferred_location' => 'Abu Dhabi',
            'country'            => 'UAE',
            'city'               => 'Abu Dhabi',
            'area'               => 'Khalifa City',
        ]);

        $response->assertStatus(200);

        $this->assertDatabaseHas('workers', [
            'id'                 => $worker->id,
            'in_country'         => false,
            'visa_status'        => null,
            'preferred_job_type' => 'part-time',
            'gender'             => 'female',
            'live_in_out'        => 'live_in',
            'preferred_location' => 'Abu Dhabi',
            'country'            => 'UAE',
            'city'               => 'Abu Dhabi',
            'area'               => 'Khalifa City',
        ]);
    }

    /**
     * Test nationalities list API with translations.
     */
    public function test_nationalities_list_api()
    {
        // 1. Default (English)
        $responseEn = $this->getJson('/api/nationalities?per_page=200');
        $responseEn->assertStatus(200)
            ->assertJson([
                'success' => true,
            ])
            ->assertJsonFragment([
                'code' => 'IN',
                'name' => 'Indian',
            ])
            ->assertJsonFragment([
                'code' => 'PH',
                'name' => 'Filipino',
            ]);

        // 2. Hindi
        $responseHi = $this->getJson('/api/nationalities?lang=hindi&per_page=200');
        $responseHi->assertStatus(200)
            ->assertJsonFragment([
                'code' => 'IN',
                'name' => 'भारतीय',
            ]);

        // 3. Swahili via header
        $responseSw = $this->withHeaders([
            'Accept-Language' => 'sw',
        ])->getJson('/api/nationalities?per_page=200');
        $responseSw->assertStatus(200)
            ->assertJsonFragment([
                'code' => 'IN',
                'name' => 'Kihindi',
            ]);

        // 4. Tagalog (taglo)
        $responseTl = $this->getJson('/api/nationalities?lang=taglo&per_page=200');
        $responseTl->assertStatus(200)
            ->assertJsonFragment([
                'code' => 'IN',
                'name' => 'Kano/Indian',
            ]);

        // 5. Tamil
        $responseTa = $this->getJson('/api/nationalities?lang=tamil&per_page=200');
        $responseTa->assertStatus(200)
            ->assertJsonFragment([
                'code' => 'IN',
                'name' => 'இந்தியன்',
            ]);

        // 6. Test Pagination structure
        $this->flushHeaders();
        $responsePaginated = $this->getJson('/api/nationalities?page=2&per_page=5');
        $responsePaginated->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'data' => [
                    'nationalities',
                    'pagination' => [
                        'total',
                        'per_page',
                        'current_page',
                        'last_page'
                    ]
                ]
            ]);
        
        $this->assertCount(5, $responsePaginated->json('data.nationalities'));
        $this->assertEquals(2, $responsePaginated->json('data.pagination.current_page'));

        // 7. Test Search functionality
        $this->flushHeaders();
        $responseSearch = $this->getJson('/api/nationalities?search=Indian');
        $responseSearch->assertStatus(200);
        $this->assertGreaterThanOrEqual(1, count($responseSearch->json('data.nationalities')));
        $responseSearch->assertJsonFragment([
            'code' => 'IN',
            'name' => 'Indian'
        ]);
    }

    /**
     * Test worker dashboard stats including employer_contacted and profile_viewed unique counts.
     */
    public function test_worker_dashboard_stats()
    {
        // 1. Create a worker
        $worker = Worker::create([
            'name'         => 'Rahul Sharma',
            'email'        => 'rahul@example.com',
            'phone'        => '+971501234567',
            'language'     => 'HI',
            'password'     => bcrypt('password'),
            'nationality'  => 'India',
            'age'          => 25,
            'salary'       => 1500,
            'availability' => 'Immediate',
            'experience'   => 'Not Specified',
            'religion'     => 'Not Specified',
            'bio'          => 'Test',
            'category_id'  => $this->category->id,
            'verified'     => true,
            'status'       => 'active',
            'api_token'    => 'worker-test-token-dashboard',
        ]);

        // Create passport document to prevent "Passport Pending" 404
        WorkerDocument::create([
            'worker_id' => $worker->id,
            'type' => 'passport',
            'number' => '123456',
            'file_path' => 'passports/test.pdf',
        ]);

        // 2. Create two employers
        $employer1 = \App\Models\User::create([
            'name' => 'Employer One',
            'email' => 'emp1@example.com',
            'password' => bcrypt('password'),
            'role' => 'employer',
            'api_token' => 'emp1-token',
        ]);

        $employer2 = \App\Models\User::create([
            'name' => 'Employer Two',
            'email' => 'emp2@example.com',
            'password' => bcrypt('password'),
            'role' => 'employer',
            'api_token' => 'emp2-token',
        ]);

        // 3. Employer 1 views worker\'s profile twice (should count as 1)
        $response = $this->withHeaders([
            'Authorization' => 'Bearer emp1-token',
        ])->getJson('/api/employers/workers/' . $worker->id);
        $response->assertStatus(200);

        $response = $this->withHeaders([
            'Authorization' => 'Bearer emp1-token',
        ])->getJson('/api/employers/workers/' . $worker->id);
        $response->assertStatus(200);

        // 4. Employer 2 views worker\'s profile once
        $response = $this->withHeaders([
            'Authorization' => 'Bearer emp2-token',
        ])->getJson('/api/employers/workers/' . $worker->id);
        $response->assertStatus(200);

        // Assert profile_views database has 2 unique views
        $this->assertEquals(2, \App\Models\ProfileView::where('worker_id', $worker->id)->count());

        // 5. Create a conversation (contact) from Employer 1
        \App\Models\Conversation::create([
            'employer_id' => $employer1->id,
            'worker_id' => $worker->id,
        ]);

        // 6. Hit the worker dashboard API
        $dashboardResponse = $this->withHeaders([
            'Authorization' => 'Bearer worker-test-token-dashboard',
        ])->getJson('/api/workers/dashboard');

        $dashboardResponse->assertStatus(200)
            ->assertJson([
                'success' => true,
                'data' => [
                    'active_status' => 'active',
                    'profile_viewed' => 2,
                    'employer_contacted' => 1,
                ]
            ]);
    }
}
