<?php

namespace Tests\Feature\Notifications;

use App\Models\ImportedJob;
use App\Models\JobAlertPreference;
use App\Models\JobSource;
use App\Models\Profile;
use App\Models\QuestionnaireResponse;
use App\Models\ResumeReport;
use App\Models\User;
use App\Services\Settings\SettingsService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\URL;
use Tests\TestCase;

class DailyJobAlertTest extends TestCase
{
    use RefreshDatabase;

    public function test_daily_job_alert_sends_new_matched_jobs_without_apply_urls(): void
    {
        Http::fake([
            'https://api.brevo.com/v3/smtp/email' => Http::response(['messageId' => 'daily-alert'], 201),
        ]);

        app(SettingsService::class)->set('email', 'brevo_api_key', 'brevo-secret-key', 'password', encrypted: true);
        app(SettingsService::class)->set('notifications', 'new_matched_jobs_email_enabled', true, 'boolean');

        $user = $this->unlockedUser();
        $job = $this->remoteJob();

        $this
            ->artisan('jobs:send-daily-alerts', ['--user' => $user->email])
            ->assertSuccessful();

        Http::assertSent(fn ($request): bool => $request->url() === 'https://api.brevo.com/v3/smtp/email'
            && $request['to'][0]['email'] === $user->email
            && str_contains((string) $request['htmlContent'], $job->title)
            && str_contains((string) $request['htmlContent'], 'View in dashboard')
            && ! str_contains((string) $request['htmlContent'], $job->apply_url)
            && isset($request['headers']['List-Unsubscribe']));

        $this->assertDatabaseHas('job_alert_email_logs', [
            'user_id' => $user->id,
            'status' => 'sent',
            'job_count' => 1,
        ]);

        $this->assertNotNull($user->jobAlertPreference()->first()?->last_sent_at);
    }

    public function test_signed_unsubscribe_turns_off_job_alerts(): void
    {
        $preference = JobAlertPreference::query()->create([
            'user_id' => User::factory()->create()->id,
            'enabled' => true,
            'frequency' => 'daily',
            'minimum_match_score' => 45,
        ]);

        $response = $this->get(URL::signedRoute('job-alerts.unsubscribe', ['preference' => $preference]));

        $response
            ->assertOk()
            ->assertSeeText('You are unsubscribed.');

        $preference->refresh();

        $this->assertFalse($preference->enabled);
        $this->assertNotNull($preference->unsubscribed_at);
    }

    public function test_first_job_alert_can_include_recent_jobs_older_than_one_day(): void
    {
        Http::fake([
            'https://api.brevo.com/v3/smtp/email' => Http::response(['messageId' => 'first-alert'], 201),
        ]);

        app(SettingsService::class)->set('email', 'brevo_api_key', 'brevo-secret-key', 'password', encrypted: true);
        app(SettingsService::class)->set('notifications', 'new_matched_jobs_email_enabled', true, 'boolean');

        $user = $this->unlockedUser();
        $job = $this->remoteJob([
            'created_at' => now()->subDays(2),
            'posted_at' => now()->subDays(2),
            'last_seen_at' => now()->subDays(2),
        ]);

        $this
            ->artisan('jobs:send-daily-alerts', ['--user' => $user->email])
            ->assertSuccessful();

        $this->assertDatabaseHas('job_alert_email_logs', [
            'user_id' => $user->id,
            'status' => 'sent',
            'job_count' => 1,
        ]);

        Http::assertSent(fn ($request): bool => str_contains((string) $request['htmlContent'], $job->title));
    }

