<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\Applicant;
use App\Models\JobPosting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
use Symfony\Component\HttpFoundation\StreamedResponse;

class ApplicantController extends Controller
{
    public function index(Request $request)
    {
        $search = trim((string) $request->query('search'));

        $applicants = Applicant::with('jobPosting')
            ->when($search !== '', function ($query) use ($search) {
                $query->where('name', 'like', '%'.$search.'%')
                    ->orWhere('email', 'like', '%'.$search.'%');
            })
            ->latest()
            ->paginate(15)
            ->withQueryString();

        $totalCount = Applicant::count();
        $stageCounts = [
            'applied' => Applicant::where('stage', 'applied')->count(),
            'screening' => Applicant::where('stage', 'screening')->count(),
            'interview' => Applicant::where('stage', 'interview')->count(),
            'offer' => Applicant::where('stage', 'offer')->count(),
            'rejected' => Applicant::where('stage', 'rejected')->count(),
        ];

        return view('recruitment.applicants.index', compact('applicants', 'search', 'totalCount', 'stageCounts'));
    }

    public function refer(Request $request)
    {
        $this->assertReferralEligible();

        $jobPostings = JobPosting::where('status', 'active')->orderBy('title')->get();
        $selectedJobId = (int) $request->query('job_posting_id') ?: null;

        return view('recruitment.applicants.refer', compact('jobPostings', 'selectedJobId'));
    }

    public function storeRefer(Request $request)
    {
        $this->assertReferralEligible();

        $companyId = Auth::user()?->company_id;
        $validated = $request->validate([
            'job_posting_id' => ['required', Rule::exists('job_postings', 'id')->where('company_id', $companyId)],
            'name' => ['required', 'string', 'max:191'],
            'email' => ['nullable', 'email', 'max:191'],
            'phone' => ['nullable', 'string', 'max:50'],
            'notes' => ['nullable', 'string', 'max:2000'],
            'resume' => ['nullable', 'file', 'mimes:pdf,doc,docx', 'max:5120'],
        ]);

        $resumePath = null;
        if ($request->hasFile('resume')) {
            $resumePath = $request->file('resume')->store('resumes/'.$companyId, 'public');
        }

        Applicant::create([
            'company_id' => $companyId,
            'job_posting_id' => $validated['job_posting_id'],
            'referred_by_user_id' => Auth::id(),
            'name' => $validated['name'],
            'email' => $validated['email'] ?? null,
            'phone' => $validated['phone'] ?? null,
            'stage' => 'applied',
            'applied_at' => now()->toDateString(),
            'notes' => $validated['notes'] ?? null,
            'resume_path' => $resumePath,
        ]);

        return redirect()->route('applicants.refer')->with('success', 'Referral submitted successfully. HR will review the candidate.');
    }

    public function create()
    {
        $jobPostings = JobPosting::where('status', 'active')->orderBy('title')->get();

        return view('recruitment.applicants.create', compact('jobPostings'));
    }

    public function store(Request $request)
    {
        $companyId = Auth::user()?->company_id;
        $validated = $request->validate([
            'job_posting_id' => ['nullable', 'exists:job_postings,id'],
            'name' => ['required', 'string', 'max:191'],
            'email' => ['nullable', 'email', 'max:191'],
            'phone' => ['nullable', 'string', 'max:50'],
            'stage' => ['required', Rule::in(['applied', 'screening', 'interview', 'offer', 'rejected'])],
            'rating' => ['nullable', 'numeric', 'min:0', 'max:5'],
            'applied_at' => ['nullable', 'date'],
            'notes' => ['nullable', 'string'],
            'resume' => ['nullable', 'file', 'mimes:pdf,doc,docx', 'max:5120'],
        ]);

        $resumePath = null;
        if ($request->hasFile('resume')) {
            $resumePath = $request->file('resume')->store('resumes/'.$companyId, 'public');
        }

        $data = collect($validated)->except(['resume'])->merge([
            'company_id' => $companyId,
            'resume_path' => $resumePath,
        ])->all();

        Applicant::create($data);

        return redirect()->route('applicants.index')->with('success', 'Applicant added successfully.');
    }

    public function show(Applicant $applicant)
    {
        $applicant->load(['jobPosting', 'interviews.interviewer', 'referredBy']);

        return view('recruitment.applicants.show', compact('applicant'));
    }

    public function edit(Applicant $applicant)
    {
        $jobPostings = JobPosting::orderBy('title')->get();

        return view('recruitment.applicants.edit', compact('applicant', 'jobPostings'));
    }

    public function update(Request $request, Applicant $applicant)
    {
        $companyId = Auth::user()?->company_id;
        $validated = $request->validate([
            'job_posting_id' => ['nullable', Rule::exists('job_postings', 'id')->where('company_id', $companyId)],
            'name' => ['required', 'string', 'max:191'],
            'email' => ['nullable', 'email', 'max:191'],
            'phone' => ['nullable', 'string', 'max:50'],
            'stage' => ['required', Rule::in(['applied', 'screening', 'interview', 'offer', 'rejected'])],
            'rating' => ['nullable', 'numeric', 'min:0', 'max:5'],
            'applied_at' => ['nullable', 'date'],
            'notes' => ['nullable', 'string'],
            'resume' => ['nullable', 'file', 'mimes:pdf,doc,docx', 'max:5120'],
        ]);

        $data = collect($validated)->except(['resume'])->all();

        if ($request->hasFile('resume')) {
            if ($applicant->resume_path && Storage::disk('public')->exists($applicant->resume_path)) {
                Storage::disk('public')->delete($applicant->resume_path);
            }
            $data['resume_path'] = $request->file('resume')->store('resumes/'.Auth::user()?->company_id, 'public');
        }

        $applicant->update($data);

        return redirect()->route('applicants.index')->with('success', 'Applicant updated successfully.');
    }

    public function destroy(Applicant $applicant)
    {
        if ($applicant->resume_path && Storage::disk('public')->exists($applicant->resume_path)) {
            Storage::disk('public')->delete($applicant->resume_path);
        }
        $applicant->delete();

        return redirect()->route('applicants.index')->with('success', 'Applicant deleted successfully.');
    }

    public function downloadResume(Applicant $applicant): StreamedResponse
    {
        if (! $applicant->resume_path || ! Storage::disk('public')->exists($applicant->resume_path)) {
            abort(404);
        }

        return Storage::disk('public')->download(
            $applicant->resume_path,
            basename($applicant->resume_path)
        );
    }

    private function assertReferralEligible(): void
    {
        $user = Auth::user();
        if (! $user || ! $user->isWorkforceMember()) {
            abort(403, 'Only employees can submit referrals.');
        }
        if (! $user->hasPermission('recruitment_refer')) {
            abort(403, 'You do not have permission to submit referrals.');
        }
    }
}
