<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\Termination;
use App\Models\User;
use App\Notifications\TerminationNoticeToEmployeeNotification;
use App\Notifications\TerminationRecordedNotification;
use App\Services\AuditService;
use App\Services\Hr\EmployeeAccessRevocationService;
use App\Services\Hr\ExitOffboardingBridgeService;
use App\Services\HrmsNotificationService;
use App\Support\FormTextRules;
use Illuminate\Http\Request;

class TerminationController extends Controller
{
    public function __construct(
        protected AuditService $audit,
        protected ExitOffboardingBridgeService $exitBridge,
        protected HrmsNotificationService $notifier,
        protected EmployeeAccessRevocationService $accessRevocation
    ) {}

    public function index()
    {
        /** @var User $user */
        $user = auth()->user();
        $canManage = $this->canManageOperations($user);

        if (! $canManage) {
            return redirect()->to(route('my-hr-records.index') . '#terminations');
        }

        $query = Termination::with(['user', 'offboarding']);
        $kpis = [
            'total' => (clone $query)->count(),
            'active' => (clone $query)->where('status', 'active')->count(),
        ];
        $terminations = $query->orderByDesc('termination_date')->paginate(15);

        return view('terminations.index', compact('terminations', '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();

        return view('terminations.create', compact('users'));
    }

    public function store(Request $request)
    {
        abort_unless($this->canManageOperations(auth()->user()), 403);

        $validated = $request->validate([
            'user_id' => 'required|exists:users,id',
            'termination_date' => 'required|date',
            'reason_type' => FormTextRules::notNumericOnly(false, 100),
            'reason' => FormTextRules::notNumericOnly(false, 2000),
            'status' => 'nullable|in:active,inactive',
            'notes' => FormTextRules::notNumericOnly(false, 1000),
        ], FormTextRules::messages());
        $validated['company_id'] = auth()->user()->company_id;
        $validated['status'] = $validated['status'] ?? 'active';

        $termination = Termination::create($validated);
        $termination->load('user');

        if ($termination->user && $termination->status === 'active') {
            $this->notifier->notifyUsersWithAnyPermission(
                (int) ($termination->company_id ?? 0),
                ['hr_operations_view'],
                new TerminationRecordedNotification($termination),
                [(int) $termination->user_id, (int) auth()->id()]
            );
            if ((int) $termination->user_id !== (int) auth()->id()) {
                $termination->user->notify(new TerminationNoticeToEmployeeNotification($termination));
            }
            $this->exitBridge->fromTermination($termination->fresh(['user']));
            $this->accessRevocation->deactivateAndRevoke($termination->user->fresh());
        }

        $this->audit->log('termination.created', $termination);

        return redirect()->route('terminations.index')->with('success', 'Termination recorded successfully.');
    }

    public function edit(Termination $termination)
    {
        abort_unless($this->canManageOperations(auth()->user()), 403);
        $this->assertTenantRecord($termination);
        $users = User::forActiveDirectory();
        if (auth()->user()->company_id) {
            $users->where('company_id', auth()->user()->company_id);
        }
        $users = $users->orderBy('name')->get();

        return view('terminations.edit', compact('termination', 'users'));
    }

    public function update(Request $request, Termination $termination)
    {
        abort_unless($this->canManageOperations(auth()->user()), 403);
        $this->assertTenantRecord($termination);
        $previousStatus = $termination->status;

        $validated = $request->validate([
            'user_id' => 'required|exists:users,id',
            'termination_date' => 'required|date',
            'reason_type' => FormTextRules::notNumericOnly(false, 100),
            'reason' => FormTextRules::notNumericOnly(false, 2000),
            'status' => 'nullable|in:active,inactive',
            'notes' => FormTextRules::notNumericOnly(false, 1000),
        ], FormTextRules::messages());
        $validated['company_id'] = auth()->user()->company_id;
        $termination->update($validated);
        $termination->load('user');

        if ($termination->user && $termination->status === 'active') {
            if ($previousStatus !== $termination->status) {
                $this->exitBridge->fromTermination($termination->fresh(['user']));
            }
            $this->accessRevocation->deactivateAndRevoke($termination->user->fresh());
        }

        $this->audit->log('termination.updated', $termination);

        return redirect()->route('terminations.index')->with('success', 'Termination updated successfully.');
    }

    public function destroy(Termination $termination)
    {
        abort_unless($this->canManageOperations(auth()->user()), 403);
        $this->assertTenantRecord($termination);

        if ($termination->offboarding_id) {
            return back()->with('error', 'Cannot delete a termination linked to offboarding.');
        }

        $termination->delete();
        $this->audit->log('termination.deleted', null, ['termination_id' => $termination->id]);

        return redirect()->route('terminations.index')->with('success', 'Termination deleted.');
    }

    protected function assertTenantRecord(Termination $termination): void
    {
        $companyId = auth()->user()?->company_id;
        if ($companyId && (int) $termination->company_id !== (int) $companyId) {
            abort(403);
        }
    }

    protected function canManageOperations(?User $user): bool
    {
        if (! $user) {
            return false;
        }

        if ($user->isCompanyAccountAdmin()) {
            return true;
        }

        return $user->hasPermission('hr_operations_view');
    }
}
