<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\Applicant;
use App\Models\Interview;
use App\Models\JobPosting;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;

class RecruitmentDashboardController extends Controller
{
    public function index(Request $request)
    {
        $companyId = (int) ($request->user()?->company_id ?? 0);
        $now = Carbon::now();

        if ($companyId <= 0) {
            return view('recruitment.dashboard', $this->emptyPayload());
        }

        $monthStart = $now->copy()->startOfMonth()->startOfDay();
        $monthEnd = $now->copy()->endOfDay();

        $activeJobPostings = JobPosting::query()->where('status', 'active')->count();

        $applicantsMtd = Applicant::query()
            ->where(function ($q) use ($monthStart, $monthEnd) {
                $q->whereBetween('applied_at', [$monthStart->toDateString(), $monthEnd->toDateString()])
                    ->orWhere(function ($q2) use ($monthStart, $monthEnd) {
                        $q2->whereNull('applied_at')
                            ->whereBetween('created_at', [$monthStart, $monthEnd]);
                    });
            })
            ->count();

        $referralsMtd = Applicant::query()
            ->whereNotNull('referred_by_user_id')
            ->where(function ($q) use ($monthStart, $monthEnd) {
                $q->whereBetween('applied_at', [$monthStart->toDateString(), $monthEnd->toDateString()])
                    ->orWhere(function ($q2) use ($monthStart, $monthEnd) {
                        $q2->whereNull('applied_at')
                            ->whereBetween('created_at', [$monthStart, $monthEnd]);
                    });
            })
            ->count();

        $offersMtd = Applicant::query()
            ->where('stage', 'offer')
            ->whereBetween('updated_at', [$monthStart, $monthEnd])
            ->count();

        $pipeline = Applicant::query()
            ->selectRaw('stage, COUNT(*) as total')
            ->groupBy('stage')
            ->pluck('total', 'stage')
            ->toArray();

        $pipelineLabels = ['Applied', 'Screening', 'Interview', 'Offer', 'Rejected'];
        $pipelineKeys = ['applied', 'screening', 'interview', 'offer', 'rejected'];
        $pipelineCounts = [];
        foreach ($pipelineKeys as $key) {
            $pipelineCounts[] = (int) ($pipeline[$key] ?? 0);
        }

        $today = $now->toDateString();
        $interviewsToday = Interview::query()
            ->whereDate('scheduled_at', $today)
            ->where('status', 'scheduled')
            ->count();

        $upcomingInterviewCount = Interview::query()
            ->where('status', 'scheduled')
            ->whereBetween('scheduled_at', [$now->copy()->startOfDay(), $now->copy()->addDays(7)->endOfDay()])
            ->count();

        $completedInterviewsMtd = Interview::query()
            ->where('status', 'completed')
            ->whereBetween('scheduled_at', [$monthStart, $monthEnd])
            ->count();

        $followUpsOverdue = Interview::query()
            ->where('status', 'scheduled')
            ->whereNotNull('follow_up_at')
            ->where('follow_up_at', '<=', $now)
            ->count();

        $applicantsByMonth = $this->applicantsLastSixMonthsSeries($now);
        $interviewWeekSeries = $this->interviewWeeklySeries($now);

        $recentActivity = $this->buildRecentActivity();

        return view('recruitment.dashboard', [
            'kpis' => [
                'active_job_postings' => $activeJobPostings,
                'applicants_mtd' => $applicantsMtd,
                'referrals_mtd' => $referralsMtd,
                'interviews_today' => $interviewsToday,
                'upcoming_7d' => $upcomingInterviewCount,
                'completed_interviews_mtd' => $completedInterviewsMtd,
                'offers_mtd' => $offersMtd,
                'follow_ups_overdue' => $followUpsOverdue,
            ],
            'chartPipeline' => [
                'labels' => $pipelineLabels,
                'data' => $pipelineCounts,
            ],
            'chartApplicantsTrend' => $applicantsByMonth,
            'chartInterviewThroughput' => $interviewWeekSeries,
            'recentActivity' => $recentActivity,
            'followUpPreview' => Interview::query()
                ->with(['applicant:id,name', 'applicant.jobPosting:id,title'])
                ->where('status', 'scheduled')
                ->whereNotNull('follow_up_at')
                ->orderBy('follow_up_at')
                ->limit(8)
                ->get(),
        ]);
    }

