<?php

namespace App\Http\Controllers;

use App\Models\Application;
use App\Models\ApplicationFollowUpReminder;
use App\Models\ImportedJob;
use App\Models\JobInterest;
use App\Services\Analytics\EngagementLogger;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rule;

class ApplicationController extends Controller
{
    public function store(Request $request, ImportedJob $job, EngagementLogger $engagementLogger): RedirectResponse
    {
        Gate::authorize('apply', $job);

        $request->user()->applications()->updateOrCreate(
            ['imported_job_id' => $job->id],
            [
                'job_source_id' => $job->job_source_id,
                'source_url' => $job->source_url,
                'apply_url' => $job->apply_url,
                'source_attribution' => $job->attribution(),
                'status' => Application::STATUS_APPLIED,
                'ip_address' => $request->ip(),
                'user_agent' => (string) $request->userAgent(),
                'applied_at' => now(),
            ]
        );
        $request->user()->recordJobInterest($job, JobInterest::SOURCE_APPLIED);
        $engagementLogger->record(
            $request->user(),
            'job_applied',
            'Applied to '.$job->title.'.',
            [
                'imported_job_id' => $job->id,
                'job_source_id' => $job->job_source_id,
            ],
            $job,
        );

        return redirect()->away($job->apply_url);
    }

    public function update(Request $request, Application $application, EngagementLogger $engagementLogger): RedirectResponse
    {
        abort_unless($application->user_id === $request->user()->id, 403);

        $validated = $request->validate([
            'status' => [
                'required',
                'string',
                Rule::in([
                    Application::STATUS_APPLIED,
                    Application::STATUS_INTERVIEW,
                    Application::STATUS_REJECTED,
                    Application::STATUS_OFFER,
                    Application::STATUS_FOLLOW_UP_NEEDED,
                ]),
            ],
            'notes' => ['nullable', 'string', 'max:2000'],
            'follow_up_at' => ['nullable', 'date', 'after_or_equal:today'],
        ]);

        $application->update([
            'status' => $validated['status'],
            'notes' => $validated['notes'] ?? null,
            'follow_up_at' => $validated['follow_up_at'] ?? null,
        ]);

        if (! empty($validated['follow_up_at'])) {
            $application->reminders()
                ->where('status', ApplicationFollowUpReminder::STATUS_PENDING)
                ->whereDate('due_on', '!=', $validated['follow_up_at'])
                ->delete();

            $application->reminders()->updateOrCreate(
                ['due_on' => $validated['follow_up_at']],
                [
                    'user_id' => $application->user_id,
                    'status' => ApplicationFollowUpReminder::STATUS_PENDING,
                    'sent_at' => null,
                    'failure_reason' => null,
                ]
            );
        } else {
            $application->reminders()
                ->where('status', ApplicationFollowUpReminder::STATUS_PENDING)
                ->delete();
        }

        $engagementLogger->record(
            $request->user(),
            'application_tracker_updated',
            'Updated application status to '.str($application->status)->headline().'.',
            [
                'application_id' => $application->id,
                'status' => $application->status,
                'follow_up_at' => $application->follow_up_at?->toDateString(),
            ],
            $application,
        );

        return back()->with('status', 'Application tracker updated.');
    }
}