    public function test_dry_run_does_not_update_last_sent_when_no_jobs_match(): void
    {
        app(SettingsService::class)->set('notifications', 'new_matched_jobs_email_enabled', true, 'boolean');

        $user = $this->unlockedUser();
        $this->remoteJob();
        $preference = $user->jobAlertPreference()->create([
            'enabled' => true,
            'frequency' => 'daily',
            'minimum_match_score' => 99,
        ]);

        $this
            ->artisan('jobs:send-daily-alerts', ['--user' => $user->email, '--dry-run' => true])
            ->assertSuccessful();

        $this->assertNull($preference->fresh()->last_sent_at);
        $this->assertDatabaseMissing('job_alert_email_logs', [
            'user_id' => $user->id,
        ]);
    }

    private function unlockedUser(): User
    {
        $user = User::factory()->create([
            'email' => 'daily-alert-user@example.com',
            'questionnaire_completed_at' => now(),
            'access_unlocked_at' => now(),
            'resume_uploaded_at' => now(),
            'resume_analyzed_at' => now(),
            'profile_completed_at' => now(),
        ]);

        QuestionnaireResponse::query()->create([
            'user_id' => $user->id,
            'answers' => [],
            'preferred_categories' => ['design'],
            'preferred_roles' => ['product designer'],
            'skills' => ['Figma', 'UI/UX'],
            'experience_level' => 'mid',
            'salary_currency' => 'USD',
            'salary_min' => 80000,
            'open_to_full_time' => true,
            'completed_at' => now(),
        ]);

        ResumeReport::query()->create([
            'user_id' => $user->id,
            'original_filename' => 'resume.pdf',
            'disk' => 'local',
            'path' => 'resumes/'.$user->id.'/resume.pdf',
            'mime_type' => 'application/pdf',
            'size_bytes' => 1024,
            'status' => ResumeReport::STATUS_COMPLETED,
            'ats_score' => 82,
            'remote_readiness_score' => 90,
            'extracted_skills' => ['Figma', 'UI/UX'],
            'role_suggestions' => ['product designer'],
            'missing_keywords' => [],
            'resume_improvements' => [],
            'analysis' => [],
            'analyzed_at' => now(),
        ]);

        Profile::query()->create([
            'user_id' => $user->id,
            'headline' => 'Remote product designer',
            'summary' => 'Designs SaaS product experiences.',
            'current_role' => 'Product Designer',
            'experience_level' => 'mid',
            'skills' => ['Figma', 'UI/UX'],
            'preferred_roles' => ['product designer'],
            'preferred_categories' => ['design'],
            'salary_currency' => 'USD',
            'salary_min' => 80000,
            'open_to_full_time' => true,
            'completed_at' => now(),
        ]);

        return $user;
    }

    /**
     * @param  array<string, mixed>  $overrides
     */
    private function remoteJob(array $overrides = []): ImportedJob
    {
        $source = JobSource::query()->create([
            'name' => 'Daily Alert Source',
            'slug' => 'daily-alert-source',
            'type' => 'manual',
            'base_url' => 'https://jobs.example',
            'attribution_text' => 'Source: Daily Alert Source',
            'is_active' => true,
        ]);

        return ImportedJob::query()->create(array_replace([
            'job_source_id' => $source->id,
            'external_id' => 'daily-alert-001',
            'title' => 'Senior Product Designer',
            'company' => 'Remote Design Co',
            'category' => 'design',
            'employment_type' => 'full_time',
            'experience_level' => 'mid',
            'location_type' => 'remote',
            'salary_currency' => 'USD',
            'salary_min' => 90000,
            'salary_max' => 120000,
            'summary' => 'Design remote SaaS workflows.',
            'description' => 'Lead UI/UX work for a distributed SaaS product team.',
            'skills' => ['Figma', 'UI/UX'],
            'tags' => ['remote', 'design'],
            'source_url' => 'https://jobs.example/roles/designer',
            'apply_url' => 'https://jobs.example/roles/designer/apply',
            'source_attribution' => 'Source: Daily Alert Source',
            'status' => ImportedJob::STATUS_ACTIVE,
            'posted_at' => now(),
            'last_seen_at' => now(),
        ], $overrides));
    }
}