    /**
     * @return array{labels: array<int, string>, applicants: array<int, int>}
     */
    private function applicantsLastSixMonthsSeries(Carbon $now): array
    {
        $labels = [];
        $data = [];
        for ($i = 5; $i >= 0; $i--) {
            $d = $now->copy()->subMonths($i);
            $labels[] = $d->format('M Y');
            $data[] = (int) Applicant::query()
                ->where(function ($q) use ($d) {
                    $q->whereYear('applied_at', $d->year)
                        ->whereMonth('applied_at', $d->month)
                        ->orWhere(function ($q2) use ($d) {
                            $q2->whereNull('applied_at')
                                ->whereYear('created_at', $d->year)
                                ->whereMonth('created_at', $d->month);
                        });
                })
                ->count();
        }

        return ['labels' => $labels, 'applicants' => $data];
    }

    /**
     * @return array{labels: array<int, string>, completed: array<int, int>, scheduled: array<int, int>}
     */
    private function interviewWeeklySeries(Carbon $now): array
    {
        $labels = [];
        $completed = [];
        $scheduled = [];
        for ($i = 5; $i >= 0; $i--) {
            $weekStart = $now->copy()->subWeeks($i)->startOfWeek();
            $weekEnd = $weekStart->copy()->endOfWeek();
            $labels[] = $weekStart->format('M j');
            $completed[] = (int) Interview::query()
                ->where('status', 'completed')
                ->whereBetween('scheduled_at', [$weekStart, $weekEnd])
                ->count();
            $scheduled[] = (int) Interview::query()
                ->where('status', 'scheduled')
                ->whereBetween('scheduled_at', [$weekStart, $weekEnd])
                ->count();
        }

        return [
            'labels' => $labels,
            'completed' => $completed,
            'scheduled' => $scheduled,
        ];
    }

    private function buildRecentActivity(): Collection
    {
        $applicants = Applicant::query()
            ->with('jobPosting:id,title')
            ->orderByDesc('created_at')
            ->limit(10)
            ->get()
            ->map(function (Applicant $a) {
                return [
                    'type' => 'Applicant',
                    'label' => $a->name,
                    'detail' => $a->jobPosting?->title ?? '—',
                    'meta' => ucfirst($a->stage),
                    'at' => $a->applied_at?->format('Y-m-d') ?? $a->created_at?->format('Y-m-d'),
                    'sort' => $a->applied_at?->toDateString() ?? $a->created_at?->toDateTimeString(),
                    'url' => route('applicants.show', $a),
                ];
            });

        $interviews = Interview::query()
            ->with(['applicant:id,name', 'applicant.jobPosting:id,title'])
            ->orderByDesc('scheduled_at')
            ->limit(10)
            ->get()
            ->map(function (Interview $i) {
                return [
                    'type' => 'Interview',
                    'label' => $i->applicant?->name ?? 'Applicant',
                    'detail' => $i->applicant?->jobPosting?->title ?? '—',
                    'meta' => ucfirst($i->status),
                    'at' => $i->scheduled_at?->format('Y-m-d H:i') ?? '—',
                    'sort' => $i->scheduled_at?->toDateTimeString() ?? '',
                    'url' => route('interviews.edit', $i),
                ];
            });

        return $applicants->concat($interviews)->sortByDesc('sort')->values()->take(18);
    }

    /**
     * @return array<string, mixed>
     */
    private function emptyPayload(): array
    {
        return [
            'kpis' => [
                'active_job_postings' => 0,
                'applicants_mtd' => 0,
                'referrals_mtd' => 0,
                'interviews_today' => 0,
                'upcoming_7d' => 0,
                'completed_interviews_mtd' => 0,
                'offers_mtd' => 0,
                'follow_ups_overdue' => 0,
            ],
            'chartPipeline' => ['labels' => [], 'data' => []],
            'chartApplicantsTrend' => ['labels' => [], 'applicants' => []],
            'chartInterviewThroughput' => ['labels' => [], 'completed' => [], 'scheduled' => []],
            'recentActivity' => collect(),
            'followUpPreview' => collect(),
        ];
    }
}
