<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\Department;
use App\Models\Designation;
use App\Models\Promotion;
use App\Models\User;
use App\Notifications\PromotionRecordedNotification;
use App\Support\FormTextRules;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class PromotionController extends Controller
{
    public function index()
    {
        /** @var User $user */
        $user = auth()->user();
        $canManage = $this->canManageOperations($user);

        if (! $canManage) {
            return redirect()->to(route('my-hr-records.index') . '#promotions');
        }

        $query = Promotion::with(['user', 'fromDesignation', 'toDesignation', 'fromDepartment', 'toDepartment']);
        $kpis = [
            'total' => (clone $query)->count(),
        ];
        $promotions = $query->orderByDesc('promotion_date')->paginate(15);

        return view('hr.promotions', compact('promotions', 'canManage', 'kpis'));
    }

    public function create()
    {
        abort_unless($this->canManageOperations(auth()->user()), 403);

        $users = User::forActiveDirectory();
        if (auth()->user()->company_id) {
            $users->where('company_id', auth()->user()->company_id);
        }
        $users = $users->orderBy('name')->get();
        $departments = Department::orderBy('name')->get();
        $designations = Designation::orderBy('name')->get();

        return view('hr.promotions-create', compact('users', 'departments', 'designations'));
    }

    public function store(Request $request)
    {
        abort_unless($this->canManageOperations(auth()->user()), 403);

        $validated = $request->validate([
            'user_id' => 'required|exists:users,id',
            'from_designation_id' => 'nullable|exists:designations,id',
            'to_designation_id' => 'nullable|exists:designations,id',
            'from_department_id' => 'nullable|exists:departments,id',
            'to_department_id' => 'nullable|exists:departments,id',
            'promotion_date' => 'required|date',
            'notes' => FormTextRules::notNumericOnly(false, 1000),
        ], FormTextRules::messages());
        $validated['company_id'] = auth()->user()->company_id;

        $promotion = null;
        DB::transaction(function () use ($validated, &$promotion): void {
            $promotion = Promotion::create($validated);
            $this->applyPromotionToEmployee($validated);
        });

        if ($promotion) {
            $promotion->load(['user', 'fromDesignation', 'toDesignation']);
            if ($promotion->user && (int) $promotion->user_id !== (int) auth()->id()) {
                $promotion->user->notify(new PromotionRecordedNotification($promotion));
            }
        }

        return redirect()->route('promotions.index')->with('success', 'Promotion recorded successfully.');
    }

    /**
     * @param  array<string, mixed>  $validated
     */
    private function applyPromotionToEmployee(array $validated): void
    {
        $employeeQuery = User::query()->whereKey($validated['user_id']);
        if (auth()->user()->company_id) {
            $employeeQuery->where('company_id', auth()->user()->company_id);
        }

        $employee = $employeeQuery->first();
        if (! $employee) {
            return;
        }

        $updates = [];
        if (! empty($validated['to_designation_id'])) {
            $updates['designation_id'] = $validated['to_designation_id'];
        }
        if (! empty($validated['to_department_id'])) {
            $updates['department_id'] = $validated['to_department_id'];
        }

        if ($updates !== []) {
            $employee->update($updates);
        }
    }

    protected function canManageOperations(?User $user): bool
    {
        if (! $user) {
            return false;
        }

        if ($user->isCompanyAccountAdmin()) {
            return true;
        }

        return $user->hasPermission('hr_operations_view');
    }
}
