<?php

namespace Tests\Feature\Jobs;

use App\Models\ImportedJob;
use App\Models\JobSource;
use App\Models\Profile;
use App\Models\QuestionnaireResponse;
use App\Models\ResumeReport;
use App\Models\User;
use App\Services\JobMatchingService;
use App\Services\Settings\SettingsService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class JobMatchingServiceTest extends TestCase
{
    use RefreshDatabase;

    public function test_best_matched_jobs_are_ranked_above_weaker_matches(): void
    {
        app(SettingsService::class)->set('matching', 'show_low_match_jobs', true, 'boolean');

        $user = $this->matchedUser();
        $strongMatch = $this->remoteJob([
            'external_id' => 'strong-match',
            'title' => 'Remote Customer Success Manager',
            'category' => 'support',
            'employment_type' => 'full_time',
            'experience_level' => 'mid',
            'country_code' => 'IN',
            'skills' => ['Customer success', 'CRM', 'Documentation'],
            'posted_at' => now()->subDay(),
        ]);
        $weakMatch = $this->remoteJob([
            'external_id' => 'weak-match',
            'title' => 'Remote Finance Analyst',
            'category' => 'finance',
            'employment_type' => 'contract',
            'experience_level' => 'senior',
            'country_code' => 'US',
            'skills' => ['Accounting'],
            'posted_at' => now(),
        ]);

        $rankedJobs = app(JobMatchingService::class)->rankedJobsFor($user);

        $this->assertSame($strongMatch->id, $rankedJobs->first()->id);
        $this->assertGreaterThan(
            $rankedJobs->firstWhere('id', $weakMatch->id)->match_score,
            $rankedJobs->firstWhere('id', $strongMatch->id)->match_score,
        );
    }

    public function test_low_match_jobs_can_be_hidden_by_admin_matching_settings(): void
    {
        app(SettingsService::class)->set('matching', 'show_low_match_jobs', false, 'boolean');
        app(SettingsService::class)->set('matching', 'minimum_match_score_to_show', 70, 'integer');

        $user = $this->matchedUser();
        $strongMatch = $this->remoteJob([
            'external_id' => 'visible-strong-match',
            'title' => 'Remote Customer Success Manager',
            'category' => 'support',
            'employment_type' => 'full_time',
            'experience_level' => 'mid',
            'country_code' => 'IN',
            'skills' => ['Customer success', 'CRM', 'Documentation'],
            'posted_at' => now()->subDay(),
        ]);
        $weakMatch = $this->remoteJob([
            'external_id' => 'hidden-weak-match',
            'title' => 'Remote Finance Analyst',
            'category' => 'finance',
            'employment_type' => 'contract',
            'experience_level' => 'senior',
            'country_code' => 'US',
            'skills' => ['Accounting'],
            'posted_at' => now(),
        ]);

        $rankedJobs = app(JobMatchingService::class)->rankedJobsFor($user);

        $this->assertTrue($rankedJobs->contains('id', $strongMatch->id));
        $this->assertFalse($rankedJobs->contains('id', $weakMatch->id));
    }

    private function matchedUser(): User
    {
        $user = User::factory()->create();

        QuestionnaireResponse::query()->create([
            'user_id' => $user->id,
            'answers' => ['goal' => 'Find customer success roles'],
            'preferred_categories' => ['support'],
            'preferred_roles' => ['Customer Success Manager'],
            'skills' => ['Customer success', 'CRM'],
            'experience_level' => 'mid',
            'availability' => 'immediate',
            'country_code' => 'IN',
            'salary_currency' => 'INR',
            'open_to_contract' => false,
            'open_to_full_time' => true,
            'completed_at' => now(),
        ]);

        ResumeReport::query()->create([
            'user_id' => $user->id,
            'original_filename' => 'resume.txt',
            'disk' => 'local',
            'path' => 'resumes/'.$user->id.'/resume.txt',
            'mime_type' => 'text/plain',
            'size_bytes' => 4096,
            'status' => ResumeReport::STATUS_COMPLETED,
            'ats_score' => 88,
            'remote_readiness_score' => 84,
            'extracted_skills' => ['Customer success', 'Documentation'],
            'role_suggestions' => ['Customer Success Manager'],
            'analyzed_at' => now(),
        ]);

        Profile::query()->create([
            'user_id' => $user->id,
            'headline' => 'Remote customer success manager',
            'experience_level' => 'mid',
            'country_code' => 'IN',
            'timezone' => 'Asia/Kolkata',
            'skills' => ['Customer success', 'CRM', 'Documentation'],
            'preferred_roles' => ['Customer Success Manager'],
            'preferred_categories' => ['support'],
            'availability' => 'immediate',
            'salary_currency' => 'INR',
            'open_to_contract' => false,
            'open_to_full_time' => true,
            'completed_at' => now(),
        ]);

        return $user;
    }

    /**
     * @param  array<string, mixed>  $overrides
     */
    private function remoteJob(array $overrides): ImportedJob
    {
        $source = JobSource::query()->firstOrCreate([
            'slug' => 'matching-test-source',
        ], [
            'name' => 'Matching Test Source',
            'type' => 'manual',
            'base_url' => 'https://matching-source.example',
            'attribution_text' => 'Source: Matching Test Source',
            'is_active' => true,
        ]);

        return ImportedJob::query()->create(array_replace([
            'job_source_id' => $source->id,
            'company' => 'Distributed Team Co',
            'location_type' => 'remote',
            'summary' => 'Remote-first role.',
            'description' => 'Remote-first role description.',
            'tags' => ['remote'],
            'source_url' => 'https://matching-source.example/jobs/'.($overrides['external_id'] ?? 'job'),
            'apply_url' => 'https://matching-source.example/jobs/'.($overrides['external_id'] ?? 'job').'/apply',
            'source_attribution' => 'Source: Matching Test Source',
            'status' => ImportedJob::STATUS_ACTIVE,
            'last_seen_at' => now(),
        ], $overrides));
    }
}
