<?php



namespace App\Http\Controllers\Web;



use App\Http\Controllers\Controller;

use App\Models\Resignation;

use App\Models\User;

use App\Notifications\ResignationStatusChangedNotification;

use App\Notifications\ResignationSubmittedNotification;

use App\Services\AuditService;

use App\Services\Hr\ExitOffboardingBridgeService;

use App\Services\HrmsNotificationService;

use App\Support\FormTextRules;

use Illuminate\Http\Request;



class ResignationController extends Controller

{

    public function __construct(

        protected AuditService $audit,

        protected ExitOffboardingBridgeService $exitBridge

    ) {}



    public function index()

    {

        $resignations = Resignation::with(['user', 'offboarding'])->orderByDesc('resignation_date')->paginate(15);



        return view('resignations.index', compact('resignations'));

    }



    public function create()

    {

        $users = User::forActiveDirectory();

        if (auth()->user()->company_id) {

            $users->where('company_id', auth()->user()->company_id);

        }

        $users = $users->orderBy('name')->get();



        return view('resignations.create', compact('users'));

    }



    public function selfCreate()

    {

        $existing = Resignation::query()

            ->where('user_id', auth()->id())

            ->whereIn('status', ['pending', 'approved'])

            ->latest('id')

            ->first();



        return view('resignations.self-create', compact('existing'));

    }



    public function store(Request $request, HrmsNotificationService $notifier)

    {

        $validated = $request->validate([

            'user_id' => 'required|exists:users,id',

            'resignation_date' => 'required|date',

            'last_working_date' => 'nullable|date|after_or_equal:resignation_date',

            'reason' => FormTextRules::notNumericOnly(false, 2000),

            'status' => 'nullable|in:pending,approved,rejected,withdrawn',

            'notes' => FormTextRules::notNumericOnly(false, 1000),

        ], FormTextRules::messages());

        $validated['company_id'] = auth()->user()->company_id;

        $validated['status'] = $validated['status'] ?? 'pending';



        $resignation = Resignation::create($validated);

        $resignation->load('user');



        if ($resignation->status === 'pending' && $resignation->user) {

            $notifier->notifyResignationApprovers(

                $resignation->user,

                new ResignationSubmittedNotification($resignation)

            );

        }



        $this->audit->log('resignation.created', $resignation);



        if ($resignation->status === 'approved') {

            $this->exitBridge->fromResignation($resignation->fresh(['user']));

        }



        return redirect()->route('resignations.index')->with('success', 'Resignation recorded successfully.');

    }



    public function selfStore(Request $request, HrmsNotificationService $notifier)

    {

        $user = auth()->user();



        $hasOpen = Resignation::query()

            ->where('user_id', $user->id)

            ->whereIn('status', ['pending', 'approved'])

            ->exists();



        if ($hasOpen) {

            return back()->with('error', 'You already have an open resignation request.');

        }



        $validated = $request->validate([

            'resignation_date' => 'required|date',

            'last_working_date' => 'nullable|date|after_or_equal:resignation_date',

            'reason' => FormTextRules::notNumericOnly(true, 2000),

        ], FormTextRules::messages());



        $resignation = Resignation::create([

            'company_id' => $user->company_id,

            'user_id' => $user->id,

            'resignation_date' => $validated['resignation_date'],

            'last_working_date' => $validated['last_working_date'] ?? null,

            'reason' => $validated['reason'],

            'status' => 'pending',

        ]);



        $resignation->load('user');

        $notifier->notifyResignationApprovers($user, new ResignationSubmittedNotification($resignation));

        $this->audit->log('resignation.self_submitted', $resignation);



        return redirect()->route('resignations.self.create')->with('success', 'Your resignation has been submitted for approval.');

    }



    public function edit(Resignation $resignation)

    {

        $this->assertTenantRecord($resignation);

        $users = User::forActiveDirectory();

        if (auth()->user()->company_id) {

            $users->where('company_id', auth()->user()->company_id);

        }

        $users = $users->orderBy('name')->get();



        return view('resignations.edit', compact('resignation', 'users'));

    }



    public function update(Request $request, Resignation $resignation)

    {

        $this->assertTenantRecord($resignation);

        $previousStatus = $resignation->status;



        $validated = $request->validate([

            'user_id' => 'required|exists:users,id',

            'resignation_date' => 'required|date',

            'last_working_date' => 'nullable|date|after_or_equal:resignation_date',

            'reason' => FormTextRules::notNumericOnly(false, 2000),

            'status' => 'nullable|in:pending,approved,rejected,withdrawn',

            'notes' => FormTextRules::notNumericOnly(false, 1000),

        ], FormTextRules::messages());

        $validated['company_id'] = auth()->user()->company_id;

        $resignation->update($validated);

        $resignation->load('user');



        if ($resignation->user && $previousStatus !== $resignation->status) {

            $this->notifyResignationStatusChange($resignation, $previousStatus);

            if ($resignation->status === 'approved') {

                $this->exitBridge->fromResignation($resignation->fresh(['user']));

            }

        }



        $this->audit->log('resignation.updated', $resignation, ['previous_status' => $previousStatus]);



        return redirect()->route('resignations.index')->with('success', 'Resignation updated successfully.');

    }



    public function updateStatus(Request $request, Resignation $resignation)

    {

        $this->assertTenantRecord($resignation);

        $previousStatus = $resignation->status;



        $request->validate(['status' => 'required|in:pending,approved,rejected,withdrawn']);

        $resignation->update(['status' => $request->status]);

        $resignation->load('user');



        if ($resignation->user && $previousStatus !== $resignation->status) {

            $this->notifyResignationStatusChange($resignation, $previousStatus);

            if ($resignation->status === 'approved') {

                $offboarding = $this->exitBridge->fromResignation($resignation->fresh(['user']));

                if ($offboarding) {

                    return redirect()->route('resignations.index')->with('success', 'Status updated. Offboarding workflow initiated.');

                }

            }

        }



        $this->audit->log('resignation.status_changed', $resignation, ['previous_status' => $previousStatus]);



        return redirect()->route('resignations.index')->with('success', 'Status updated.');

    }



    public function destroy(Resignation $resignation)

    {

        $this->assertTenantRecord($resignation);



        if ($resignation->offboarding_id) {

            return back()->with('error', 'Cannot delete a resignation linked to offboarding.');

        }



        if ($resignation->status === 'approved') {

            return back()->with('error', 'Approved resignations cannot be deleted.');

        }



        $resignation->delete();

        $this->audit->log('resignation.deleted', null, ['resignation_id' => $resignation->id]);



        return redirect()->route('resignations.index')->with('success', 'Resignation deleted.');

    }



    protected function notifyResignationStatusChange(Resignation $resignation, string $previousStatus): void

    {

        if ($resignation->status === 'pending' && $previousStatus !== 'pending' && $resignation->user) {

            app(HrmsNotificationService::class)->notifyResignationApprovers(

                $resignation->user,

                new ResignationSubmittedNotification($resignation)

            );



            return;

        }



        if (in_array($resignation->status, ['approved', 'rejected', 'withdrawn'], true)) {

            $resignation->user?->notify(new ResignationStatusChangedNotification($resignation, $resignation->status));

        }

    }



    protected function assertTenantRecord(Resignation $resignation): void

    {

        $companyId = auth()->user()?->company_id;

        if ($companyId && (int) $resignation->company_id !== (int) $companyId) {

            abort(403);

        }

    }

}


