<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\Appreciation;
use App\Models\Complaint;
use App\Models\Offboarding;
use App\Models\Promotion;
use App\Models\Resignation;
use App\Models\Termination;
use App\Models\Warning;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;

class HrDashboardController extends Controller
{
    public function index(Request $request)
    {
        $companyId = (int) ($request->user()?->company_id ?? 0);
        $today = Carbon::today();

        if ($companyId <= 0) {
            return view('hr.dashboard', [
                'summary' => $this->emptySummary(),
                'recentActivity' => collect(),
            ]);
        }

        return view('hr.dashboard', [
            'summary' => $this->buildSummary($companyId, $today),
            'recentActivity' => $this->buildRecentActivity($companyId),
        ]);
    }

    private function emptySummary(): array
    {
        return [
            'total_records' => 0,
            'pending_actions' => 0,
            'movement_this_month' => 0,
            'recognitions_this_month' => 0,
            'complaints_by_status' => [],
            'resignations_by_status' => [],
            'terminations_by_status' => [],
        ];
    }

    private function buildSummary(int $companyId, Carbon $today): array
    {
        $monthYear = [(int) $today->year, (int) $today->month];

        $warningsThisMonth = Warning::query()
            ->where('company_id', $companyId)
            ->whereYear('warning_date', $monthYear[0])
            ->whereMonth('warning_date', $monthYear[1])
            ->count();

        $complaintsThisMonth = Complaint::query()
            ->where('company_id', $companyId)
            ->whereYear('complaint_date', $monthYear[0])
            ->whereMonth('complaint_date', $monthYear[1])
            ->count();

        $promotionsThisMonth = Promotion::query()
            ->where('company_id', $companyId)
            ->whereYear('promotion_date', $monthYear[0])
            ->whereMonth('promotion_date', $monthYear[1])
            ->count();

        $offboardingsThisMonth = Offboarding::query()
            ->where('company_id', $companyId)
            ->whereYear('offboarding_date', $monthYear[0])
            ->whereMonth('offboarding_date', $monthYear[1])
            ->count();

        $resignationsThisMonth = Resignation::query()
            ->where('company_id', $companyId)
            ->whereYear('resignation_date', $monthYear[0])
            ->whereMonth('resignation_date', $monthYear[1])
            ->count();

        $terminationsThisMonth = Termination::query()
            ->where('company_id', $companyId)
            ->whereYear('termination_date', $monthYear[0])
            ->whereMonth('termination_date', $monthYear[1])
            ->count();

        $appreciationsThisMonth = Appreciation::query()
            ->where('company_id', $companyId)
            ->whereYear('appreciation_date', $monthYear[0])
            ->whereMonth('appreciation_date', $monthYear[1])
            ->count();

        $complaintsByStatus = Complaint::query()
            ->where('company_id', $companyId)
            ->selectRaw('COALESCE(NULLIF(status, ""), "unknown") as status_key, COUNT(*) as total')
            ->groupBy('status_key')
            ->pluck('total', 'status_key')
            ->toArray();

        $resignationsByStatus = Resignation::query()
            ->where('company_id', $companyId)
            ->selectRaw('COALESCE(NULLIF(status, ""), "unknown") as status_key, COUNT(*) as total')
            ->groupBy('status_key')
            ->pluck('total', 'status_key')
            ->toArray();

        $terminationsByStatus = Termination::query()
            ->where('company_id', $companyId)
            ->selectRaw('COALESCE(NULLIF(status, ""), "unknown") as status_key, COUNT(*) as total')
            ->groupBy('status_key')
            ->pluck('total', 'status_key')
            ->toArray();

        $pendingActions = (int) (($complaintsByStatus['pending'] ?? 0) + ($complaintsByStatus['under_review'] ?? 0) + ($resignationsByStatus['pending'] ?? 0));
        $movementThisMonth = $promotionsThisMonth + $offboardingsThisMonth + $resignationsThisMonth + $terminationsThisMonth;
        $totalRecords = $warningsThisMonth + $complaintsThisMonth + $promotionsThisMonth + $offboardingsThisMonth + $resignationsThisMonth + $terminationsThisMonth + $appreciationsThisMonth;

        return [
            'total_records' => $totalRecords,
            'pending_actions' => $pendingActions,
            'movement_this_month' => $movementThisMonth,
            'recognitions_this_month' => $appreciationsThisMonth,
            'complaints_by_status' => $complaintsByStatus,
            'resignations_by_status' => $resignationsByStatus,
            'terminations_by_status' => $terminationsByStatus,
        ];
    }

