<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\Applicant;
use App\Models\Company;
use App\Models\JobPosting;
use App\Services\Recruitment\ApplicantStageService;
use App\Services\Recruitment\ReferralDuplicateService;
use App\Services\Recruitment\RecruitmentSlaService;
use App\Support\EmployeeValidation;
use App\Support\FormTextRules;
use App\Support\ResolvesPrivateUploads;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class CareersController extends Controller
{
    use ResolvesPrivateUploads;

    public function __construct(
        protected ApplicantStageService $stageService,
        protected ReferralDuplicateService $duplicates,
        protected RecruitmentSlaService $sla
    ) {}

    public function index(string $companyKey)
    {
        $company = $this->resolveCompany($companyKey);
        $jobs = JobPosting::query()
            ->with('department')
            ->where('company_id', $company->id)
            ->where('status', 'active')
            ->orderByDesc('posted_at')
            ->get();

        return view('careers.index', compact('company', 'jobs', 'companyKey'));
    }

    public function show(string $companyKey, JobPosting $jobPosting)
    {
        $company = $this->resolveCompany($companyKey);
        abort_unless((int) $jobPosting->company_id === (int) $company->id && $jobPosting->status === 'active', 404);

        return view('careers.apply', compact('company', 'jobPosting', 'companyKey'));
    }

    public function apply(Request $request, string $companyKey)
    {
        $company = $this->resolveCompany($companyKey);

        $request->merge(EmployeeValidation::normalize($request->only(['email', 'phone'])));

        $validated = $request->validate([
            'job_posting_id' => ['required', Rule::exists('job_postings', 'id')->where('company_id', $company->id)],
            'name' => ['required', 'string', 'max:191', 'regex:'.EmployeeValidation::ALPHA_SPACES],
            'email' => ['required', 'email', 'max:191'],
            'phone' => ['nullable', 'digits:10'],
            'notes' => FormTextRules::notNumericOnly(false, 2000),
            'resume' => ['required', 'file', 'mimes:pdf,doc,docx', 'max:5120'],
        ], array_merge(FormTextRules::messages(), [
            'name.regex' => EmployeeValidation::messages()['name.regex'],
            'phone.digits' => EmployeeValidation::messages()['phone.digits'],
        ]));

        if ($this->duplicates->isDuplicate((int) $company->id, (int) $validated['job_posting_id'], $validated['email'])) {
            return back()->withInput()->withErrors([
                'email' => 'You already have an active application for this role.',
            ]);
        }

        $resumePath = $request->file('resume')->store('resumes/'.$company->id, $this->privateUploadDisk());

        $appliedAt = now();
        $applicant = Applicant::create([
            'company_id' => $company->id,
            'job_posting_id' => $validated['job_posting_id'],
            'source' => 'careers',
            'name' => $validated['name'],
            'email' => $validated['email'],
            'phone' => $validated['phone'] ?? null,
            'stage' => 'applied',
            'applied_at' => $appliedAt->toDateString(),
            'sla_due_at' => $this->sla->dueAtForNewApplicant($appliedAt),
            'notes' => $validated['notes'] ?? null,
            'resume_path' => $resumePath,
        ]);

        $this->stageService->recordInitial($applicant, null);

        return redirect()
            ->route('careers.index', $companyKey)
            ->with('success', 'Thank you! Your application has been submitted. Our HR team will contact you if your profile is shortlisted.');
    }

    protected function resolveCompany(string $companyKey): Company
    {
        if (ctype_digit($companyKey)) {
            return Company::query()->where('status', 'active')->findOrFail((int) $companyKey);
        }

        $company = Company::findByShortName($companyKey);
        if ($company && $company->status === 'active') {
            return $company;
        }

        $key = strtolower($companyKey);

        return Company::query()
            ->where('status', 'active')
            ->whereRaw('LOWER(name) = ?', [$key])
            ->firstOrFail();
    }
}