    private function buildRecentActivity(int $companyId): Collection
    {
        $recentPerModule = 8;

        $warnings = Warning::query()
            ->with('user:id,name')
            ->where('company_id', $companyId)
            ->orderByDesc('warning_date')
            ->orderByDesc('id')
            ->limit($recentPerModule)
            ->get()
            ->map(function (Warning $warning) {
                return [
                    'module' => 'Warning',
                    'employee' => $warning->user?->name ?? '—',
                    'title' => $warning->subject ?: 'Warning',
                    'meta' => $warning->severity ?: 'medium',
                    'activity_date' => optional($warning->warning_date)?->format('Y-m-d') ?? optional($warning->created_at)?->format('Y-m-d'),
                    'sort_date' => optional($warning->warning_date)?->toDateString() ?? optional($warning->created_at)?->toDateString(),
                    'link' => route('warnings.index'),
                ];
            });

        $complaints = Complaint::query()
            ->with('againstUser:id,name')
            ->where('company_id', $companyId)
            ->orderByDesc('complaint_date')
            ->orderByDesc('id')
            ->limit($recentPerModule)
            ->get()
            ->map(function (Complaint $complaint) {
                return [
                    'module' => 'Complaint',
                    'employee' => $complaint->againstUser?->name ?? '—',
                    'title' => $complaint->subject ?: 'Complaint',
                    'meta' => $complaint->status ?: 'pending',
                    'activity_date' => optional($complaint->complaint_date)?->format('Y-m-d') ?? optional($complaint->created_at)?->format('Y-m-d'),
                    'sort_date' => optional($complaint->complaint_date)?->toDateString() ?? optional($complaint->created_at)?->toDateString(),
                    'link' => route('complaints.index'),
                ];
            });

        $promotions = Promotion::query()
            ->with('user:id,name')
            ->where('company_id', $companyId)
            ->orderByDesc('promotion_date')
            ->orderByDesc('id')
            ->limit($recentPerModule)
            ->get()
            ->map(function (Promotion $promotion) {
                return [
                    'module' => 'Promotion',
                    'employee' => $promotion->user?->name ?? '—',
                    'title' => 'Promotion updated',
                    'meta' => 'movement',
                    'activity_date' => optional($promotion->promotion_date)?->format('Y-m-d') ?? optional($promotion->created_at)?->format('Y-m-d'),
                    'sort_date' => optional($promotion->promotion_date)?->toDateString() ?? optional($promotion->created_at)?->toDateString(),
                    'link' => route('promotions.index'),
                ];
            });

        $offboardings = Offboarding::query()
            ->with('user:id,name')
            ->where('company_id', $companyId)
            ->orderByDesc('offboarding_date')
            ->orderByDesc('id')
            ->limit($recentPerModule)
            ->get()
            ->map(function (Offboarding $offboarding) {
                return [
                    'module' => 'Offboarding',
                    'employee' => $offboarding->user?->name ?? '—',
                    'title' => 'Offboarding scheduled',
                    'meta' => $offboarding->type ?: 'other',
                    'activity_date' => optional($offboarding->offboarding_date)?->format('Y-m-d') ?? optional($offboarding->created_at)?->format('Y-m-d'),
                    'sort_date' => optional($offboarding->offboarding_date)?->toDateString() ?? optional($offboarding->created_at)?->toDateString(),
                    'link' => route('offboardings.show', $offboarding),
                ];
            });

        $resignations = Resignation::query()
            ->with('user:id,name')
            ->where('company_id', $companyId)
            ->orderByDesc('resignation_date')
            ->orderByDesc('id')
            ->limit($recentPerModule)
            ->get()
            ->map(function (Resignation $resignation) {
                return [
                    'module' => 'Resignation',
                    'employee' => $resignation->user?->name ?? '—',
                    'title' => 'Resignation submitted',
                    'meta' => $resignation->status ?: 'pending',
                    'activity_date' => optional($resignation->resignation_date)?->format('Y-m-d') ?? optional($resignation->created_at)?->format('Y-m-d'),
                    'sort_date' => optional($resignation->resignation_date)?->toDateString() ?? optional($resignation->created_at)?->toDateString(),
                    'link' => route('resignations.index'),
                ];
            });

        $terminations = Termination::query()
            ->with('user:id,name')
            ->where('company_id', $companyId)
            ->orderByDesc('termination_date')
            ->orderByDesc('id')
            ->limit($recentPerModule)
            ->get()
            ->map(function (Termination $termination) {
                return [
                    'module' => 'Termination',
                    'employee' => $termination->user?->name ?? '—',
                    'title' => 'Termination recorded',
                    'meta' => $termination->status ?: 'active',
                    'activity_date' => optional($termination->termination_date)?->format('Y-m-d') ?? optional($termination->created_at)?->format('Y-m-d'),
                    'sort_date' => optional($termination->termination_date)?->toDateString() ?? optional($termination->created_at)?->toDateString(),
                    'link' => route('terminations.index'),
                ];
            });

        $appreciations = Appreciation::query()
            ->with('user:id,name')
            ->where('company_id', $companyId)
            ->orderByDesc('appreciation_date')
            ->orderByDesc('id')
            ->limit($recentPerModule)
            ->get()
            ->map(function (Appreciation $appreciation) {
                $date = optional($appreciation->appreciation_date)?->toDateString();

                return [
                    'module' => 'Appreciation',
                    'employee' => $appreciation->user?->name ?? '—',
                    'title' => $appreciation->title ?: 'Appreciation shared',
                    'meta' => 'recognition',
                    'activity_date' => $date ? Carbon::parse($date)->format('Y-m-d') : optional($appreciation->created_at)?->format('Y-m-d'),
                    'sort_date' => $date ?: optional($appreciation->created_at)?->toDateString(),
                    'link' => route('appreciations.index'),
                ];
            });

        return collect()
            ->concat($warnings)
            ->concat($complaints)
            ->concat($promotions)
            ->concat($offboardings)
            ->concat($resignations)
            ->concat($terminations)
            ->concat($appreciations)
            ->sortByDesc('sort_date')
            ->values()
            ->take(18);
    }
}
