<?php

namespace App\Http\Controllers;

use App\Exports\PayrollExportNew;
use App\Models\ExchangeRate;
use App\Models\Payroll;
use App\Models\PayrollEmployee;
use App\Models\User;
use App\Models\OrganisationAllowance;
use App\Models\Deduction;
use Exception;
use Http;
use Illuminate\Support\Facades\Storage;
use Maatwebsite\Excel\Facades\Excel;
use App\Interfaces\UserRepositoryInterface;
use App\Interfaces\OrganisationRepositoryInterface;
use App\Interfaces\UserOrgPermissionRepositoryInterface;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Carbon\Carbon;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use App\Imports\DataImport;
use PhpParser\Builder\FunctionLike;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use App\Mail\InvitationMail;
use App\Mail\InvitationAcceptedMail;
use App\Mail\ContactMail;
use App\Mail\GroupInvitationMail;
use App\Mail\SendPayroll;
use App\Exports\PayrollExport;
use App\Imports\AllowanceImport;
use App\Imports\ExceptionalAllowanceImport;
use App\Imports\ExceptionalDeductionImport;
use App\Imports\DeductionImport;
use App\Imports\DeductionEmployee;
use App\Imports\AllowanceEmployee;
use App\Exports\UsersExport;
use App\Models\Organisation;
use App\Models\PayrollTransaction;
use Spatie\Activitylog\Models\Activity;

class OrganisationController extends Controller
{
    private UserRepositoryInterface $userRepository;
    private OrganisationRepositoryInterface $organisationRepository;

    private UserOrgPermissionRepositoryInterface $userOrgPermissionRepository;

    public function __construct(UserRepositoryInterface $userRepository, OrganisationRepositoryInterface $organisationRepository, UserOrgPermissionRepositoryInterface $userOrgPermissionRepository)
    {
        $this->middleware('auth.api');
        $this->userRepository = $userRepository;
        $this->organisationRepository = $organisationRepository;
        $this->userOrgPermissionRepository = $userOrgPermissionRepository;
    }

    public function updateOrganisationRequest(Request $request)
    {
        $data = $request->all();
        try {
            $user = Auth::user();
            $user_data = $this->userRepository->findById($user->id);
            $org = $this->organisationRepository->findById($user->organisation_id);

            if ($org) {
                if ($request->logo) {
                    // Get the uploaded file
                    $file = $request->file('logo');
                    // Define the path where the file should be stored in S3
                    $path = 'uploads/' . uniqid() . '.' . $file->getClientOriginalExtension();
                    // Put the file content into the defined path in S3
                    Storage::disk('s3')->put($path, file_get_contents($file));
                    // Get the full URL of the stored file
                    $disk = Storage::disk('s3');
                    $url = $disk->url($path);

                    $data = [...$data, 'logo' => $url];

                    // return $data;
                    $org = $this->organisationRepository->update($org->id, $data);
                }

                //Add to audit
                $userProfile = $this->userRepository->getUserProfileByUser($user->id);
                $auditData = [
                    "organisation_id" => $org->id,
                    "content" => "{$userProfile['first_name']} {$userProfile['last_name']} changed company profile information",
                    "level" => "low",
                    "is_exposed" => 1,
                    "user_id" => $user->id
                ];
                $audit = $this->organisationRepository->createAuditTrail($auditData);
                return response()->json([
                    'status' => 'success',
                    'data' => ['user_profile' => $user_data, 'organisation' => $org],
                    'message' => 'Update was successfully'
                ]);
            }
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function uploadFile(Request $request)
    {
        $data = $request->all();
        try {
            $user = Auth::user();
            $user_data = $this->userRepository->findById($user->id);
            if ($user_data->is_active == false) {

                return response()->json([
                    'status' => 'success',
                    'message' => 'User cannot upload file'
                ], 500);
            }
            if ($request->upload) {
                // Get the uploaded file
                $file = $request->file('upload');
                // Define the path where the file should be stored in S3
                $path = 'uploads/' . uniqid() . '.' . $file->getClientOriginalExtension();
                // Put the file content into the defined path in S3
                Storage::disk('s3')->put($path, file_get_contents($file));
                // Get the full URL of the stored file
                $disk = Storage::disk('s3');
                $url = $disk->url($path);
            }

            return response()->json([
                'status' => 'success',
                'data' => $url,
                'message' => 'File was successfully uploaded'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //List Employees
    public function listOrganisationEmployees(Request $request)
    {
        try {
            $user = Auth::user();
            $limit = 1000;
            // $limit = (int) $request->limit ?? 1000;

            //check if org exists
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot add users at the moment',
                ], 400);
            }

            $data = [
                "employment_status" => $request->employment_status ?? 'all',
                "pay_group" => $request->pay_group ?? 'all',
                "search_string" => $request->search_string ?? ''
            ];
            $users = $this->userRepository->findByOrganisation($org->id, $data, $limit);
            return response()->json([
                'status' => 'success',
                'message' => 'Employee list returned',
                'data' => $users
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function getEmployeeByUserID(Request $request)
    {
        $user = Auth::user();
        return $theUser = User::where('id', $request->user_id)->where("organisation_id", $user->organisation_id)->first();
    }


    //Edit Base Employee Data
    public function updateDefaultEmployee(Request $request)
    {
        try {
            $user = Auth::user();
            $userId = $request->userId;

            //check if org exists
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot add users at the moment',
                ], 400);
            }
            $userBelongsToOrg = $this->organisationRepository->checkUserInOrg($org->id, $userId);
            if (!$userBelongsToOrg) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'User does not belong to this organisation',
                    'data' => []
                ], 400);
            }
            $data = [
                "time_id" => $request->timeId
            ];

            $updatedUser = $this->organisationRepository->updateDefaultEmployee($userId, $data);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} updated employee Information",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Employee default data updated successfully',
                'data' => $updatedUser
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Delete User/Employee
    public function deleteEmployee(Request $request)
    {
        try {
            $user = Auth::user();
            $requestedUser = $request->userId;

            //check if org exists
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot add users at the moment',
                ], 400);
            }

            //Check if user belongs to the org 
            $orgUser = $this->userRepository->findById($requestedUser);
            if (!$orgUser) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Employee does not exist',
                ], 400);
            }
            if ($orgUser->organisation_id != $org->id) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Employee does not belong to your organisation',
                ], 400);
            }

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} deleted one employee with the id of {$requestedUser}",
                "level" => "low",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $this->organisationRepository->createAuditTrail($auditData);

            $this->userRepository->deleteUser($requestedUser);

            return response()->json([
                'status' => 'success',
                'message' => 'Employee deleted successfully',
                'data' => []
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Grant Employee Permissions
    public function grantEmployeePermission(Request $request)
    {
        try {
            $userId = $request->userId;
            $accessLevelName = $request->accessLevelName;
            $description = $request->description;
            $permissionId = $request->permissionId;
            $accessLevel = $request->accessLevel;

            //Add Validations
            $validator = Validator::make($request->all(), [
                'accessLevelName' => 'string|required',
                'description' => 'string',
                'permissionId' => 'integer|required',
                'accessLevel' => 'array|required',
                'userId' => 'integer|required',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $user = Auth::user();

            //check if org exists
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot add permissions at the moment',
                ], 400);
            }

            $permissionsData = [
                "user_id" => $userId,
                "org_id" => $org->id,
                "name" => $accessLevelName,
                "description" => $description,
                "permission_id" => $permissionId,
                "access_levels" => $accessLevel,
            ];

            $userPermissions = $this->userOrgPermissionRepository->createAccessLevel($permissionsData);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} granted one employee permission with the id of {$userId}",
                "level" => "critical",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);

            return response()->json([
                'status' => 'success',
                'message' => 'Employee permission created successfully',
                'data' => $userPermissions,
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Revoke Employee Permission
    public function revokePermission(Request $request)
    {
        try {
            $id = $request->id;
            $user = Auth::user();

            //check if org exists
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot add permissions at the moment',
                ], 400);
            }
            $userPermission = $this->userOrgPermissionRepository->revokeAccess($id);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} revoked one employee permission with the id of {$id}",
                "level" => "critical",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Employee permission revoked successfully',
                'data' => []
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Employee Permissions
    public function getAllPermissions(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $userPermissions_array = $this->userOrgPermissionRepository->getAll($org->id)->toArray();
            $userPermissions = array_map(function ($item) {
                $name = '';
                if (isset($item['user']['profile']['first_name']) && isset($item['user']['profile']['last_name'])) {
                    $name = $item['user']['profile']['first_name'] . ' ' . $item['user']['profile']['last_name'];
                }
                return array_merge($item, ['assigned_to' => $name]);
            }, $userPermissions_array);


            return response()->json([
                'status' => 'success',
                'message' => 'Employee permission returned successfully',
                'data' => $userPermissions
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get One Employee Permissions
    public function getOnePermissions(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $id = $request->id;
            $userPermissions = $this->userOrgPermissionRepository->getOne($id);

            return response()->json([
                'status' => 'success',
                'message' => 'Employee permission returned successfully',
                'data' => $userPermissions
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Employee Permission
    public function updatePermission(Request $request, $id)
    {
        try {
            $accessLevelName = $request->accessLevelName;
            $description = $request->description;
            $permissionId = $request->permissionId;
            $accessLevel = $request->accessLevel;
            $id = $request->id;
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot add permissions at the moment',
                ], 400);
            }

            //Add Validations
            $validator = Validator::make($request->all(), [
                'accessLevelName' => 'string',
                'description' => 'string',
                'permissionId' => 'integer',
                'accessLevel' => 'array',
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }
            $permissionsData = [
                "name" => $accessLevelName,
                "description" => $description,
                "permission_id" => $permissionId,
                "access_levels" => $accessLevel,
            ];

            $userPermission = $this->userOrgPermissionRepository->updateAccessLevel($id, $permissionsData);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} updated one employee permission with the id of {$id}",
                "level" => "critical",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Employee permission updated successfully',
                'data' => $userPermission
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Create Tax Settings
    public function createTaxSettings(Request $request)
    {
        try {
            $user = Auth::user();
            $salary_range = $request->salary_range;
            $percentage = $request->percentage;

            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot create tax settings at the moment',
                ], 400);
            }

            //Add Validations
            $validator = Validator::make($request->all(), [
                'salary_range' => 'integer',
                'percentage' => 'integer',
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }
            $taxData = [
                "org_id" => $org->id,
                "salary_range" => $salary_range,
                "percentage" => $percentage,
            ];
            $taxSettings = $this->organisationRepository->createTaxSettings($taxData);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} create a new tax settings",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Tax settings created successfully',
                'data' => $taxSettings
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Tax Settings
    public function updateTaxSettings(Request $request)
    {
        try {
            $user = Auth::user();
            $taxId = $request->taxId;
            $salary_range = $request->salary_range;
            $percentage = $request->percentage;

            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot update tax settings at the moment',
                ], 400);
            }

            //Add Validations
            $validator = Validator::make($request->all(), [
                'salary_range' => 'integer',
                'percentage' => 'integer',
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $taxData = [
                "salary_range" => $salary_range,
                "percentage" => $percentage,
            ];


            $foundTaxRecord = $this->organisationRepository->getSingleTaxSetting($taxId);

            if (empty($foundTaxRecord)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Tax setting not found',
                    'data' => $foundTaxRecord
                ], 400);
            }

            $taxSettings = $this->organisationRepository->updateTaxSettings($taxId, $taxData);


            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} updated a new tax settings",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Tax settings updated successfully',
                'data' => $taxSettings
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }



    //Get Tax Settings
    public function getTaxSettings(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access tax settings at the moment',
                ], 400);
            }
            $taxSettings = $this->organisationRepository->getTaxSettings($org->id);
            return response()->json([
                'status' => 'success',
                'message' => 'Tax settings returned successfully',
                'data' => $taxSettings
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Delete Tax Settings
    public function deleteTax(Request $request)
    {
        try {
            $user = Auth::user();
            $taxId = $request->taxId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access tax settings at the moment',
                ], 400);
            }
            $taxSetting = $this->organisationRepository->deleteTaxSettings($taxId);


            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} deleted a tax settings",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Tax settings deleted successfully',
                'data' => []
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    // Check tax table status
    public function getTaxStatus(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access tax settings at the moment',
                ], 400);
            }

            $currentYear = $this->organisationRepository->getCurrentTaxYear($org->id);
            $isUsing2026Rates = $this->organisationRepository->isUsing2026TaxRates($org->id);

            // If no tax settings exist, return null for year
            if (!$currentYear) {
                return response()->json([
                    'status' => 'success',
                    'data' => [
                        'year' => null,
                        'needs_upgrade' => true
                    ]
                ], 200);
            }

            // Check if needs upgrade
            $needsUpgrade = !$isUsing2026Rates;

            return response()->json([
                'status' => 'success',
                'data' => [
                    'year' => $currentYear,
                    'needs_upgrade' => $needsUpgrade
                ]
            ], 200);

        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    // Upgrade tax table to 2026 tax rates
    public function upgradeTaxTable(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot perform this operation at the moment',
                ], 400);
            }

            // Check if already using 2026 rates
            $currentYear = $this->organisationRepository->getCurrentTaxYear($org->id);
            $isUsing2026Rates = $this->organisationRepository->isUsing2026TaxRates($org->id);

            if ($isUsing2026Rates) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Tax table is already using 2026 tax rate',
                ], 400);
            }

            // Backup old tax table with user info and notes
            $backupResult = $this->organisationRepository->backupTaxTable(
                $org->id,
                $user->id
            );

            // Define new tax rates for 2026
            $newTaxRates = [
                ['salary_range' => 800000, 'percentage' => 0],
                ['salary_range' => 3000000, 'percentage' => 15],
                ['salary_range' => 9000000, 'percentage' => 18],
                ['salary_range' => 13000000, 'percentage' => 21],
                ['salary_range' => 25000000, 'percentage' => 23],
                ['salary_range' => 50000000, 'percentage' => 25],
            ];

            // Create new tax settings
            $this->organisationRepository->createNewTaxSettings($org->id, $newTaxRates);

            // Log the upgrade activity
            activity()
                ->causedBy($user)
                ->performedOn($org)
                ->withProperties([
                    'backup_version' => $backupResult['backup_version'] ?? null,
                    'old_tax_year' => $currentYear,
                    'new_tax_year' => 2026,
                    'backup_record_count' => $backupResult['record_count'] ?? 0
                ])
                ->log('Tax table upgraded to 2026');

            return response()->json([
                'status' => 'success',
                'message' => 'Tax table upgraded to 2026 successfully',
            ], 200);

        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    // Get backedup tax settings
    public function getTaxBackupHistory(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access backup history at the moment',
                ], 400);
            }

            $limit = $request->input('limit', 10);
            $backupHistory = $this->organisationRepository->getTaxBackupHistory($org->id, $limit);

            return response()->json([
                'status' => 'success',
                'message' => 'Tax backup history retrieved successfully',
                'data' => $backupHistory
            ], 200);

        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Create Employee Tax Record
    public function createEmployeeTaxRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $taxId = $request->taxId;
            $userId = $request->userId;
            $personal_rate = $request->personal_rate;
            $is_exempted = $request->is_exempted;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access tax settings at the moment',
                ], 400);
            }

            $userBelongsToOrg = $this->organisationRepository->checkUserInOrg($org->id, $userId);
            if (!$userBelongsToOrg) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'User does not belong to this organisation',
                    'data' => []
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'userId' => 'integer|required',
                'taxId' => 'integer',
                'personal_rate' => 'integer',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $taxRecord = [
                "employee_id" => $userId,
                "org_id" => $org->id,
                "tax_id" => $taxId,
                "personal_rate" => $personal_rate,
                "is_exempted" => $is_exempted
            ];
            $taxSetting = $this->organisationRepository->createEmployeeTaxRecord($taxRecord);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} create a new tax record for employee",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Tax recorded created successfully',
                'data' => $taxSetting
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Employee Tax Record
    public function updateEmployeeTaxRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $taxId = $request->taxId;
            $personal_rate = $request->personal_rate;
            $is_exempted = $request->is_exempted;
            $recordId = $request->recordId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access tax settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'tax_id' => 'integer',
                'personal_rate' => 'integer',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $taxRecord = [
                "tax_id" => $taxId,
                "personal_rate" => $personal_rate,
                "is_exempted" => $is_exempted
            ];

            $foundTaxRecord = $this->organisationRepository->getEmployeeTaxRecord($recordId);

            if (empty($foundTaxRecord)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Tax record not found',
                    'data' => $foundTaxRecord
                ], 400);
            }

            $taxSetting = $this->organisationRepository->updateEmployeeTaxRecord($recordId, $taxRecord);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} updated a tax record for employee",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Tax record updated successfully',
                'data' => $taxSetting
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Single Employee Tax Record
    public function getSingleEmployeeTaxRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $recordId = $request->recordId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access tax settings at the moment',
                ], 400);
            }
            $taxSetting = $this->organisationRepository->getEmployeeTaxRecord($recordId);

            if (empty($taxSetting)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Tax record not found',
                    'data' => $taxSetting
                ], 400);
            }
            return response()->json([
                'status' => 'success',
                'message' => 'Tax record returned successfully',
                'data' => $taxSetting
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function getSingleTaxSetting(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access tax settings at the moment',
                ], 400);
            }
            $taxSetting = $this->organisationRepository->getSingleTaxSetting($id);

            if (empty($taxSetting)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Tax record not found',
                    'data' => $taxSetting
                ], 400);
            }
            return response()->json([
                'status' => 'success',
                'message' => 'Tax record returned successfully',
                'data' => $taxSetting
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Employee Tax Record
    public function getAllEmployeeTaxRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access tax settings at the moment',
                ], 400);
            }
            $taxSetting = $this->organisationRepository->getAllEmployeesTaxRecord($org->id);
            return response()->json([
                'status' => 'success',
                'message' => 'Tax records returned successfully',
                'data' => $taxSetting
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }


    //Delete Single Employee Tax Record
    public function deleteTaxRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $recordId = $request->recordId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access tax settings at the moment',
                ], 400);
            }
            $taxSetting = $this->organisationRepository->deleteEmployeeTaxRecord($recordId);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} deleted a tax record for employee",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Tax record deleted successfully',
                'data' => []
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    /**
     * Generate a unique slug for the allowance.
     */
    private function generateUniqueSlug($name, $orgId)
    {
        // Extract first 3 alphanumeric characters and convert to uppercase
        $slug = strtoupper(preg_replace('/[^a-zA-Z0-9]/', '', substr($name, 0, 3)));

        // Get existing slugs for the organization
        $existingSlugs = OrganisationAllowance::where('org_id', $orgId)
            ->where('slug', 'LIKE', $slug . '%')
            ->pluck('slug')
            ->toArray();

        // Find a unique numeric suffix (00-99)
        $count = 0;
        while (in_array("{$slug}" . str_pad($count, 2, '0', STR_PAD_LEFT), $existingSlugs)) {
            $count++;
            if ($count > 99) { // Avoid infinite loops
                throw new \Exception('Slug limit reached for this name.');
            }
        }

        return "{$slug}" . str_pad($count, 2, '0', STR_PAD_LEFT);
    }



    private function generateUniqueSlugDeduction($name, $orgId)
    {
        // Extract first 3 alphanumeric characters from the name
        $slug = strtoupper(preg_replace('/[^a-zA-Z0-9]/', '', substr($name, 0, 3)));

        // Get existing slugs for the organization
        $existingSlugs = Deduction::where('org_id', $orgId)
            ->where('slug', 'LIKE', $slug . '%')
            ->pluck('slug')
            ->toArray();

        // Find a unique numeric suffix (00-99)
        $count = 0;
        while (in_array("{$slug}" . str_pad($count, 2, '0', STR_PAD_LEFT), $existingSlugs)) {
            $count++;
            if ($count > 99) { // Avoid infinite loops
                throw new Exception('Slug limit reached for this name.');
            }
        }

        return "{$slug}" . str_pad($count, 2, '0', STR_PAD_LEFT);
    }

    //Create Org Allowance 
    public function createOrgAllowance(Request $request)
    {
        try {
            $user = Auth::user();
            $type = $request->type;
            $name = $request->name;
            $description = $request->description;
            $isExceptional = $request->isExceptional;
            $startDate = $request->startDate;
            $endDate = $request->endDate;
            $startDate = $request->startDate ? Carbon::createFromFormat('Y-m', $request->startDate)->startOfMonth()->toDateString() : null;
            $endDate = $request->endDate ? Carbon::createFromFormat('Y-m', $request->endDate)->startOfMonth()->toDateString() : null;
            $isTaxable = $request->is_taxable;
            $percentage_of = $request->percentage_of;

            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access allowance settings at the moment',
                ], 400);
            }

            //Add Validations
            $validator = Validator::make($request->all(), [
                'type' => 'string',
                'name' => 'string',
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            // Generate a unique slug
            $slug = $this->generateUniqueSlug($name, $org->id);

            $allowanceData = [
                "type" => $type,
                "name" => $name,
                "percentage_of" => $percentage_of,
                "slug" => $slug,
                "description" => $description,
                "org_id" => $org->id,
                "added_by" => $user->id,
                'is_exceptional' => $isExceptional,
                'start_date' => $startDate,
                'end_date' => $endDate,
                'is_taxable' => $isTaxable
            ];
            $orgAllowance = $this->organisationRepository->createOrgAllowance($allowanceData);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} created a new allowance record for employees",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Allowance created successfully',
                'data' => $orgAllowance
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Org Allowance 
    public function updateOrgAllowance(Request $request)
    {
        try {
            $user = Auth::user();
            $type = $request->type;
            $percentage_of = $request->percentage_of;
            $name = $request->name;
            $status = $request->status;
            $id = $request->id;
            $description = $request->description;
            $isExceptional = $request->isExceptional;
            $startDate = $request->startDate;
            $endDate = $request->endDate;
            $isTaxable = $request->is_taxable;

            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access allowance settings at the moment',
                ], 400);
            }

            //Add Validations
            $validator = Validator::make($request->all(), [
                'type' => 'string',
                'name' => 'string',
                // 'description' => 'string',
                'status' => 'boolean',
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $allowanceData = [
                "type" => $type,
                "name" => $name,
                "description" => $description,
                "status" => $status,
                'is_exceptional' => $isExceptional,
                'percentage_of' => $percentage_of,
                'start_date' => $startDate,
                'end_date' => $endDate,
                'is_taxable' => $isTaxable

            ];
            $foundAllowance = $this->organisationRepository->getSingleOrgAllowance($id);

            if (empty($foundAllowance)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Allowance not found',
                    'data' => $foundAllowance
                ], 400);
            }

            $orgAllowance = $this->organisationRepository->updateOrgAllowance($allowanceData, $id);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} updated an allowance record",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Allowance updated successfully',
                'data' => $orgAllowance
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Org Allowance
    public function getAllAllowances(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access allowance settings at the moment',
                ], 400);
            }
            $orgAllowance = $this->organisationRepository->getAllOrgAllowance($org->id);

            return response()->json([
                'status' => 'success',
                'message' => 'Allowance returned successfully',
                'data' => $orgAllowance
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Single OrG Allowance
    public function getSingleAllowance(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access allowance settings at the moment',
                ], 400);
            }

            $orgAllowance = $this->organisationRepository->getSingleOrgAllowance($id);

            if (empty($orgAllowance)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Allowance not found',
                    'data' => $orgAllowance
                ], 400);
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Allowance returned successfully',
                'data' => $orgAllowance
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Delete Single OrG Allowance
    public function deleteOrgAllowance(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access allowance settings at the moment',
                ], 400);
            }
            $orgAllowance = $this->organisationRepository->deleteOrgAllowance($id);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} deleted an allowance record for employee",
                "level" => "critical",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Allowance deleted successfully',
                'data' => $orgAllowance
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Add Allowance To Employee 
    public function createEmployeeAllowanceRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $allowanceId = $request->allowanceId;
            $userId = $request->userId;
            $value = $request->value;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access allowance settings at the moment',
                ], 400);
            }

            $userBelongsToOrg = $this->organisationRepository->checkUserInOrg($org->id, $userId);
            if (!$userBelongsToOrg) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'User does not belong to this organisation',
                    'data' => []
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'userId' => 'integer|required',
                'allowanceId' => 'integer',
                'value' => 'integer',
            ]);


            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $allowanceData = [
                "org_id" => $org->id,
                "employee_id" => $userId,
                "allowance_id" => $allowanceId,
                "value" => $value,
            ];

            $allowanceRecord = $this->organisationRepository->createEmployeeAllowanceRecord($allowanceData);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} added an employee with id {$userId} to an allowance record",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Allowance recorded created successfully',
                'data' => $allowanceRecord
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Employee Allowance
    public function updateEmployeeRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $recordId = $request->recordId;
            $allowanceId = $request->allowanceId;
            $value = $request->value;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access allowance settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'allowanceId' => 'integer',
                'value' => 'integer',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            //Check for record
            $existingRecord = $this->organisationRepository->getEmployeeAllowanceRecord($recordId);

            if (empty($existingRecord)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Allowance not found',
                    'data' => $existingRecord
                ], 400);
            }

            $allowanceData = [
                "allowance_id" => $allowanceId,
                "value" => $value,
            ];

            $allowanceRecord = $this->organisationRepository->updateEmployeeAllowanceRecord($recordId, $allowanceData);


            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} updated an allowance record for an employee.",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Allowance recorded updated successfully',
                'data' => $allowanceRecord
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Employee Allowances
    public function getAllEmployeeAllowance(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access allowance settings at the moment',
                ], 400);
            }
            $allowanceRecords = $this->organisationRepository->getAllEmployeesAllowanceRecord($org->id);

            return response()->json([
                'status' => 'success',
                'message' => 'Allowances returned successfully',
                'data' => $allowanceRecords
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Single Employee Allowances
    public function getSingleEmployeeAllowance(Request $request)
    {
        try {
            $user = Auth::user();
            $recordId = $request->recordId;

            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access allowance settings at the moment',
                ], 400);
            }
            $allowanceRecord = $this->organisationRepository->getEmployeeAllowanceRecord($recordId);

            if (empty($allowanceRecord)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Allowance not found',
                    'data' => $allowanceRecord
                ], 400);
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Allowances returned successfully',
                'data' => $allowanceRecord
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Delete Single Employee Allowance
    public function deleteEmployeeAllowance(Request $request)
    {
        try {
            $user = Auth::user();
            $recordId = $request->recordId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access allowance settings at the moment',
                ], 400);
            }
            $employeeAllowance = $this->organisationRepository->deleteEmployeeAllowanceRecord($recordId);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} deleted an allowance for an employee",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Allowance deleted successfully',
                'data' => $employeeAllowance
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Pension Agreements
    public function updatePensionAgreement(Request $request)
    {
        try {
            $user = Auth::user();
            $employee_contribution = $request->employee_contribution;
            $company_contribution = $request->company_contribution;
            $id = $request->id;

            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access pension settings at the moment',
                ], 400);
            }

            //Add Validations
            $validator = Validator::make($request->all(), [
                'employee_contribution' => 'integer',
                'company_contribution' => 'integer',
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }
            $pensionData = [
                "employee_contribution" => $employee_contribution,
                "company_contribution" => $company_contribution
            ];
            $foundPension = $this->organisationRepository->fetchSinglePensionAgreements($id);

            if (empty($foundPension)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Pension agreement not found',
                    'data' => $foundPension
                ], 400);
            }
            $updatePension = $this->organisationRepository->updatePensionAgreement($id, $pensionData);


            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} updated the permission agreement",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Pension updated successfully',
                'data' => $updatePension
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Fetch Pension Agreements
    public function fetchAllPensionAgreements(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access pension settings at the moment',
                ], 400);
            }

            $orgPensions = $this->organisationRepository->fetchPensionAgreements($org->id);
            return response()->json([
                'status' => 'success',
                'message' => 'Pension returned successfully',
                'data' => $orgPensions
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Fetch Single Pension Agreement
    public function fetchSinglePensionAgreement(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access Pension settings at the moment',
                ], 400);
            }

            $orgPension = $this->organisationRepository->fetchSinglePensionAgreements($id);

            if (empty($orgPension)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Pension not found',
                    'data' => $orgPension
                ], 400);
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Pension returned successfully',
                'data' => $orgPension
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Create Employee Pension Record
    public function createEmployeePensionRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $pensionId = $request->pensionId;
            $userId = $request->userId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access Pension settings at the moment',
                ], 400);
            }

            $userBelongsToOrg = $this->organisationRepository->checkUserInOrg($org->id, $userId);
            if (!$userBelongsToOrg) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'User does not belong to this organisation',
                    'data' => []
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'userId' => 'integer|required',
                'pensionId' => 'integer',
            ]);


            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $pensionData = [
                "employee_id" => $userId,
                "org_id" => $org->id,
                "pension_id" => $pensionId
            ];
            $employeePension = $this->organisationRepository->createEmployeePensionRecord($pensionData);


            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} added an employee with id {$userId} to a pension agremment record",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Pension record created successfully',
                'data' => $employeePension
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Employee Pension Record
    public function updateEmployeePensionRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $pensionId = $request->pensionId;
            $recordId = $request->recordId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access Pension settings at the moment',
                ], 400);
            }

            //Add Validations
            $validator = Validator::make($request->all(), [
                'pensionId' => 'integer',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $pensionData = [
                "pension_id" => $pensionId
            ];
            $employeePension = $this->organisationRepository->updateEmployeePensionRecord($recordId, $pensionData);


            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} updated a pension record",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Pension updated created successfully',
                'data' => $employeePension
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Pension Records
    public function getAllPensionsRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access Pension settings at the moment',
                ], 400);
            }
            $employeePensions = $this->organisationRepository->getAllPensionsRecord($org->id);

            return response()->json([
                'status' => 'success',
                'message' => 'Pensions returned successfully',
                'data' => $employeePensions
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Single Pension Record
    public function getSinglePensionRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $recordId = $request->recordId;

            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access Pension settings at the moment',
                ], 400);
            }
            $employeeRecord = $this->organisationRepository->getSinglePensionRecord($recordId);
            if (empty($employeeRecord)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Pension not found',
                    'data' => $employeeRecord
                ], 400);
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Pensions returned successfully',
                'data' => $employeeRecord
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function getSinglePayroll(Request $request)
    {
        try {
            $user = Auth::user();
            $payrollId = $request->payroll_id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access Payroll Run at the moment',
                ], 400);
            }
            $payRollRecord = $this->organisationRepository->getSinglePayRollRecord($payrollId);
            if (empty($payRollRecord)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Payroll not found',
                    'data' => $payRollRecord
                ], 400);
            }

            $employeeDataArray = $payRollRecord->employee_data->toArray();

            $total_allowance = 0;
            $total_deduction = 0;
            $total_bonus = 0;
            $total_non_statutory_deduction = 0;

            $payrollYear = $payRollRecord->year;
            $payrollMonth = $payRollRecord->month;
            $currentDateStart = Carbon::create($payrollYear, $payrollMonth + 1, 1)->startOfMonth();
            $currentDateEnd = Carbon::create($payrollYear, $payrollMonth + 1, 1)->endOfMonth();

            // Loop through each employee
            foreach ($employeeDataArray as $key => $employee) {
                $isProrated = false;
                $prorateReason = null;
                $prorateStartDate = $currentDateStart->format('Y-m-d');
                $prorateEndDate = $currentDateEnd->format('Y-m-d');
                $proratePercentage = 100;

                if (isset($employee['employee']['job_info'])) {
                    $jobInfo = $employee['employee']['job_info'];

                    $hireDate = isset($jobInfo['hire_date']) && !empty($jobInfo['hire_date'])
                        ? Carbon::parse($jobInfo['hire_date'])
                        : null;

                    $terminationDate = isset($jobInfo['termination_date']) && !empty($jobInfo['termination_date'])
                        ? Carbon::parse($jobInfo['termination_date'])
                        : null;

                    if ($hireDate && $hireDate->isAfter($currentDateStart)) {
                        $isProrated = true;
                        $prorateReason = "hired_mid_month";
                        $prorateStartDate = $hireDate->format('Y-m-d');
                    }

                    if ($terminationDate && $terminationDate->between($currentDateStart, $currentDateEnd) && $terminationDate->isBefore($currentDateEnd)) {
                        if ($isProrated) {
                            $prorateReason = "hired_and_terminated_mid_month";
                        } else {
                            $isProrated = true;
                            $prorateReason = "terminated_mid_month";
                        }
                        $prorateEndDate = $terminationDate->format('Y-m-d');
                    }

                    if ($isProrated) {
                        $startDay = Carbon::parse($prorateStartDate);
                        $endDay = Carbon::parse($prorateEndDate);
                        $daysWorked = $endDay->diffInDays($startDay) + 1;
                        $totalDaysInMonth = $currentDateEnd->daysInMonth;
                        $proratePercentage = round(($daysWorked / $totalDaysInMonth) * 100, 2);
                    }

                    $employeeDataArray[$key]['is_prorated'] = $isProrated;
                    $employeeDataArray[$key]['prorate_reason'] = $prorateReason;
                    $employeeDataArray[$key]['prorate_start_date'] = $prorateStartDate;
                    $employeeDataArray[$key]['prorate_end_date'] = $prorateEndDate;
                    $employeeDataArray[$key]['prorate_percentage'] = $proratePercentage;
                }

                // Check if 'non_statutory_deduction_array' exists for the current employee
                if (isset($employee['allowances_array'])) {
                    foreach ($employee['allowances_array'] as $allowance) {
                        // Add the 'amount' to the total sum
                        if (isset($allowance['value'])) {
                            $total_allowance += $allowance['value'];
                        }
                    }
                }

                if (isset($employee['deduction_array'])) {
                    foreach ($employee['deduction_array'] as $deduction) {
                        // Add the 'amount' to the total sum
                        if (isset($deduction['value'])) {
                            $total_deduction += $deduction['value'];
                        }
                    }
                }

                if (isset($employee['bonus_array'])) {
                    foreach ($employee['bonus_array'] as $deduction) {
                        // Add the 'amount' to the total sum
                        if (isset($deduction['amount'])) {
                            $total_bonus += $deduction['amount'];
                        }
                    }
                }

                if (isset($employee['non_statutory_deduction_array'])) {
                    foreach ($employee['non_statutory_deduction_array'] as $deduction) {
                        // Add the 'amount' to the total sum
                        if (isset($deduction['amount'])) {
                            $total_non_statutory_deduction += $deduction['amount'];
                        }
                    }
                }
            }
            $extraSums = [
                'allowance_amount' => $total_allowance,
                'deduction_amount' => $total_deduction,
                'bonus_amount' => $total_bonus,
                'non_statutory_deduction_amount' => $total_non_statutory_deduction,

                'taxable_income_amount' => array_sum(array_column($employeeDataArray, 'taxable_income_amount')),
                'basic_salary_amount' => array_sum(array_column($employeeDataArray, 'basic_salary_amount')),
                'pension_amount' => array_sum(array_column($employeeDataArray, 'pension_amount')),
                'pension_employer_amount' => array_sum(array_column($employeeDataArray, 'pension_employer_amount')),
                'itf_amount' => array_sum(array_column($employeeDataArray, 'itf_amount')),
                'ecs_amount' => array_sum(array_column($employeeDataArray, 'ecs_amount')),
                'cra_amount' => array_sum(array_column($employeeDataArray, 'cra_amount')),
                'tax_amount' => array_sum(array_column($employeeDataArray, 'tax_amount')),
                'gross_amount' => array_sum(array_column($employeeDataArray, 'gross_amount')),
                'payable_amount' => array_sum(array_column($employeeDataArray, 'payable_amount'))
            ];
            $orgAllowances = $this->organisationRepository->getAllOrgAllowance($org->id);
            $orgDeductions = $this->organisationRepository->getAllDeductions($org->id);

            $payRollRecordArray = $payRollRecord->toArray();
            $payRollRecordArray['employee_data'] = $employeeDataArray;

            return response()->json([
                'status' => 'success',
                'message' => 'Payroll returned successfully',
                'allowances' => $orgAllowances,
                'deductions' => $orgDeductions,
                'sums' => $extraSums,
                'data' => $payRollRecordArray
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function getAllPayroll(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access Payroll Run at the moment',
                ], 400);
            }
            $payRollRecord = $this->organisationRepository->getAllPayRollRecords($org->id);
            if (empty($payRollRecord)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Payroll not found',
                    'data' => $payRollRecord
                ], 400);
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Payroll returned successfully',
                'data' => $payRollRecord
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Delete Pension Record
    public function deletePensionRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $recordId = $request->recordId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access Pension settings at the moment',
                ], 400);
            }
            $employeePension = $this->organisationRepository->deletePensionRecord($recordId);


            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} deleted a pension record",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);

            return response()->json([
                'status' => 'success',
                'message' => 'Pension deleted successfully',
                'data' => $employeePension
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }


    //Update Time Settings
    public function createTimeSettings(Request $request)
    {
        try {
            $user = Auth::user();
            $resumption_time = $request->resumptionTime;
            $closing_time = $request->closingTime;
            $default_late_period = $request->defaultLatePeriod;
            $name = $request->name;

            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot update time settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'resumptionTime' => 'string',
                'closingTime' => 'string',
                "defaultLatePeriod" => "integer",
                "name" => "string",
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $timeData = [
                "resumption_time" => Carbon::parse($resumption_time)->format('Y-m-d H:i:s'),
                "closing_time" => Carbon::parse($closing_time)->format('Y-m-d H:i:s'),
                "default_late_period" => $default_late_period,
                "name" => $name,
                "org_id" => $org->id,
            ];

            $timeSettings = $this->organisationRepository->createTimeSettings($timeData);


            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} created a time setting record",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);


            return response()->json([
                'status' => 'success',
                'message' => 'Time created successfully',
                'data' => $timeSettings
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Time Settings
    public function updateTimeSettings(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $resumption_time = $request->resumptionTime;
            $closing_time = $request->closingTime;
            $default_late_period = $request->defaultLatePeriod;
            $name = $request->name;

            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot update time settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'resumptionTime' => 'string',
                'closingTime' => 'string',
                "defaultLatePeriod" => "integer",
                "name" => "string",
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $foundTimeRecord = $this->organisationRepository->getSingleTimeSettings($id);

            if (empty($foundTimeRecord)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Time setting not found here',
                    'data' => $foundTimeRecord
                ], 400);
            }

            $timeData = [
                "resumption_time" => Carbon::parse($resumption_time)->format('Y-m-d H:i:s'),
                "closing_time" => Carbon::parse($closing_time)->format('Y-m-d H:i:s'),
                "default_late_period" => $default_late_period,
                "name" => $name,
                "org_id" => $org->id,
            ];

            $timeSettings = $this->organisationRepository->updateTimeSettings($id, $timeData);


            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} updated a time setting record",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Time settings updated successfully',
                'data' => $timeSettings
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Time Settings
    public function getAllTimeSettings(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access time settings at the moment',
                ], 400);
            }
            $timeSettings = $this->organisationRepository->getTimeSettings($org->id);
            return response()->json([
                'status' => 'success',
                'message' => 'Time settings returned successfully',
                'data' => $timeSettings
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Single Time Settings
    public function getSingleTimeSetting(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access time settings at the moment',
                ], 400);
            }

            $foundTimeRecord = $this->organisationRepository->getSingleTimeSettings($id);

            if (empty($foundTimeRecord)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Time setting not found',
                    'data' => $foundTimeRecord
                ], 400);
            }
            return response()->json([
                'status' => 'success',
                'message' => 'Time settings returned successfully',
                'data' => $foundTimeRecord
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Employee Attendance 
    public function getEmployeeAttendance(Request $request)
    {
        try {
            $user = Auth::user();
            $userId = $request->id;
            $start = $request->start ?? '2020-01-01';
            $end = $request->end ?? '2500-01-01';
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access time settings at the moment',
                ], 400);
            }

            $userBelongsToOrg = $this->organisationRepository->checkUserInOrg($org->id, $userId);
            if (!$userBelongsToOrg) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'User does not belong to this organisation',
                    'data' => []
                ], 400);
            }
            $employeeAttendance = $this->organisationRepository->getEmployeeAttendance($userId, $start, $end);
            return response()->json([
                'status' => 'success',
                'message' => 'Time settings returned successfully',
                'data' => $employeeAttendance
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Employee Attendance 
    public function getEmployeeAllAttendance(Request $request)
    {
        try {
            $user = Auth::user();
            $start = $request->start ?? '2020-01-01';
            $end = $request->end ?? '2500-01-01';
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access time settings at the moment',
                ], 400);
            }
            $employeeAttendance = $this->organisationRepository->getAllEmployeeAttendance($start, $end, $org->id);
            return response()->json([
                'status' => 'success',
                'message' => 'Time attendances returned successfully',
                'data' => $employeeAttendance
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Generate Payroll 

    public function generatePayrollExcel(Request $request, $payroll_Id)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access time settings at the moment',
                ], 400);
            }

            $payRollRecord = $this->organisationRepository->getSinglePayRollRecord($payroll_Id);
            $data = [];
            foreach ($payRollRecord->employee_data as $key => $item) {
                $data[] = [
                    'Employee ID' => $item['employee_id'],
                    'Payroll ID' => $payRollRecord['id'],
                    'Name' => $item->employee->profile?->first_name . ' ' . $item->employee->profile?->middle_name . ' ' . $item->employee->profile?->last_name,
                    'Department' => !empty($item->employee->jobInfo->department?->name) ? $item->employee->jobInfo->department->name : "Not Set",
                    'Employment Type' => !empty($item->employee->jobInfo->employment_type_id) ? $item->employee->jobInfo->employment_type_id : "Not Set",
                    'PayGroup' => !empty($payRollRecord->pay_group) ? $payRollRecord->pay_group : "Monthly",
                    'Payment Status' => $item['payment_status'],
                    'Basic Salary' => !empty($item['basic_salary_amount']) ? $item['basic_salary_amount'] : "0.00",
                    'Allowances' => !empty($item['allowance_amount']) ? $item['allowance_amount'] : "0.00",
                    'Bonuses' => !empty($item['bonus_amount']) ? $item['bonus_amount'] : "0.00",
                    'Deductions' => !empty($item['deduction_amount']) ? $item['deduction_amount'] : '0.00',
                    'Non Statutory Deductions' => !empty($item['non_statutory_deduction_amount']) ? $item['non_statutory_deduction_amount'] : '0.00',
                    'Pension(employee)' => !empty($item['pension_amount']) ? $item['pension_amount'] : '0.00',
                    'Pension(employer)' => !empty($item['pension_employer_amount']) ? $item['pension_employer_amount'] : '0.00',
                    'ECS' => !empty($item['ecs_amount']) ? $item['ecs_amount'] : "0.00",
                    'ITF' => !empty($item['itf_amount']) ? $item['itf_amount'] : "0.00",
                    'CRA' => !empty($item['cra_amount']) ? $item['cra_amount'] : "0.00",
                    'Tax' => !empty($item['tax_amount']) ? $item['tax_amount'] : "0.00",
                    'Gross Pay' => !empty($item['gross_amount']) ? $item['gross_amount'] : "0.00",
                    'Payable Amount' => !empty($item['payable_amount']) ? $item['payable_amount'] : "0.00",
                    'Bank Name' => $item->employee->bankInfo?->bank_name ?? '',
                    'Bank Code' => $item->employee->bankInfo?->bank_code ?? '',
                    'Account Number' => $item->employee->bankInfo?->account_number ?? '',
                    'Account Name' => $item->employee->bankInfo?->account_name ?? '',
                ];
            }
            $export = new PayrollExport($data);

            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} generated a payroll record",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return Excel::download($export, 'payroll for-' . $payRollRecord->year . '-' . $payRollRecord->month . '.xlsx');
        } catch (Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Calculate Payrate based on payroll 
    public function calculatePayrate($jobProfile, $type)
    {

        if (empty($jobProfile['pay_rate']) || empty($jobProfile['pay_frequency']) || empty($jobProfile['user_id'])) {

            throw new \InvalidArgumentException('Invalid job profile data provided. ' . $jobProfile['user_id']);
        }
        //Fetch current payrate against days of month 
        $payRate = (float) $jobProfile['pay_rate'];
        $daysInMonth = Carbon::now()->daysInMonth;
        $dailyPayRate = (int) $payRate / $daysInMonth;
        $hourlyPayRate = $jobProfile['pay_frequency'] === 'hourly' ? $payRate : 0;

        //Let Check for user payroll type 
        if ($type === 'weekly') {
            // Weekly cycle: Start from 7 days ago until today
            $startDate = Carbon::now()->subDays(7)->startOfDay();
            $endDate = Carbon::now()->endOfDay();
        } else if ($type === 'bi-weekly') {
            // Bi-weekly cycle: Start from 14 days ago until today
            $startDate = Carbon::now()->subDays(14)->startOfDay();
            $endDate = Carbon::now()->endOfDay();
        } else if ($type === "monthly") {
            // Monthly cycle: Start from the beginning of the current month until today
            $startDate = Carbon::now()->startOfMonth();
            $endDate = Carbon::now()->endOfDay();
        } else {
            throw new \InvalidArgumentException("Invalid payroll type: $type");
        }

        //check for pay frequency type
        if ($jobProfile['pay_frequency'] == 'hourly') {

            // Check how long (in minutes) user worked in a month
            $workMinutes = $this->organisationRepository->getWorkHours($startDate, $endDate, $jobProfile['user_id']);

            // Sum the total work minutes and convert to hours, Check for overtime
            $totalWorkMinutes = $workMinutes->sum('total_work_minutes') ?? 0;
            $totalOverTimeMinutes = $workMinutes->sum('total_overtime_minutes') ?? 0;
            $workHours = $totalWorkMinutes / 60;
            $overTimeHours = $totalOverTimeMinutes / 60;

            //Calcutate Overtime Pay & hourly pay
            $finalHourlyPay = $hourlyPayRate * $workHours;
            $finalOverTimePay = ($jobProfile['overtime_rate'] ?? 0) * $overTimeHours;

            return round($finalHourlyPay + $finalOverTimePay, 2);
        } else {
            return $this->calculateProratedPay($jobProfile);
        }
    }

    public function calculateUnpaidLeave($employeeId)
    {
        $jobProfile = $this->userRepository->getJobProfileByUser($employeeId);
        if (empty($jobProfile['pay_rate']) || empty($jobProfile['pay_frequency']) || empty($jobProfile['user_id'])) {
            throw new \InvalidArgumentException('Invalid job profile data provided.');
        }
        // Fetch current pay rate against days of month
        $payRate = (float) $jobProfile['pay_rate'];
        $payFrequency = $jobProfile['pay_frequency'];
        $daysInMonth = Carbon::now()->daysInMonth;

        // Calculate daily and hourly pay rates
        $dailyPayRate = $payFrequency === 'monthly' ? $payRate / $daysInMonth : 0;
        $hourlyPayRate = $payFrequency === 'hourly' ? $payRate : 0;

        // Fetch Employee Leave Fee
        $leaveFees = $this->organisationRepository->getLeavesFee($employeeId);

        // Initialize unpaid leave costs
        $unpaidLeaveHourly = 0;
        $unpaidLeaveMonthly = 0;

        // Loop through leave fees
        foreach ($leaveFees as $leaveFee) {
            if ($leaveFee['type'] === 'hourly') {
                $unpaidLeaveHourly += $leaveFee['hours'] * $hourlyPayRate;
            } elseif ($leaveFee['type'] === 'monthly') {
                $unpaidLeaveMonthly += $leaveFee['days'] * $dailyPayRate;
            }
        }

        // Return unpaid leave amount based on employee's pay frequency
        return $payFrequency === 'hourly' ? $unpaidLeaveHourly : $unpaidLeaveMonthly;
    }

    private function calculateProratedPay(array $jobProfile)
    {
        $payRate = $jobProfile['is_annual_pay']
            ? (float) ($jobProfile['pay_rate'] ?? 0) / 12
            : (float) ($jobProfile['pay_rate'] ?? 0);

        $altHireDate = Carbon::parse($jobProfile['created_at'])->firstOfMonth();
        $hireDate = isset($jobProfile['hire_date']) ? Carbon::parse($jobProfile['hire_date']) : $altHireDate;
        $currentDate = Carbon::now()->startOfMonth();
        $terminationDate = isset($jobProfile['termination_date']) ? Carbon::parse($jobProfile['termination_date']) : null;

        $totalDaysInMonth = $currentDate->daysInMonth; // Total days in the current month
        $startDay = 1; // Default to the first day of the month
        $endDay = $totalDaysInMonth; // Default to the last day of the month
        // $daysWorked = $endDay;
        // Adjust start day if hire date is in the current month
        if ($hireDate->isSameMonth($currentDate)) {
            $startDay = $hireDate->day;
        }

        // Adjust end day if termination date is in the current month
        if ($terminationDate && $terminationDate->isSameMonth($currentDate)) {
            $endDay = $terminationDate->day;
        }

        // Calculate days worked
        $daysWorked = max(0, $endDay - $startDay + 1); // Ensure no negative days worked

        // Prorate the pay based on days worked
        return ($payRate / $totalDaysInMonth) * $daysWorked;
    }


    public function calculateHourlyPay($payload, $type)
    {
        $jobInfo = $payload;

        //Check If Pay is Hourly 
        if ($jobInfo['pay_frequency'] == 'hourly') {

            //Fetch current payrate against hours of month 
            $hourlyPayRate = $jobInfo['pay_rate'];
            // $daysInMonth = Carbon::now()->daysInMonth;
            // $hoursInMonth = $daysInMonth * 24;
            // $hourlyPayRate = (int) $payRate / $hoursInMonth;

            //Let Check for user payroll type 
            if ($type === 'weekly') {
                // Weekly cycle: Start from 7 days ago until today
                $startDate = Carbon::now()->subDays(7)->startOfDay();
                $endDate = Carbon::now()->endOfDay();
            } else if ($type === 'bi-weekly') {
                // Bi-weekly cycle: Start from 14 days ago until today
                $startDate = Carbon::now()->subDays(14)->startOfDay();
                $endDate = Carbon::now()->endOfDay();
            } else if ($type === "monthly") {
                // Monthly cycle: Start from the beginning of the current month until today
                $startDate = Carbon::now()->startOfMonth();
                $endDate = Carbon::now()->endOfDay();
            } else {
                throw new \InvalidArgumentException("Invalid payroll type: $type");
            }

            // Check how long (in minutes) user worked in a month
            $workMinutes = $this->organisationRepository->getWorkHours($startDate, $endDate, $jobInfo['user_id']);

            // Sum the total work minutes and convert to hours, Check for overtime
            $totalWorkMinutes = $workMinutes->sum('total_work_minutes') ?? 0;
            $totalOverTimeMinutes = $workMinutes->sum('total_overtime_minutes') ?? 0;
            $workHours = $totalWorkMinutes / 60;
            $overTimeHours = $totalOverTimeMinutes / 60;

            //Calcutate Overtime Pay & hourly pay
            $finalHourlyPay = $hourlyPayRate * $workHours;
            $finalOverTimePay = ($jobInfo['overtime_rate'] ?? 0) * $overTimeHours;

            //Return pay.
            return round($finalHourlyPay + $finalOverTimePay, 2);
        }
    }
    //Pension Calculator
    // public function calculatePension($employeeId, $orgId, $type)
    // {
    //     // Fetch job profile
    //     $jobProfile = $this->userRepository->getJobProfileByUser($employeeId);
    //     if (!$jobProfile) {
    //         throw new \Exception("Job profile not found for employee ID: {$employeeId}");
    //     }

    //     // Get employee allowances
    //     $employeeRecord = !empty($jobProfile["pay_grade"])
    //         ? ($jobProfile['pay_grade']['allowances'] ?? [])
    //         : ($this->organisationRepository->getPersonalAllowanceRecord($employeeId) ?? []);

    //     // Fetch Transport & Housing Allowance
    //     $transportAllowance = $this->organisationRepository->getSingleOrgAllowanceType('transport', $orgId);
    //     $housingAllowance = $this->organisationRepository->getSingleOrgAllowanceType('housing', $orgId);

    //     // if (!$transportAllowance || !$housingAllowance) {
    //     //     throw new \Exception("Transport or Housing Allowance data is missing for Org ID: {$orgId}");
    //     // }

    //     $transportAllowanceId = $transportAllowance->id ?? null;
    //     $housingAllowanceId = $housingAllowance->id ?? null;

    //     // Initialize allowance values
    //     $transportAllowanceValue = 0;
    //     $housingAllowanceValue = 0;
    //     $otherAllowances = 0;
    //     $datat = [];
    //     // Process employee allowances
    //     foreach ($employeeRecord as $allowance) {
    //         $allowance = json_decode(json_encode($allowance), true);


    //         // Check validity of allowance based on start & end dates
    //         $currentDate = Carbon::now();
    //         $startDate = !empty($allowance['start_date']) ? Carbon::parse($allowance['start_date']) : null;
    //         $endDate = !empty($allowance['end_date']) ? Carbon::parse($allowance['end_date']) : null;

    //         $isValidDate = (!$startDate || !$endDate) || ($startDate && $endDate && $currentDate->between($startDate, $endDate));

    //         // Get allowance value (annual adjustment)
    //         $value = $isValidDate
    //             ? ($allowance['is_annual'] ? ($allowance['value'] ?? $allowance['allowance_value']) / 12 : ($allowance['value'] ?? $allowance['allowance_value']))
    //             : 0;

    //         // Calculate salary value
    //         $salaryValue = ($this->calculatePayrate($jobProfile, $type) * $value / 100);

    //         // array_push($datat, $allowance, $allowance['org_id'],$allowance['organisation_allowance']);

    //         if (isset($allowance['organisation_allowance'])) {

    //             $orgAllowance = $allowance['organisation_allowance'];
    //             if ($orgAllowance['type'] === 'percentage') {
    //                 $salaryValue = ($orgAllowance['percentage_of'] === "gross_salary" && $jobProfile['gross_amount'] > 0)
    //                     ? $jobProfile['gross_amount'] * ($value / 100)
    //                     : ($this->calculatePayrate($jobProfile, $type) * $value / 100);
    //             } else {
    //                 $salaryValue = $value;
    //             }
    //         }

    //         // Categorize allowances
    //         if ($allowance['allowance_id'] == $transportAllowanceId) {
    //             $transportAllowanceValue = $salaryValue;
    //         } elseif ($allowance['allowance_id'] == $housingAllowanceId) {
    //             $housingAllowanceValue = $salaryValue;
    //         } else {
    //             $otherAllowances += $salaryValue;
    //         }
    //     }

    //     // Get pension percentage
    //     $pensionPercentage = $jobProfile['pay_grade']['pension_percentage'] ?? $jobProfile['pension_percentage'] ?? 0;

    //     // Determine pensionable salary base
    //     $salaryBase = $this->calculatePayrate($jobProfile, $type) + ($transportAllowanceValue ?: 0) + ($housingAllowanceValue ?: 0);
    //     if ($transportAllowanceValue == 0 && $housingAllowanceValue == 0) {
    //         // use gross
    //         $salaryBase += $otherAllowances;
    //     }
    //     // return [$datat, $this->calculatePayrate($jobProfile, $type), $transportAllowanceValue, $housingAllowanceValue, $salaryBase];
    //     // Calculate pension contributions
    //     $pensionEmployee = $salaryBase * ($pensionPercentage / 100);
    //     if ($pensionPercentage > 0) {
    //         $pensionEmployer = $salaryBase * ((18 - max(0, $pensionPercentage)) / 100);
    //     } else {
    //         $pensionEmployer = 0;
    //     }

    //     return ['employee' => $pensionEmployee, 'employer' => $pensionEmployer];
    // }
    public function calculatePension($employeeId, $orgId, $type)
    {
        // -----------------------------
        // 1. Fetch job profile
        // -----------------------------
        $jobProfile = $this->userRepository->getJobProfileByUser($employeeId);
        if (!$jobProfile) {
            throw new \Exception("Job profile not found for employee ID: {$employeeId}");
        }

        // -----------------------------
        // 2. Get employee allowances
        // -----------------------------
        $employeeRecord = [];
        if (!empty($jobProfile['pay_grade'])) {
            $employeeRecord = $jobProfile['pay_grade']['allowances'] ?? [];
        } else {
            $employeeRecord = $this->organisationRepository->getPersonalAllowanceRecord($employeeId) ?? [];
        }
        $basePay = $this->calculatePayrate($jobProfile, $type);

        // -----------------------------
        // 3. Fetch Transport & Housing Allowance
        // -----------------------------
        $transportAllowance = $this->organisationRepository->getSingleOrgAllowanceType('transport', $orgId);
        $housingAllowance = $this->organisationRepository->getSingleOrgAllowanceType('housing', $orgId);

        $transportAllowanceId = $transportAllowance->id ?? null;
        $housingAllowanceId = $housingAllowance->id ?? null;

        // -----------------------------
        // 4. Initialize allowance values
        // -----------------------------
        $transportAllowanceValue = 0;
        $housingAllowanceValue = 0;
        $otherAllowances = 0;

        // -----------------------------
        // 5. Process employee allowances
        // -----------------------------
        foreach ($employeeRecord as $allowanceRaw) {
            $allowance = json_decode(json_encode($allowanceRaw), true);

            // Validity check based on start & end dates
            $currentDate = \Carbon\Carbon::now();
            $startDate = !empty($allowance['start_date']) ? \Carbon\Carbon::parse($allowance['start_date']) : null;
            $endDate = !empty($allowance['end_date']) ? \Carbon\Carbon::parse($allowance['end_date']) : null;

            $isValidDate = (!$startDate && !$endDate) || ($startDate && $endDate && $currentDate->between($startDate, $endDate));

            // Allowance value
            $rawValue = $allowance['value'] ?? $allowance['allowance_value'] ?? 0;
            $value = $isValidDate ? ($allowance['is_annual'] ? $rawValue / 12 : $rawValue) : 0;


            // Handle organisation allowance
            if (isset($allowance['organisation_allowance'])) {
                $orgAllowance = $allowance['organisation_allowance'];

                if (!empty($orgAllowance['type']) && $orgAllowance['type'] === 'percentage') {
                    if (($orgAllowance['percentage_of'] ?? '') === "gross_salary" && !empty($jobProfile['gross_amount'])) {
                        $baseSalary = $jobProfile['is_annual_pay']
                            ? $jobProfile['gross_amount']
                            : $jobProfile['gross_amount'] / 12;

                        $salaryValue = $baseSalary * ($value / 100);

                    } elseif (($orgAllowance['percentage_of'] ?? '') === "basic_salary" && !empty($jobProfile['pay_rate'])) {
                        $salaryValue = $basePay * ($value / 100);
                    } else {
                        $salaryValue = $basePay * ($value / 100);
                    }

                    // $salaryValue = $allowance['is_annual'] ? $value / 12 : $value;
                } else {
                    // Fixed value allowance
                    $salaryValue = $value;
                }
            }

            // Categorize allowances
            if (($allowance['allowance_id'] ?? null) == $transportAllowanceId) {
                $transportAllowanceValue = $salaryValue;
            } elseif (($allowance['allowance_id'] ?? null) == $housingAllowanceId) {
                $housingAllowanceValue = $salaryValue;
            } else {
                $otherAllowances += $salaryValue;
            }
        }

        // -----------------------------
        // 6. Pension percentage
        // -----------------------------
        $pensionPercentage = $jobProfile['pay_grade']['pension_percentage'] ?? $jobProfile['pension_percentage'] ?? 0;

        // -----------------------------
        // 7. Pensionable salary base
        // -----------------------------

        $salaryBase = $basePay + $transportAllowanceValue + $housingAllowanceValue;

        // -----------------------------
        // 8. Calculate pension contributions
        // -----------------------------
        $pensionEmployee = $salaryBase * ($pensionPercentage / 100);
        $pensionEmployer = ($pensionPercentage > 0) ? $salaryBase * ((18 - max(0, $pensionPercentage)) / 100) : 0;



        // -----------------------------
        // 9. Return results
        // -----------------------------
        return [
            'employee' => $pensionEmployee,
            'employer' => $pensionEmployer,
            'housingAllowanceValue' => $housingAllowanceValue
        ];
    }




    //Basic Pay Calculator
    public function calculateBasicPay($employeeId, $orgId, $type)
    {
        //Fetch basic Salary
        $jobProfile = $this->userRepository->getJobProfileByUser($employeeId);
        $basicPay = $this->calculatePayrate($jobProfile, $type);
        return $basicPay;
    }
    //Allowance Calulator
    public function calculateAllowance($employeeId, $orgId, $type)
    {

        //Fetch basic Salary
        $jobProfile = $this->userRepository->getJobProfileByUser($employeeId);

        // if (!empty($jobProfile["pay_grade"])) {
        //     // Find Allowances For EmployeeId if pay_grade exists
        //     $employeeRecord = $jobProfile['pay_grade']['allowances'] ?? [];
        // } else {
        //     // Find Allowances For EmployeeId if pay_grade does not exist
        //     $employeeRecord = $jobProfile['allowances'];
        //     //    $this->organisationRepository->getPersonalAllowanceRecord($employeeId);
        // }

        $employeeRecord = $jobProfile['allowances'];

        if (!$employeeRecord) {
            return ['value' => 0, 'array' => []];
        }

        // return $employeeRecord
        // Initialize total allowance value
        $totalAllowanceValue = 0;

        $allowances_array = [];
        if (is_array($employeeRecord) && !empty($employeeRecord)) {
            // Check if this allowance exists in the employee records
            foreach ($employeeRecord as $allowance) {
                $relativeValue = 0;
                $currentDate = Carbon::now();

                $startDate = !empty($allowance['start_date']) ? Carbon::parse($allowance['start_date']) : null;
                $endDate = !empty($allowance['end_date']) ? Carbon::parse($allowance['end_date']) : null;
                //Check if it falls under start and end date and Divide By 12 If its annual
                if ($currentDate->between($startDate, $endDate)) {
                    $value = $allowance['is_annual']
                        ? ($allowance['value'] ?? $allowance['allowance_value']) / 12
                        : ($allowance['value'] ?? $allowance['allowance_value']);
                } elseif (empty($allowance['start_date']) && empty($allowance['end_date'])) {

                    if (isset($allowance) && isset($allowance['allowance_value'])) {
                        $value = $allowance['is_annual']
                            ? ($allowance['value'] ?? $allowance['allowance_value']) / 12
                            : ($allowance['value'] ?? $allowance['allowance_value']);
                    }
                } else {

                    $value = 0; // No allowance if the payroll date is outside the range
                }

                $basePay = $this->calculatePayrate($jobProfile, $type);

                if (isset($allowance['organisation_allowance'])) {
                    if ($allowance['organisation_allowance']['type'] == 'percentage') {

                        if ($allowance['organisation_allowance']['percentage_of'] == "gross_salary" && $jobProfile['gross_amount'] > 0) {
                            $relativeValue = $jobProfile['gross_amount'] * ($value / 100);
                        } else if ($allowance['organisation_allowance']['percentage_of'] == "basic_salary") {
                            $relativeValue = $basePay * ($value / 100);
                        } else {
                            $relativeValue = ($basePay * $value / 100);
                        }
                    } else {
                        $relativeValue = $value;
                    }

                    array_push($allowances_array, ['allowance_id' => $allowance['allowance_id'], 'name' => $allowance['organisation_allowance']['name'], 'value' => $relativeValue]);
                    // Add the relative value to total allowance value
                }
                $totalAllowanceValue += $relativeValue;
            }
        }
        return ['value' => $totalAllowanceValue, 'array' => $allowances_array];
    }


    public function calculateDeduction($employeeId, $orgId, $type)
    {

        //Fetch basic Salary
        $jobProfile = $this->userRepository->getJobProfileByUser($employeeId);

        // Use jobProfile['deductions'] if present, else fallback to pay_grade or repository
        if (!empty($jobProfile['deductions']) && is_array($jobProfile['deductions'])) {
            $employeeRecord = $jobProfile['deductions'];
        } else if (!empty($jobProfile["pay_grade"])) {
            $employeeRecord = $jobProfile['pay_grade']['deductions'] ?? [];
        } else {
            $employeeRecord = $this->organisationRepository->getPersonalAllowanceRecord($employeeId);
        }

        if (!$employeeRecord) {
            return ['value' => 0, 'array' => []];
        }

        $totalDeductionValue = 0;
        $deductions_array = [];
        if (is_array($employeeRecord) && !empty($employeeRecord)) {
            foreach ($employeeRecord as $deduction) {
                $relativeValue = 0;
                $currentDate = Carbon::now();
                $startDate = !empty($deduction['start_date']) ? Carbon::parse($deduction['start_date']) : null;
                $endDate = !empty($deduction['end_date']) ? Carbon::parse($deduction['end_date']) : null;
                // If both dates are empty, treat as always valid (like allowance logic)
                if ((empty($deduction['start_date']) && empty($deduction['end_date'])) || $currentDate->between($startDate, $endDate)) {
                    $value = $deduction['is_annual']
                        ? ($deduction['value'] ?? $deduction['deduction_value']) / 12
                        : ($deduction['value'] ?? $deduction['deduction_value']);
                } else {
                    $value = 0;
                }
                if (isset($deduction['deduction'])) {
                    if ($deduction['deduction']['type'] == 'percentage') {
                        if ($value <= 100) {
                            $relativeValue = ($this->calculatePayrate($jobProfile, $type) * $value / 100);
                        }
                    } else {
                        $relativeValue = $value;
                    }
                    $deductions_array[] = [
                        'deduction_id' => $deduction['deduction_id'],
                        'name' => $deduction['deduction']['name'],
                        'value' => $relativeValue
                    ];
                }
                $totalDeductionValue += $relativeValue;
            }
        }
        return ['value' => $totalDeductionValue, 'array' => $deductions_array];
    }

    public function calculateDeductionSingle($employeeId, $orgId, $selectedDeductions, $type)
    {
        // Find Deductions For EmployeeId
        //Fetch basic Salary
        $jobProfile = $this->userRepository->getJobProfileByUser($employeeId);

        // Use jobProfile['deductions'] if present, else fallback to pay_grade or repository
        if (!empty($jobProfile['deductions']) && is_array($jobProfile['deductions'])) {
            $employeeRecord = $jobProfile['deductions'];
        } else if (!empty($jobProfile["pay_grade"])) {
            $employeeRecord = $jobProfile['pay_grade']['deductions'] ?? [];
        } else {
            $employeeRecord = $this->organisationRepository->getPersonalAllowanceRecord($employeeId);
        }

        if (!$employeeRecord) {
            return ['value' => 0, 'array' => []];
        }

        $totalDeductionValue = 0;
        $deductions_array = [];

        if (is_array($employeeRecord) && !empty($employeeRecord)) {
            foreach ($employeeRecord as $deduction) {
                if (!in_array($deduction['deduction_id'], $selectedDeductions)) {
                    continue;
                }
                $relativeValue = 0;
                $currentDate = Carbon::now();
                $startDate = !empty($deduction['start_date']) ? Carbon::parse($deduction['start_date']) : null;
                $endDate = !empty($deduction['end_date']) ? Carbon::parse($deduction['end_date']) : null;
                if ($currentDate->between($startDate, $endDate)) {
                    $value = $deduction['is_annual']
                        ? ($deduction['value'] ?? $deduction['deduction_value']) / 12
                        : ($deduction['value'] ?? $deduction['deduction_value']);
                } else {
                    $value = 0;
                }
                if (isset($deduction['deduction'])) {
                    if ($deduction['deduction']['type'] == 'percentage') {
                        if ($value <= 100) {
                            $relativeValue = ($this->calculatePayrate($jobProfile, $type) * $value / 100);
                        }
                    } else {
                        $relativeValue = $value;
                    }
                    $deductions_array[] = [
                        'deduction_id' => $deduction['deduction_id'],
                        'name' => $deduction['deduction']['name'],
                        'value' => $relativeValue
                    ];
                }
                $totalDeductionValue += $relativeValue;
            }
        }
        return ['value' => $totalDeductionValue, 'array' => $deductions_array];
    }


    public function calculateCRA($employeeId, $orgId, $totalAllowanceAmount, $askForpension, $type)
    {

        return 0;
        // Fetch Basic Salary
        // $jobProfile = $this->userRepository->getJobProfileByUser($employeeId);
        // $base_salary = $this->calculatePayrate($jobProfile, $type);

        // $gross_income = (($base_salary + $totalAllowanceAmount) - $askForpension) * 12; // per annum

        // // $gross_income = (($base_salary + $totalAllowanceAmount) - $askForpension) * 12; // per annum

        // //   remove pension , remove housing fund where application 
        // // Calculate CRA
        // $cra_first_component = max(200000, 0.01 * $gross_income);
        // $cra_second_component = 0.20 * $gross_income;
        // return $totalCRA = (($cra_first_component + $cra_second_component) / 12) + $askForpension;
    }

    public function calculateTaxRelief(
        $askForPension,
        $annualRentPaid = 0
    ) {
        // Fetch Basic Salary
        /**
         * NEW TAX RELIEF (Rent Relief)
         * 20% of rent paid, capped at ₦500,000 per annum
         */
        $annualRentRelief = min(0.20 * $annualRentPaid, 500000);
        // Convert to monthly relief
        $monthlyRentRelief = $annualRentRelief / 12;
        // Return monthly relief + pension (still deductible)
        return $monthlyRentRelief + $askForPension;
    }


    public function calculateTax($employeeId, $orgId, $taxable_income_amount)
    {
        // Fetch Job Profile
        $jobProfile = $this->userRepository->getJobProfileByUser($employeeId);
        if (!empty($jobProfile["pay_grade"]) && isset($jobProfile['pay_grade']['is_taxable'])) {
            if ($jobProfile['pay_grade']['is_taxable'] == false) {
                return 0; // No tax if not taxable
            }
        }

        // Fetch Tax Settings from Database
        $orgTaxes = $this->organisationRepository->getTaxSettings($orgId);
        if (!$orgTaxes || empty($orgTaxes)) {
            return false; // No tax settings found
        }

        // Convert monthly income to annual income
        $total_income = $taxable_income_amount * 12; // Per annum
        $calculatedIncome = $total_income;

        // Initialize tax
        $totalTax = 0;
        $table = [];

        $orgTaxes = collect($orgTaxes)->sortBy('salary_range')->values()->all();
        $data = [$taxable_income_amount, $calculatedIncome, $orgTaxes];

        // Calculate tax based on the progressive tax system
        foreach ($orgTaxes as $index => $orgTax) {
            if ($calculatedIncome >= $orgTax->salary_range) {
                $totalTax += ($orgTax->salary_range * $orgTax->percentage / 100);
                $calculatedIncome -= $orgTax->salary_range;
            } else {
                // Apply the last tax rate to the remaining income
                $totalTax += ($calculatedIncome * $orgTax->percentage / 100);
                $calculatedIncome = 0; // Ensure no further deductions
                break;
            }
        }

        // If there's any remaining income, apply the last tax bracket
        if ($calculatedIncome > 0) {
            $lastBracket = end($orgTaxes);
            $totalTax += ($calculatedIncome * $lastBracket->percentage / 100);
        }

        // Convert annual tax to monthly tax
        $monthlyTax = round($totalTax / 12, 2, PHP_ROUND_HALF_UP);

        return max(0, $monthlyTax); // Ensure tax isn't negative
    }

    //Run calculator
    public function runCalculator(Request $request)
    {
        try {
            $employeeId = $request->employeeId;
            $jobProfile = $this->userRepository->getJobProfileByUser($employeeId);
            $type = $request->type;

            // if (!empty($jobProfile["pay_grade"])) {
            //     // Find Allowances For EmployeeId if pay_grade exists
            //     $employeeRecord = $jobProfile['pay_grade']['allowances'] ?? [];
            // } else {
            //     // Find Allowances For EmployeeId if pay_grade does not exist
            //     $employeeRecord = $jobProfile['allowances'];
            //     //    $this->organisationRepository->getPersonalAllowanceRecord($employeeId);
            // }

            $employeeRecord = $jobProfile;
            return response()->json([
                'status' => 'success',
                'message' => 'Calculator Ran',
                'data' => $employeeRecord
            ], 200);
        } catch (Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    // payroll run
    public function runPayroll(Request $request)
    {
        //dd("Hello");
        // try {
        $data = $request->all();
        $payrollId = $data['payroll_id'];
        // get the payroll and use the type  

        $employees = isset($data['employees']['employees']) ? $data['employees']['employees'] : $data['employees'];
        if (isset($payrollId)) {
            $oldPayroll = Payroll::findOrFail($payrollId);
            $data['payroll_type'] = $oldPayroll['payrollStart']['payroll_type'];
            $data['payroll_start']['date']['month'] = $oldPayroll['payrollStart']['date']['month'];
            $data['payroll_start']['date']['year'] = $oldPayroll['payrollStart']['date']['year'];
            $data['payroll_start']['pay_group'] = $oldPayroll['payrollStart']['pay_group'];
            $data['taxSet'] = $oldPayroll['payrollItems']['taxSet'];
            $data['ecsSet'] = $oldPayroll['payrollItems']['ecsSet'];
            $data['itfSet'] = $oldPayroll['payrollItems']['itfSet'];
            $data['pensionSet'] = $oldPayroll['payrollItems']['pensionSet'];
        }
        $payroll_start = $data['payroll_start'];
        $payrollDuration = $payroll_start['payroll_duration'];

        $payroll_type = $data['payroll_type'] ?? 'statutory';
        $taxSet = $data['taxSet'] ?? true;
        $pensionSet = $data['pensionSet'] ?? true;
        $ecsSet = $data['ecsSet'] ?? true;
        $itfSet = $data['itfSet'] ?? true;
        $selectedAllowances = $data["selectedAllowances"] ?? [];
        $selectedDeductions = $data["selectedDeductions"] ?? [];
        $payrollAction = $data['payroll_action'] ?? 'run';
        $employee_data = [];

        $user = Auth::user();


        $payrollItems = [
            'payroll_type' => $payroll_type,
            'taxSet' => $taxSet,
            'pensionSet' => $pensionSet,
            'ecsSet' => $ecsSet,
            'itfSet' => $itfSet,
            'selectedAllowances' => $selectedAllowances,
            'selectedDeductions' => $selectedDeductions
        ];

        //Check what kind of payroll the user selects
        if ($payroll_type == 'employee_payment') {
            foreach ($employees as $key => $employee) {

                $jobProfile = $this->userRepository->getJobProfileByUser($employee['id']);

                $basic_amount = $this->calculateBasicPay($employee['id'], $employee['organisation_id'], $payrollDuration);
                $unpaidLeave = $this->calculateUnpaidLeave($employee['id']);

                $penCal = $this->calculatePension($employee['id'], $employee['organisation_id'], $payrollDuration);
                $pension_amount = $pensionSet ? ($penCal['employee'] ?? 0.00) : 0.00;
                $pension_employer_amount = $pensionSet ? $penCal['employer'] : 0.00;

                $housingAllowanceValue = $penCal['housingAllowanceValue'] ?? 0.00;

                $allowances_array = [];
                $allowance_amount = 0.00;



                // if (isset($employee['job_info']['allowances']) && is_array($employee['job_info']['allowances'])) {
                //     foreach ($employee['job_info']['allowances'] as $allowance) {
                //         // Match against selectedAllowances using allowance_id
                //         if (in_array($allowance['allowance_id'], $selectedAllowances)) {
                //             $allowances_array[] = $allowance;
                //             $allowance_amount += $allowance['value'] ?? 0;
                //         }
                //     }
                // }


                $deduction_array = [];
                $deduction_amount = 0;

                // if (isset($employee['job_info']['deductions']) && is_array($employee['job_info']['deductions'])) {
                //     foreach ($employee['job_info']['deductions'] as $deduction) {
                //         // Match against selectedDeductions using deduction_id
                //         if (in_array($deduction['deduction_id'], $selectedDeductions)) {
                //             $deduction_array[] = $deduction;
                //             $deduction_amount += $deduction['value'] ?? 0;
                //         }
                //     }
                // }

                $allowances = $this->calculateAllowance($employee['id'], $employee['organisation_id'], $payrollDuration);
                $deductions = $this->calculateDeduction($employee['id'], $employee['organisation_id'], $payrollDuration);
                $allowance_amount = $allowances['value'];
                $allowances_array = $allowances['array'];


                if (is_array($deductions)) {
                    $deduction_amount = $deductions['value'];
                } else {
                    $deduction_amount = 0;
                }

                if (is_array($deductions)) {
                    $deduction_array = $deductions['array'];
                } else {
                    $deduction_array = [];
                }



                $bonuses_array = $employee['bonuses'];
                $bonuses_amount = array_sum(array_column($bonuses_array, 'amount'));
                $non_statutory_deduction_array = $employee['non_statutory_deductions'];
                $non_statutory_deduction_amount = array_sum(array_column($non_statutory_deduction_array, 'amount'));
                // $cra_amount = $this->calculateCRA($employee['id'], $employee['organisation_id'], $allowance_amount, $pension_amount, $payrollDuration);
                $cra_amount = $this->calculateTaxRelief($pension_amount, $jobProfile['annual_rent_amount'] ?? 0);


                $gross_amount = $basic_amount + $allowance_amount + $bonuses_amount;
                $taxable_income_amount = max(0, $gross_amount - $cra_amount);



                $tax_amount = $taxSet ? $this->calculateTax($employee['id'], $employee['organisation_id'], $taxable_income_amount) : 0.00;

                // ECS - 1% gross
                // ITF - 1% gross 

                $ecs_amount = $ecsSet ? 0.01 * $gross_amount : 0.00; //  can be zero if set to o
                $itf_amount = $itfSet ? 0.01 * $gross_amount : 0.00; // can be zero too
                $net_amount = $gross_amount
                    - ($pension_amount
                        + $tax_amount
                        + $deduction_amount
                        + $non_statutory_deduction_amount
                        + $unpaidLeave);
                $payable_amount = $net_amount;

                $data = [
                    'payroll_month' => $payroll_start['date']['month'],
                    'payroll_year' => $payroll_start['date']['year'],
                    'basic_salary_amount' => $basic_amount,
                    'employee_id' => $employee['id'],
                    'pension_amount' => $pension_amount,
                    'pension_employer_amount' => $pension_employer_amount,
                    'allowance_amount' => $allowance_amount,
                    'allowances_array' => $allowances_array,
                    'deduction_amount' => $deduction_amount,
                    'deduction_array' => $deduction_array,
                    'bonus_array' => $bonuses_array,
                    'bonus_amount' => $bonuses_amount,
                    'non_statutory_deduction_array' => $non_statutory_deduction_array,
                    'non_statutory_deduction_amount' => $non_statutory_deduction_amount,
                    'cra_amount' => $cra_amount,
                    'ecs_amount' => $ecs_amount,
                    'itf_amount' => $itf_amount,
                    'taxable_income_amount' => $taxable_income_amount,
                    'tax_amount' => $tax_amount,
                    'gross_amount' => $gross_amount,
                    'unpaid_leave' => $unpaidLeave,
                    'payable_amount' => $payable_amount,
                ];
                array_push($employee_data, $data);
            }
        } else {
            foreach ($employees as $key => $employee) {
                $basic_amount = $this->calculateBasicPay($employee['id'], $employee['organisation_id'], $payrollDuration);
                $jobProfile = $this->userRepository->getJobProfileByUser($employee['id']);
                $unpaidLeave = $this->calculateUnpaidLeave($employee['id']);


                // $pension_amount = $this->calculatePension($employee['id'], $employee['organisation_id'], $payrollDuration)['employee'];
                // $pension_employer_amount = $this->calculatePension($employee['id'], $employee['organisation_id'], $payrollDuration)['employer'];

                $penCal = $this->calculatePension($employee['id'], $employee['organisation_id'], $payrollDuration);
                $pension_amount = $pensionSet ? ($penCal['employee'] ?? 0.00) : 0.00;
                $pension_employer_amount = $pensionSet ? $penCal['employer'] : 0.00;

                $housingAllowanceValue = $penCal['housingAllowanceValue'] ?? 0.00;


                $allowances = $this->calculateAllowance($employee['id'], $employee['organisation_id'], $payrollDuration);
                $deductions = $this->calculateDeduction($employee['id'], $employee['organisation_id'], $payrollDuration);
                $allowance_amount = $allowances['value'];
                $allowances_array = $allowances['array'];

                if (is_array($deductions)) {
                    $deduction_amount = $deductions['value'];
                } else {
                    $deduction_amount = 0;
                }

                if (is_array($deductions)) {
                    $deduction_array = $deductions['array'];
                } else {
                    $deduction_array = [];
                }




                $bonuses_array = $employee['bonuses'];
                $bonuses_amount = array_sum(array_column($bonuses_array, 'amount'));
                $non_statutory_deduction_array = $employee['non_statutory_deductions'];
                $non_statutory_deduction_amount = array_sum(array_column($non_statutory_deduction_array, 'amount'));
                // $cra_amount = $this->calculateCRA($employee['id'], $employee['organisation_id'], $allowance_amount, $pension_amount, $payrollDuration);
                // $cra_amount = $this->calculateTaxRelief($pension_amount, $housingAllowanceValue);
                $cra_amount = $this->calculateTaxRelief($pension_amount, $jobProfile['annual_rent_amount'] ?? 0);


                $gross_amount = $basic_amount + $allowance_amount + $bonuses_amount;
                $taxable_income_amount = max(0, $gross_amount - $cra_amount);
                $tax_amount = $this->calculateTax($employee['id'], $employee['organisation_id'], $taxable_income_amount);

                // ECS - 1% gross
                // ITF - 1% gross 

                $ecs_amount = 0.01 * $gross_amount; //  can be zero if set to o
                $itf_amount = 0.01 * $gross_amount; // can be zero too
                $net_amount = ($gross_amount) - ($pension_amount + $itf_amount + $ecs_amount + $tax_amount + $deduction_amount + $non_statutory_deduction_amount + $unpaidLeave);
                $payable_amount = $net_amount;

                $data = [
                    'payroll_month' => $payroll_start['date']['month'],
                    'payroll_year' => $payroll_start['date']['year'],
                    'basic_salary_amount' => $basic_amount,
                    'employee_id' => $employee['id'],
                    'pension_amount' => $pension_amount,
                    'pension_employer_amount' => $pension_employer_amount,
                    'allowance_amount' => $allowance_amount,
                    'allowances_array' => $allowances_array,
                    'deduction_amount' => $deduction_amount,
                    'deduction_array' => $deduction_array,
                    'bonus_array' => $bonuses_array,
                    'bonus_amount' => $bonuses_amount,
                    'non_statutory_deduction_array' => $non_statutory_deduction_array,
                    'non_statutory_deduction_amount' => $non_statutory_deduction_amount,
                    'cra_amount' => $cra_amount,
                    'ecs_amount' => $ecs_amount,
                    'itf_amount' => $itf_amount,
                    'taxable_income_amount' => $taxable_income_amount,
                    'tax_amount' => $tax_amount,
                    'gross_amount' => $gross_amount,
                    'unpaid_leave' => $unpaidLeave,
                    'payable_amount' => $payable_amount,
                ];
                array_push($employee_data, $data);
            }
        }



        $result = $this->organisationRepository->createPayrollData($payrollId, $user->organisation_id, $payroll_start['date']['year'], $payroll_start['date']['month'], $payroll_start['pay_group'], $payrollItems, $payroll_start, $employee_data);


        // updates the record and save 
        if (!$result) {
            return response()->json([
                'status' => 'failed',
                'message' => 'Pay run Failed',
                'data' => "An error occurred!"
            ], 400);
        }
        return response()->json([
            'status' => 'success',
            'message' => 'Successfully',
            'employee_data' => $employee_data,
            'employee_data' => $employee_data,
            'data' => $result
        ], 200);
        // } catch (Exception $e) {
        //     return response()->json([
        //         'status' => 'failed',
        //         'message' => 'Pay run Failed',
        //         'data' => $e->getMessage()
        //     ], 400);
        // }
    }

    public function dashboardMetrics(Request $request)
    {
        $user = auth()->user();
        $org = $this->organisationRepository->findById($user->organisation_id);

        if (!$org || $org->is_active === false) {

            return response()->json([
                'status' => 'failed',
                'message' => 'You cannot access time settings at the moment',
            ], 400);
        }
        // Total employees
        $totalEmployees = User::where('organisation_id', $org->id)->count();
        // Total unpaid salary
        $totalUnpaidSalary = PayrollEmployee::where('payment_status', 'unpaid')->where('org_id', $org->id)->sum('payable_amount');
        // Total paid salary
        $totalPaidSalary = PayrollEmployee::where('payment_status', 'paid')->where('org_id', $org->id)->sum('payable_amount');

        // Payroll pending approvals
        $payrollPendingApprovals = Payroll::where('approval_status_desc', 'pending')->where('org_id', $org->id)->count();

        return response()->json([
            'status' => 'success',
            'data' => [
                'total_employees' => $totalEmployees,
                'total_unpaid_salary' => $totalUnpaidSalary,
                'total_paid_salary' => $totalPaidSalary,
                'payroll_pending_approvals' => $payrollPendingApprovals
            ]
        ], 200);
    }

    //Create Org Allowance 
    public function createOrgDepartment(Request $request)
    {
        try {
            $user = Auth::user();
            $name = $request->name;
            $jobTitles = $request->jobTitles;

            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access department at the moment',
                ], 400);
            }

            //Add Validations
            $validator = Validator::make($request->all(), [
                'name' => 'string',
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $data = [
                "name" => $name,
                "org_id" => $org->id,
                "job_titles" => $jobTitles
            ];
            $orgDepartment = $this->organisationRepository->createOrgDepartment($data);


            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} created a new department",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);
            return response()->json([
                'status' => 'success',
                'message' => 'Department created successfully',
                'data' => $orgDepartment
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Org Allowance 
    public function updateOrgDepartment(Request $request)
    {
        try {
            $user = Auth::user();
            $name = $request->name;
            $id = $request->id;
            $jobTitles = $request->jobTitles;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access allowance settings at the moment',
                ], 400);
            }

            //Add Validations
            $validator = Validator::make($request->all(), ['name' => 'string']);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $data = [
                "name" => $name,
                "job_titles" => $jobTitles,
            ];
            $foundDepartment = $this->organisationRepository->getSingleOrgDepartment($id);

            if (empty($foundDepartment)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Department not found',
                    'data' => $data
                ], 400);
            }

            $orgDepartment = $this->organisationRepository->updateOrgDepartment($data, $id);


            //Add to audit
            $userProfile = $this->userRepository->getUserProfileByUser($user->id);
            $auditData = [
                "organisation_id" => $org->id,
                "content" => "{$userProfile['first_name']} {$userProfile['last_name']} updated a department",
                "level" => "high",
                "is_exposed" => 1,
                "user_id" => $user->id
            ];
            $audit = $this->organisationRepository->createAuditTrail($auditData);

            return response()->json([
                'status' => 'success',
                'message' => 'Department updated successfully',
                'data' => $orgDepartment
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Org Department
    public function getAllDepartments(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access department settings at the moment',
                ], 400);
            }
            $orgDepartment = $this->organisationRepository->getAllOrgDepartment($org->id);

            return response()->json([
                'status' => 'success',
                'message' => 'Department returned successfully',
                'data' => $orgDepartment
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Single OrG Department
    public function getSingleDepartment(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access department settings at the moment',
                ], 400);
            }

            $orgDepartment = $this->organisationRepository->getSingleOrgDepartment($id);

            if (empty($orgDepartment)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Allowance not found',
                    'data' => $orgDepartment
                ], 400);
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Department returned successfully',
                'data' => $orgDepartment
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Delete Single OrG Allowance
    public function deleteOrgDepartment(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access department settings at the moment',
                ], 400);
            }
            $orgDepartment = $this->organisationRepository->deleteOrgDepartment($id);

            return response()->json([
                'status' => 'success',
                'message' => 'Department deleted successfully',
                'data' => $orgDepartment
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Create Deduction
    public function createOrgDeduction(Request $request)
    {
        try {
            $user = Auth::user();
            $type = $request->type;
            $name = $request->name;
            $status = $request->status;
            $isExceptional = $request->isExceptional;
            $startDate = $request->startDate;
            $endDate = $request->endDate;
            $startDate = $request->startDate ? Carbon::createFromFormat('Y-m', $request->startDate)->startOfMonth()->toDateString() : null;
            $endDate = $request->endDate ? Carbon::createFromFormat('Y-m', $request->endDate)->startOfMonth()->toDateString() : null;
            $isTaxable = $request->isTaxable;

            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access deduction settings at the moment',
                ], 400);
            }

            //Add Validations
            $validator = Validator::make($request->all(), [
                'type' => 'string',
                'name' => 'string',
                'status' => 'string',
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $slug = $this->generateUniqueSlugDeduction($name, $org->id);

            $deductionData = [
                "type" => $type,
                "name" => $name,
                "status" => $status,
                "org_id" => $org->id,
                "is_exceptional" => $isExceptional,
                "start_date" => $startDate,
                "end_date" => $endDate,
                "slug" => $slug,
                "is_taxable" => $isTaxable
            ];

            $orgDeduction = $this->organisationRepository->createDeductions($deductionData);
            return response()->json([
                'status' => 'success',
                'message' => 'Deduction created successfully',
                'data' => $orgDeduction
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Org Deduction 
    public function updateOrgDeduction(Request $request)
    {
        try {
            $user = Auth::user();
            $type = $request->type;
            $name = $request->name;
            $status = $request->status;
            $id = $request->id;
            $isExceptional = $request->isExceptional;
            $startDate = $request->startDate;
            $endDate = $request->endDate;
            $isTaxable = $request->isTaxable;


            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access deductions settings at the moment',
                ], 400);
            }

            //Add Validations
            $validator = Validator::make($request->all(), [
                'type' => 'string',
                'name' => 'string',
                'status' => 'string',
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $deductionData = [
                "type" => $type,
                "name" => $name,
                "status" => $status,
                "is_exceptional" => $isExceptional,
                "start_date" => $startDate,
                "end_date" => $endDate,
                "is_taxable" => $isTaxable
            ];
            $foundDeduction = $this->organisationRepository->getSingleDeduction($id);

            if (empty($foundDeduction)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Deduction not found',
                    'data' => $foundDeduction
                ], 400);
            }

            $orgDeduction = $this->organisationRepository->updateDeductions($deductionData, $id);

            return response()->json([
                'status' => 'success',
                'message' => 'Deduction updated successfully',
                'data' => $orgDeduction
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Org Deduction
    public function getAllDeductions(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access deduction settings at the moment',
                ], 400);
            }
            $orgDeductions = $this->organisationRepository->getAllDeductions($org->id);

            return response()->json([
                'status' => 'success',
                'message' => 'Deductions returned successfully',
                'data' => $orgDeductions
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Single OrG Deductions
    public function getSingleDeduction(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access deduction settings at the moment',
                ], 400);
            }

            $orgDeduction = $this->organisationRepository->getSingleDeduction($id);

            if (empty($orgDeduction)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Deduction not found',
                    'data' => $orgDeduction
                ], 400);
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Deduction returned successfully',
                'data' => $orgDeduction
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Delete Single Deduction Allowance
    public function deleteDeduction(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access deduction settings at the moment',
                ], 400);
            }
            $orgDeduction = $this->organisationRepository->deleteDeduction($id);

            return response()->json([
                'status' => 'success',
                'message' => 'Deduction deleted successfully',
                'data' => $orgDeduction
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Add Dediuction To Employee 
    public function createEmployeeDeductionRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $deductionId = $request->deductionId;
            $userId = $request->userId;
            $value = $request->value;
            $payrollId = $request->payrollId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access deduction settings at the moment',
                ], 400);
            }

            $userBelongsToOrg = $this->organisationRepository->checkUserInOrg($org->id, $userId);
            if (!$userBelongsToOrg) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'User does not belong to this organisation',
                    'data' => []
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'userId' => 'integer|required',
                'deductionId' => 'integer',
                'payrollId' => 'integer',
                'value' => 'integer',
            ]);


            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $deductionData = [
                "org_id" => $org->id,
                "employee_id" => $userId,
                "deduction_id" => $deductionId,
                "payroll_id" => $payrollId,
                "value" => $value,
            ];

            $deductionRecord = $this->organisationRepository->createDeductionRecord($deductionData);

            return response()->json([
                'status' => 'success',
                'message' => 'Deduction recorded created successfully',
                'data' => $deductionRecord
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }


    //Update Employee Deduction
    public function updateEmployeeDeductionRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $recordId = $request->recordId;
            $deductionId = $request->deductionId;
            $value = $request->value;
            $payrollId = $request->payrollId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access deduction settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'deductionId' => 'integer',
                'value' => 'integer',
                'payrollId' => 'integer',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            //Check for record
            $existingRecord = $this->organisationRepository->getDeductionRecord($recordId);

            if (empty($existingRecord)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Deduction not found',
                    'data' => $existingRecord
                ], 400);
            }

            $deductionData = [
                "deduction_id" => $deductionId,
                "payroll_id" => $payrollId,
                "value" => $value,
            ];

            $deductionRecord = $this->organisationRepository->updateEmployeeAllowanceRecord($deductionData, $recordId);

            return response()->json([
                'status' => 'success',
                'message' => 'Deduction recorded updated successfully',
                'data' => $deductionRecord
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Employee Deduction
    public function getAllEmployeeDeduction(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access deduction settings at the moment',
                ], 400);
            }
            $deductionRecords = $this->organisationRepository->getAllOrgDeductionRecord($org->id);

            return response()->json([
                'status' => 'success',
                'message' => 'Deductions returned successfully',
                'data' => $deductionRecords
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Single Employee Deduction
    public function getSingleEmployeeDeduction(Request $request)
    {
        try {
            $user = Auth::user();
            $recordId = $request->recordId;

            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access deduction settings at the moment',
                ], 400);
            }
            $deductionRecord = $this->organisationRepository->getDeductionRecord($recordId);

            if (empty($deductionRecord)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Deduction not found',
                    'data' => $deductionRecord
                ], 400);
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Deduction returned successfully',
                'data' => $deductionRecord
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }


    //Delete Single Employee Pension
    public function deleteEmployeeDeductionRecord(Request $request)
    {
        try {
            $user = Auth::user();
            $recordId = $request->recordId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access deductions settings at the moment',
                ], 400);
            }
            $employeeDeduction = $this->organisationRepository->deleteEmployeeDeductionRecord($recordId);
            return response()->json([
                'status' => 'success',
                'message' => 'Allowance deleted successfully',
                'data' => $employeeDeduction
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Create New Holiday
    public function createHoliday(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $name = $request->name;
            $description = $request->description;
            $startDate = $request->startDate;
            $endDate = $request->endDate;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access holidays settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'name' => 'string',
                'description' => 'string',
                'start_date' => 'string',
                'end_date' => 'string',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $holidayData = [
                "name" => $name,
                "description" => $description,
                "org_id" => $org->id,
                "start_date" => $startDate,
                "end_date" => $endDate
            ];

            $orgHoliday = $this->organisationRepository->createHoliday($holidayData);
            return response()->json([
                'status' => 'success',
                'message' => 'Holiday created successfully',
                'data' => $orgHoliday
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Holidays
    public function getAllHolidays(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access holidays settings at the moment',
                ], 400);
            }

            $holidays = $this->organisationRepository->getAllHolidays($org->id);
            return response()->json([
                'status' => 'success',
                'message' => 'Holiday returned successfully',
                'data' => $holidays
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Single Holidays
    public function getSingleHoliday(Request $request)
    {
        try {
            $user = Auth::user();
            $holidayId = $request->holidayId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access holidays settings at the moment',
                ], 400);
            }

            $holiday = $this->organisationRepository->getSingleHoliday($holidayId);
            if (empty($holiday)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Holiday not found',
                    'data' => $holiday
                ], 400);
            }
            return response()->json([
                'status' => 'success',
                'message' => 'Holiday returned successfully',
                'data' => $holiday
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Holiday

    public function updateHoliday(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $holidayId = $request->holidayId;
            $name = $request->name;
            $description = $request->description;
            $startDate = $request->startDate;
            $endDate = $request->endDate;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access holidays settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'name' => 'string',
                'description' => 'string',
                'start_date' => 'string',
                'end_date' => 'string',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $holidayData = [
                "name" => $name,
                "description" => $description,
                "start_date" => $startDate,
                "end_date" => $endDate
            ];


            $holiday = $this->organisationRepository->getSingleHoliday($holidayId);
            if (empty($holiday)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Holiday not found',
                    'data' => $holiday
                ], 400);
            }


            $orgHoliday = $this->organisationRepository->updateHoliday($holidayId, $holidayData);
            return response()->json([
                'status' => 'success',
                'message' => 'Holiday created successfully',
                'data' => $orgHoliday
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function deleteHoliday(Request $request)
    {
        try {
            $user = Auth::user();
            $holidayId = $request->holidayId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access holidays settings at the moment',
                ], 400);
            }

            $holiday = $this->organisationRepository->getSingleHoliday($holidayId);
            if (empty($holiday)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Holiday not found',
                    'data' => $holiday
                ], 400);
            }

            $deletedHoliday = $this->organisationRepository->deleteHoliday($holidayId);
            return response()->json([
                'status' => 'success',
                'message' => 'Holiday deleted successfully',
                'data' => []
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Import Allowance Data
    public function importAllowance(Request $request)
    {

        try {
            $request->validate([
                'file' => 'required|mimes:xls,xlsx'
            ]);

            $type = $request->type;

            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if ($type == 'isExceptional') {
                Excel::import(new ExceptionalAllowanceImport($user->id, $org->id), $request->file('file'));
            } else {
                Excel::import(new AllowanceImport($user->id, $org->id), $request->file('file'));
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Allowance data imported successfully'
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Import Allowance Employee Data
    public function importAllowanceEmployee(Request $request)
    {

        try {
            $request->validate([
                'file' => 'required|mimes:xls,xlsx'
            ]);


            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);


            Excel::import(new AllowanceEmployee($user->id, $org->id), $request->file('file'));


            return response()->json([
                'status' => 'success',
                'message' => 'Allowance Employee imported successfully'
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Import Deduction Employee Data
    public function importDeductionEmployee(Request $request)
    {

        try {
            $request->validate([
                'file' => 'required|mimes:xls,xlsx'
            ]);


            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);


            Excel::import(new DeductionEmployee($user->id, $org->id), $request->file('file'));


            return response()->json([
                'status' => 'success',
                'message' => 'Deduction Employee imported successfully'
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Import Deduction Data
    public function deductionAllowance(Request $request)
    {

        try {
            $request->validate([
                'file' => 'required|mimes:xls,xlsx'
            ]);

            $type = $request->type;
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if ($type == 'isExceptional') {
                Excel::import(new ExceptionalDeductionImport($org->id), $request->file('file'));
            } else {
                Excel::import(new DeductionImport($org->id), $request->file('file'));
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Deduction data imported successfully'
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }


    public function getAuditTrails(Request $request)
    {
        try {
            $user = Auth::user();

            $audits = Activity::with(['causer', 'subject'])
                ->whereHas('causer', function ($query) use ($user) {
                    $query->where('organisation_id', $user->organisation_id);
                })
                ->latest()
                ->paginate(30);

            return response()->json([
                'status' => 'success',
                'message' => 'Audit trails retrieved',
                'data' => $audits
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Set Users For Approval Process
    public function setUserForPayrollApproval(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $level = $request->level;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access payroll settings at the moment',
                ], 400);
            }

            $user = $this->organisationRepository->setApprovalUser($id, $level);

            return response()->json([
                'status' => 'success',
                'message' => 'Approval permission saved',
                'data' => $user
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Revoke Users For Approval Process
    public function revokeUserForPayrollApproval(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access payroll settings at the moment',
                ], 400);
            }

            $user = $this->organisationRepository->revokeApprovalUser($id);

            return response()->json([
                'status' => 'success',
                'message' => 'Approval permission revoked',
                'data' => $user
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Users with approval for payroll
    public function getUsersWithPayrollPermission(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access payroll settings at the moment',
                ], 400);
            }

            $approvedUsers = $this->organisationRepository->usersWithPayrollApproval($org->id);

            return response()->json([
                'status' => 'success',
                'message' => 'Approval users',
                'data' => $approvedUsers
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Users with approval for payroll AUTH
    public function checkUserWithPayrollPermission(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access payroll settings at the moment',
                ], 400);
            }

            $approvedUser = $this->organisationRepository->userWithPayrollApproval($user->email, $org->id);

            if (!empty($approvedUser)) {
                return response()->json([
                    'status' => 'success',
                    'message' => 'Approved for payroll',
                    'data' => true
                ], 200);
            } else {
                return response()->json([
                    'status' => 'success',
                    'message' => 'Not approved for payroll',
                    'data' => false
                ], 200);
            }
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function approvePayroll(Request $request)
    {
        $user = Auth::user();
        $payrollId = $request->id;
        $org = $this->organisationRepository->findById($user->organisation_id);

        if (!$org || $org->is_active === false) {
            return response()->json([
                'status' => 'failed',
                'message' => 'You cannot access payroll settings at the moment',
            ], 400);
        }

        $permittedUser = $this->organisationRepository->userWithPayrollApproval($user->email, $org->id);

        if ($permittedUser) {
            $payroll = $this->organisationRepository->approvePayroll($payrollId);

            // Generate Payroll Excel
            $payRollRecord = $this->organisationRepository->getSinglePayRollRecord($payrollId);
            $data = [];
            foreach ($payRollRecord->employee_data as $item) {
                $data[] = [
                    'Staff ID' => $item['employee_id'],
                    'Surname' => $item->employee->profile?->last_name,
                    'Other Names' => $item->employee->profile?->first_name . ' ' . $item->employee->profile?->middle_name,
                    'Payable Amount' => $item['payable_amount'] ?? "0.00",
                    'Employee Countribution' => $item['pension_amount'] ?? '0.00',
                    'Bank Code' => $item->employee->bankInfo?->bank_code,
                    'Account Number' => $item->employee->bankInfo?->account_number,
                    'PFA Code' => $item->employee->bankInfo?->pfa_name,
                    'Pension PIN' => $item->employee->bankInfo?->pfa ?? "",
                    'Plan Id' => $item->employee->bankInfo?->pfa_plan_id ?? "",
                    'Pensioable Income' => $item['gross_amount'] ?? "0.00",
                    'Email Address' => $item->employee->profile?->work_email ?? "",
                    'Mobile Number' => $item->employee->profile?->work_phone ?? "",
                    'Account Type' => "20",
                    'Tax State' => $item->employee->bankInfo?->tax_state ?? "Lagos",
                    'Tax Number' => $item->employee->bankInfo?->tax_id ?? "",
                    'Tax Amount' => $item['tax_amount'] ?? "0.00",
                ];
            }


            // Send to Accounting
            $accountData = [
                "date" => Carbon::now(),
                "amount" => $payroll,
                "reference" => Str::random(10),
                "userId" => $user->id,
                "orgId" => $org->id,
                "description" => "payroll_payment"
            ];
            $result = $this->organisationRepository->sendToAccounting($org->id, $accountData);

            return response()->json([
                'status' => 'success',
                'message' => 'Payroll Approved and Sent to Email',
                'data' => $result
            ], 200);
        } else {
            return response()->json([
                'status' => 'Failed',
                'message' => 'Permission Denied',
                'data' => []
            ], 400);
        }

    }

    // public function PayrollDisburse(Request $request)
    // {
    //     try {
    //         $user = Auth::user();
    //         $payrollId = $request->id;
    //         $org = $this->organisationRepository->findById($user->organisation_id);

    //         if (!$org || $org->is_active === false) {
    //             return response()->json([
    //                 'status' => 'failed',
    //                 'message' => 'You cannot access payroll settings at the moment',
    //             ], 400);
    //         }


    //         $payRollRecord = $this->organisationRepository->getSinglePayRollRecord($payrollId);
    //         $transactions = [];
    //         foreach ($payRollRecord->employee_data as $item) {
    //             $transactions[] = [
    //                 "amount" => $item['payable_amount'],
    //                 "transactionRef" => time() . "" . $item['employee_id'],
    //                 "destinationAccount" => $item->employee->bankInfo?->account_number,
    //                 "destinationAccountName" => $item->employee->bankInfo?->account_name,
    //                 "destinationBankCode" => $item->employee->bankInfo?->bank_code,
    //                 "destinationNarration" => "Salary Payment"
    //             ];
    //         }


    //         $loginRemita = $this->remitaLogin();
    //         if (isset($loginRemita['accessToken'])) {
    //             $accessToken = $loginRemita['accessToken'];
    //             $response = $this->sendBulkPayment($accessToken, $transactions);

    //             if (isset($response['data']['authorizationId'])) {
    //                 $payRollRecord->rrr = $response['data']['authorizationId'];
    //                 $payRollRecord->save();
    //             } else {
    //                 return response()->json([
    //                     'status' => 'failed',
    //                     'message' => $response,
    //                 ], 500);
    //             }
    //         }

    //         return response()->json([
    //             'status' => 'success',
    //             'message' => 'Payroll Disbursement Startedd',
    //             'data' => ['accessToken' => $accessToken, 'rrr' => $response]
    //         ], 200);
    //     } catch (Exception $e) {
    //         return response()->json([
    //             'status' => 'failed',
    //             'message' => $e->getMessage(),
    //         ], 500);
    //     }
    // }


    public function PayrollDisburse(Request $request)
    {
        try {
            $user = Auth::user();
            $payrollId = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access payroll settings at the moment',
                ], 400);
            }

            $payRollRecord = $this->organisationRepository->getSinglePayRollRecord($payrollId);
            $transactions = [];
            foreach ($payRollRecord->employee_data as $item) {
                $bankInfo = $item->employee->bankInfo;

                if (!$bankInfo) {
                    continue;
                }

                $amount = round($item['payable_amount'], 2);
                if ($amount <= 0) {
                    continue;
                }
                if ($amount > 0 && isset($bankInfo->account_number) && isset($bankInfo->bank_code)) {
                    $transactions[] = [
                        "amount" => $amount,
                        "transactionRef" => time() . "" . $item['employee_id'],
                        "destinationAccount" => $bankInfo->account_number,
                        "destinationAccountName" => $bankInfo->account_name,
                        "destinationBankCode" => $bankInfo->bank_code,
                        "destinationNarration" => "Salary Payment - Payraty",
                        "employee_data_id" => $item['id']
                    ];
                }
            }

            $loginRemita = $this->remitaLogin();
            if (isset($loginRemita['accessToken'])) {
                $accessToken = $loginRemita['accessToken'];
                $response = $this->sendBulkPayment($accessToken, $transactions);

                if (isset($response['status']) && $response['status'] === "00") {
                    $payRollRecord->rrr = $response['bulkRef'];
                    $payRollRecord->save();

                    PayrollTransaction::where(['payroll_id' => $payrollId])->delete();
                    // Save the transactions
                    DB::transaction(function () use ($org, $transactions, $payrollId, $response) {
                        foreach ($transactions as $tx) {

                            PayrollTransaction::create([
                                'org_id' => $org->id,
                                'payroll_id' => $payrollId,
                                'transaction_ref' => $tx['transactionRef'],
                                'bulk_reference' => $response['bulkRef'],
                                'payroll_employee_id' => $tx['employee_data_id'],
                                'transaction_type' => 'salary',
                                'amount' => $tx['amount'],
                                'destination_account' => $tx['destinationAccount'],
                                'destination_account_name' => $tx['destinationAccountName'],
                                'destination_bank_code' => $tx['destinationBankCode'],
                                'destination_narration' => $tx['destinationNarration'],
                                'status' => 'PENDING',
                                'remita_status' => 'IN_PROGRESS',
                                'meta' => [
                                    'source' => 'remita',
                                ],
                            ]);

                        }
                    });

                    return response()->json([
                        'status' => 'success',
                        'message' => 'Payroll disbursement queued successfully',
                        'data' => [
                            'bulkPaymentId' => $response['bulkRef'] ?? null,
                            'transaction_count' => count($transactions),
                            'total_to_pay' => round(array_sum(array_column($transactions, 'amount')), 2),
                            'status' => 'IN_PROGRESS',
                            ...$response['data'] ?? null // this is what customers sees for account details
                        ],
                        'transactions' => $transactions
                    ], 200);
                } else {
                    return response()->json([
                        'status' => 'failed',
                        'message' => $response,
                        'transactions' => $transactions
                    ], 500);
                }
            } else {
                return response()->json([
                    'status' => 'failed',
                    'message' => $loginRemita['error'],
                ], 401);
            }

        } catch (Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function PayrollPaymentDetails($bulkPaymentId)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access payroll settings at the moment',
                ], 400);
            }

            // Authenticate with Remita
            $loginRemita = $this->remitaLogin();
            if (!isset($loginRemita['accessToken'])) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Unable to authenticate with Remita',
                ], 401);
            }

            $accessToken = $loginRemita['accessToken'];

            // Call Remita Bulk Payment Details API (GET)
            $url = 'https://api-gateway.remita.net/api/v1/integration/bulk/payment/details/' . $bulkPaymentId;

            $response = Http::withToken($accessToken)
                ->timeout(60)
                ->get($url)
                ->json();

            /**
             * Remita Failure
             */
            if (($response['status'] ?? null) !== '00') {
                return response()->json([
                    'status' => 'failed',
                    'message' => $response['message'] ?? 'Failed to fetch bulk payment status',
                ], 400);
            }

            $transactions = $response['data']['transactions'] ?? [];

            DB::transaction(function () use ($transactions, $bulkPaymentId) {
                foreach ($transactions as $tx) {
                    $remitaStatus = $tx['status'] ?? null;

                    // Map Remita status → internal status
                    $internalStatus = match ($remitaStatus) {
                        'CREDIT_SUCCESS' => 'COMPLETED',
                        'IN_PROGRESS' => 'PROCESSING',
                        'FAILED',
                        'CREDIT_FAILED' => 'FAILED',
                        default => 'PENDING',
                    };

                    PayrollTransaction::where('transaction_ref', $tx['paymentIdentifier'])
                        ->where('bulk_reference', $bulkPaymentId)
                        ->update([
                            'remita_status' => $remitaStatus,
                            'status' => $internalStatus,
                            'meta' => array_merge(
                                PayrollTransaction::where('transaction_ref', $tx['paymentIdentifier'])
                                    ->value('meta') ?? [],
                                [
                                    'last_synced_at' => now(),
                                ]
                            ),
                        ]);
                }
            });

            return response()->json([
                'status' => 'success',
                'message' => 'Payroll transaction statuses updated successfully',
                'data' => [
                    'bulkPaymentId' => $bulkPaymentId,
                    'transactions' => $response['data']['transactions'] ?? [],
                    'pagination' => $response['data']['pagination'] ?? null,
                ],
            ], 200);

        } catch (\Throwable $e) {
            return response()->json([
                'status' => 'failed',
                'message' => 'Unexpected error occurred',
                'error' => $e->getMessage(),
            ], 500);
        }
    }

    public function getPayrollTransactions(Request $request)
    {
        $user = Auth::user();
        $org = $this->organisationRepository->findById($user->organisation_id);

        if (!$org || $org->is_active === false) {

            return response()->json([
                'status' => 'failed',
                'message' => 'You cannot access payroll settings at the moment',
            ], 400);
        }

        // GET /api/org/get-payroll-transactions?payroll_id=12&bulk_reference=BULK_2025_01&search=044

        $filters = $request->only([
            'from_date',
            'to_date',
            'bulk_reference',
            'transaction_ref',
            'payroll_id',
            'search',
        ]);

        $transactions = $this->organisationRepository->getPayrollTransactions($org->id, $filters);

        return response()->json([
            'status' => 'success',
            'message' => 'Payroll transactions fetched successfully',
            'data' => $transactions,
        ], 200);
    }

    public function sendBulkPayment($accessToken, $transactions, $narration = "Salary Payment")
    {
        $bulkRef = "5643" . time() . "" . rand(100, 1000);
        $payload = json_encode([
            "batchRef" => $bulkRef,
            "totalAmount" => round(array_sum(array_column($transactions, 'amount')), 2),
            "sourceAccount" => "1228518098",
            "sourceAccountName" => "Payraty Nig Ltd",
            "sourceBankCode" => "057",
            "originalAccountNumber" => "1228518098",
            "originalBankCode" => "057",
            "currency" => "NGN",
            "sourceNarration" => $narration,
            "customReference" => "ref_" . time() . "" . rand(100, 1000),
            "transactions" => $transactions,
            "payByTransfer" => true
        ], true);

        $curl = curl_init();
        curl_setopt_array($curl, [
            CURLOPT_URL => 'https://api-gateway.remita.net/api/v1/integration/bulk/payment',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => $payload,
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                "Authorization: Bearer $accessToken",
            ],
        ]);



        $response = curl_exec($curl);
        curl_close($curl);

        $data = json_decode($response, true);

        $data['bulkRef'] = $bulkRef;
        return $data;
    }

    public function reJectPayroll(Request $request)
    {
        try {
            $user = Auth::user();
            $payrollId = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access payroll settings at the moment',
                ], 400);
            }

            $permittedUser = $this->organisationRepository->userWithPayrollApproval($user->email, $org->id);

            if ($permittedUser) {
                $payroll = $this->organisationRepository->reJectPayroll($payrollId);

                return response()->json([
                    'status' => 'success',
                    'message' => 'Payroll Rejected',
                    'data' => $payroll
                ], 200);
            } else {
                return response()->json([
                    'status' => 'Failed',
                    'message' => 'Permission Denied',
                    'data' => []
                ], 400);
            }
            ;
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Approve Payroll
    public function SendPayrollForApproval(Request $request)
    {
        try {
            $user = Auth::user();
            $payrollId = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access payroll settings at the moment',
                ], 400);
            }

            $approvedUsers = $this->organisationRepository->usersWithPayrollApproval($org->id);

            if (empty($approvedUsers)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'No users found with payroll approval permissions.',
                ], 404);
            }

            foreach ($approvedUsers as $approvedUser) {
                $mailData = [
                    'link' => env('FRONTEND_URL') .
                        ($approvedUser['user_type'] == 'employee'
                            ? "/employee/dashboard/payroll/approval/{$payrollId}"
                            : "/dashboard/payroll/approval/{$payrollId}")
                ];

                // Send the email to the user
                Mail::to($approvedUser["email"])->send(new SendPayroll($mailData));
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Payroll sent for approval',
                'data' => []
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function markPayrollSession(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access payroll settings at the moment',
                ], 400);
            }

            // $permittedUser = $this->organisationRepository->userWithPayrollApproval($user->email, $org->id);

            // if (!$permittedUser) {
            //     return response()->json([
            //         'status' => 'Failed',
            //         'message' => 'Permission Denied',
            //         'data' => []
            //     ], 403);
            // }

            $user = $this->organisationRepository->markPayrollSession($id);

            return response()->json([
                'status' => 'success',
                'message' => 'Payroll Session Closed',
                'data' => $user
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function startPayrollRun(Request $request)
    {
        try {
            $user = Auth::user();
            $id = $request->id;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access payroll settings at the moment',
                ], 400);
            }

            $payrollInfo = $this->organisationRepository->getSinglePayRollRecord($id);
            $employees = $this->userRepository->findByOrganisationAndPayGroupWithjobInfo($user->organisation_id, $payrollInfo->pay_group);

            return response()->json([
                'status' => 'success',
                'message' => 'Payroll Session Returned',
                'data' => [
                    "employee_info" => $employees,
                    "payroll_info" => $payrollInfo
                ]
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Create Payroll Grade
    public function createPayGroup(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $name = $request->name;
            $description = $request->description;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygroup settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'name' => 'string',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $payGroupData = [
                "name" => $name,
                "description" => $description,
                "organisation_id" => $org->id,
            ];

            $orgPaygroup = $this->organisationRepository->createPayGroup($payGroupData);


            return response()->json([
                'status' => 'success',
                'message' => 'Paygroup created successfully',
                'data' => $orgPaygroup
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Paygrades
    public function getAllPaygroups(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygroups settings at the moment',
                ], 400);
            }

            $paygroups = $this->organisationRepository->listPaygroup($org->id);
            return response()->json([
                'status' => 'success',
                'message' => 'Paygroups returned successfully',
                'data' => $paygroups
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Single Paygrades
    public function getSinglePayGroup(Request $request)
    {
        try {
            $user = Auth::user();
            $paygroupId = $request->paygroupId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygroups settings at the moment',
                ], 400);
            }

            $paygroup = $this->organisationRepository->getSinglePayGroup($paygroupId);
            if (empty($paygroup)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Paygroup not found',
                    'data' => $paygroup
                ], 400);
            }
            return response()->json([
                'status' => 'success',
                'message' => 'Paygrade returned successfully',
                'data' => $paygroup
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Pay Grade
    public function updatePayGroup(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $name = $request->name;
            $description = $request->description;
            $paygroupId = $request->paygroupId;
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygroup settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'name' => 'string',
                'description' => 'string',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $data = [
                "name" => $name,
                "description" => $description,
            ];


            $paygroup = $this->organisationRepository->getSinglePayGroup($paygroupId);
            if (empty($paygroup)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Paygroup not found',
                    'data' => $paygroup
                ], 400);
            }


            $orgPaygroup = $this->organisationRepository->updatePayGroup($paygroupId, $data);
            return response()->json([
                'status' => 'success',
                'message' => 'Paygroup updated successfully',
                'data' => $orgPaygroup
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function createPayGrade(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $name = $request->name;
            $description = $request->description;
            $allowances = $request->allowances;
            $deductions = $request->deductions;
            $pensionPercentage = $request->pensionPercentage;
            $paygroupId = $request->paygroupId;
            $isTaxable = $request->isTaxable;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygrade settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'name' => 'string',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $payGradeData = [
                "name" => $name,
                "description" => $description,
                "pension_percentage" => $pensionPercentage,
                "organisation_id" => $org->id,
                "pay_group_id" => $paygroupId,
                "allowances" => $allowances,
                "deductions" => $deductions,
                "is_taxable" => $isTaxable
            ];

            $orgPaygrade = $this->organisationRepository->createPayGrade($payGradeData);
            return response()->json([
                'status' => 'success',
                'message' => 'Paygrade created successfully',
                'data' => $orgPaygrade
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Paygrades
    public function getAllPaygrades(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygrades settings at the moment',
                ], 400);
            }

            $paygrades = $this->organisationRepository->listPaygrade($org->id);
            return response()->json([
                'status' => 'success',
                'message' => 'Paygrades returned successfully',
                'data' => $paygrades
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Single Paygrades
    public function getSinglePayGrade(Request $request)
    {
        try {
            $user = Auth::user();
            $paygradeId = $request->paygradeId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygroups settings at the moment',
                ], 400);
            }

            $paygrade = $this->organisationRepository->getSinglePayGrade($paygradeId);
            if (empty($paygrade)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Paygrade not found',
                    'data' => $paygrade
                ], 400);
            }
            return response()->json([
                'status' => 'success',
                'message' => 'Paygrade returned successfully',
                'data' => $paygrade
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Pay Grade
    public function updatePayGrade(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $paygradeId = $request->paygradeId;
            $name = $request->name;
            $description = $request->description;
            $allowances = $request->allowances;
            $deductions = $request->deductions;
            $pensionPercentage = $request->pensionPercentage;
            $isTaxable = $request->isTaxable;

            $paygroupId = $request->paygroupId;
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygrade settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'name' => 'string',
                'description' => 'string',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $data = [
                "name" => $name,
                "description" => $description,
                "pension_percentage" => $pensionPercentage,
                "pay_group_id" => $paygroupId,
                "allowances" => $allowances,
                "deductions" => $deductions,
                "is_taxable" => $isTaxable
            ];


            $paygrade = $this->organisationRepository->getSinglePayGrade($paygradeId);
            if (empty($paygrade)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Paygrade not found',
                    'data' => $paygrade
                ], 400);
            }


            $orgPaygrade = $this->organisationRepository->updatePayGrade($paygradeId, $data);
            return response()->json([
                'status' => 'success',
                'message' => 'Paygrade created successfully',
                'data' => $orgPaygrade
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function assignToPaygrade(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $paygrade_id = $request->paygradeId;
            $user_id = $request->userId;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygrade settings at the moment',
                ], 400);
            }

            if (!is_array($user_id)) {
                $user_id = [$user_id];
            }

            $results = [];
            $existingPaygrades = $this->organisationRepository->existingUsersInPaygrade($org->id);
            foreach ($user_id as $userId) {
                // Check if the user is already assigned to a pay grade
                if (in_array($userId, $existingPaygrades)) {
                    // Skip this user as they are already assigned
                    $results[] = [
                        'user_id' => $userId,
                        'status' => 'failed',
                        'message' => 'User is already assigned to a pay grade.',
                    ];
                    continue;
                }
                $data = [
                    "organisation_id" => $org->id,
                    "pay_grade_id" => $paygrade_id,
                    "user_id" => $userId
                ];

                // Assign paygrade
                $employeePaygrade = $this->organisationRepository->assignToPaygrade($data);
                $results[] = $employeePaygrade;

                // Add Paygrade to job
                $jobInfo = $this->organisationRepository->addPaygradeToJob($userId, $paygrade_id);
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Paygrade assigned successfully',
                'data' => $results
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function removeFromPaygrade(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $id = $request->id;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygrade settings at the moment',
                ], 400);
            }

            $employeePaygrade = $this->organisationRepository->removeFromPaygrade($id);
            return response()->json([
                'status' => 'success',
                'message' => 'employee removed from paygrade successfully',
                'data' => $employeePaygrade
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function listEmployeePaygrade(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygrade settings at the moment',
                ], 400);
            }

            $employeePaygrade = $this->organisationRepository->listEmployeePaygrade($org->id);
            return response()->json([
                'status' => 'success',
                'message' => 'Employee Paygrade List Successfully',
                'data' => $employeePaygrade
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function deletePayGroup(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $id = $request->id;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygroup settings at the moment',
                ], 400);
            }

            $employeePaygrade = $this->organisationRepository->deletePayGroup($id);
            return response()->json([
                'status' => 'success',
                'message' => 'Paygroup deleted successfully',
                'data' => $employeePaygrade
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function deletePayGrade(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $id = $request->id;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access paygrade settings at the moment',
                ], 400);
            }

            $employeePaygrade = $this->organisationRepository->deletePayGrade($id);
            return response()->json([
                'status' => 'success',
                'message' => 'Paygrade deleted successfully',
                'data' => $employeePaygrade
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function payrollPieChart(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access data charts settings at the moment',
                ], 400);
            }
            $payroll = $this->organisationRepository->payrollPieChart($org->id);

            return response()->json([
                'status' => 'success',
                'data' => $payroll,
                'message' => 'Payroll List'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function payrollListChart(Request $request)
    {
        try {
            $user = Auth::user();
            $year = Carbon::now()->year;
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access data charts settings at the moment',
                ], 400);
            }
            $payroll = $this->organisationRepository->payrollList($year, $org->id);

            return response()->json([
                'status' => 'success',
                'data' => $payroll,
                'message' => 'Payroll List'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function employeeChart(Request $request)
    {
        try {
            $user = Auth::user();
            $year = Carbon::now()->year;
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access data charts settings at the moment',
                ], 400);
            }
            $employeeChart = $this->organisationRepository->employeeChart($org->id);

            return response()->json([
                'status' => 'success',
                'data' => $employeeChart,
                'message' => 'employee List'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function getTotalPayroll(Request $request)
    {
        try {
            $user = Auth::user();
            $year = Carbon::now()->year;
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access payroll data settings at the moment',
                ], 400);
            }
            $payrollTotal = $this->organisationRepository->payrollTotal($org->id);

            return response()->json([
                'status' => 'success',
                'data' => $payrollTotal,
                'message' => 'Payroll Total'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function getAssignedWorkShift(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access employee data settings at the moment',
                ], 400);
            }
            $employee = $this->organisationRepository->getAssignedWorkShift($org->id);

            return response()->json([
                'status' => 'success',
                'data' => $employee,
                'message' => 'Employee workshift list'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Assign User To Manager

    public function assignUserToManager(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access employee data settings at the moment',
                ], 400);
            }

            $userId = $request->userId;
            $managerId = $request->managerId;

            //Add Validations
            $validator = Validator::make($request->all(), [
                'userId' => 'integer',
                'managerId' => 'integer',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $managerUser = $this->organisationRepository->addUserToManager($userId, $managerId, $org->id);

            return response()->json([
                'status' => 'success',
                'data' => $managerUser,
                'message' => 'User Added To Manager Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function getTeamPayslips(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $date = $request->date;
            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access teams data at the moment',
                ], 400);
            }


            //Get Team USers First
            $teamUsers = $this->organisationRepository->getTeamMembers($org->id, $user->id);
            if (empty($teamUsers)) {
                return response()->json([
                    'status' => 'success',
                    'data' => [],
                    'message' => 'No team members at the moment'
                ]);
            }

            //Get Payslip for each user 
            $userIds = $teamUsers->pluck('user_id')->toArray();
            $payslips = $this->organisationRepository->teamPayslips($userIds, $date);
            return response()->json([
                'status' => 'success',
                'data' => $payslips,
                'message' => 'Payslips Returned Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function getTeamAttendance(Request $request)
    {
        try {
            $start = $request->start ?? '2020-01-01';
            $end = $request->end ?? '2500-01-01';
            $employeeId = $request->employeeId;
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access attendance data at the moment',
                ], 400);
            }


            //Get Team USers First
            //$teamUsers = $this->organisationRepository->getTeamMembers($org->id, $user->id);

            // if (empty($teamUsers)) {
            //     return response()->json([
            //         'status' => 'success',
            //         'data' => [],
            //         'message' => 'No team members at the moment'
            //     ]);
            // }

            //Get Payslip for each user 
            //$userIds = $teamUsers->pluck('user_id')->toArray();
            $attendances = $this->organisationRepository->getTeamEmployeeAttendance($start, $end, $org->id, $user->id, $employeeId);
            return response()->json([
                'status' => 'success',
                'data' => $attendances,
                'message' => 'Attendances Returned Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function getTeamLeaveRequests(Request $request)
    {
        try {
            $start = $request->start ?? '2020-01-01';
            $end = $request->end ?? '2500-01-01';
            $employeeId = $request->employeeId;
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access leave request data at the moment',
                ], 400);
            }


            //Get Team USers First
            $teamUsers = $this->organisationRepository->getTeamMembers($org->id, $user->id);

            if (empty($teamUsers)) {
                return response()->json([
                    'status' => 'success',
                    'data' => [],
                    'message' => 'No team members at the moment'
                ]);
            }

            //Get Payslip for each user 
            $userIds = $teamUsers->pluck('user_id')->toArray();
            $leaveRequests = $this->organisationRepository->teamLeaveRequest($userIds, $start, $end, $employeeId);
            return response()->json([
                'status' => 'success',
                'data' => $leaveRequests,
                'message' => 'Leave Requests Returned Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function approveLeaveRequest(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access leave request data settings at the moment',
                ], 400);
            }

            $leaveId = $request->id;

            //Check if requested leave that is been approved falls with the same year
            $leaveRequest = $this->organisationRepository->getLeaveRequest($leaveId);
            $leaveRequestYear = $leaveRequest->created_at->year;
            $currentYear = Carbon::now()->year;

            if ($currentYear == $leaveRequestYear) {

                //Check if user has leave days 
                $jobProfile = $this->userRepository->getJobProfileByUserId($leaveRequest->user_id);
                if (!empty($jobProfile) && $jobProfile?->leave_days < $leaveRequest->days) {

                    //Create a new leave fee record
                    $payFrequency = $jobProfile?->pay_frequency;
                    $leaveRecord = $this->organisationRepository->createLeaveFee($org->id, $leaveRequest->user_id, $leaveRequest->days, $payFrequency);
                }
                $approvedLeave = $this->organisationRepository->approveLeaveRequest($leaveId);
                return response()->json([
                    'status' => 'success',
                    'data' => $approvedLeave,
                    'message' => 'Leave Approved Successfully'
                ]);
            } else {
                return response()->json([
                    'status' => 'failed',
                    'message' => "Leave request is not in the current year."
                ], 400);
            }
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function denyLeaveRequest(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access leave request data settings at the moment',
                ], 400);
            }

            $leaveId = $request->id;

            //Check if requested leave that is been denied falls with the same year
            $leaveRequest = $this->organisationRepository->getLeaveRequest($leaveId);
            $leaveRequestYear = $leaveRequest->created_at->year;
            $currentYear = Carbon::now()->year;

            if ($currentYear == $leaveRequestYear) {
                $denyLeave = $this->organisationRepository->denyLeaveRequest($leaveId);
                return response()->json([
                    'status' => 'success',
                    'data' => $denyLeave,
                    'message' => 'Leave Denied Successfully'
                ]);
            } else {
                return response()->json([
                    'status' => 'failed',
                    'message' => "Leave request is not in the current year."
                ], 400);
            }
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function getTeamExpenses(Request $request)
    {
        try {
            $start = $request->start ?? '2020-01-01';
            $end = $request->end ?? '2500-01-01';
            $employeeId = $request->employeeId;
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access expenses request data at the moment',
                ], 400);
            }


            //Get Team USers First
            $teamUsers = $this->organisationRepository->getTeamMembers($org->id, $user->id);

            if (empty($teamUsers)) {
                return response()->json([
                    'status' => 'success',
                    'data' => [],
                    'message' => 'No team members at the moment'
                ]);
            }

            //Get Payslip for each user 
            $userIds = $teamUsers->pluck('user_id')->toArray();
            $expenses = $this->organisationRepository->getTeamExpenses($userIds, $start, $end, $employeeId);
            return response()->json([
                'status' => 'success',
                'data' => $expenses,
                'message' => 'Expenses Returned Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function approveExpense(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access expenses request data settings at the moment',
                ], 400);
            }

            $expenseId = $request->id;

            $expense = $this->organisationRepository->approveExpense($expenseId);
            return response()->json([
                'status' => 'success',
                'data' => $expense,
                'message' => 'Expense Approved Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function denyExpense(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access expenses request data settings at the moment',
                ], 400);
            }

            $expenseId = $request->id;

            $expense = $this->organisationRepository->denyExpense($expenseId);
            return response()->json([
                'status' => 'success',
                'data' => $expense,
                'message' => 'Expense Denied Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //List Employees
    public function listTeamEmployees(Request $request)
    {
        try {
            $user = Auth::user();
            $limit = (int) $request->limit ?? 20;
            $managerId = $request->managerId;

            //check if org exists
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot add users at the moment',
                ], 400);
            }

            $data = [
                "employment_status" => $request->employment_status ?? 'all',
                "pay_group" => $request->pay_group ?? 'all',
                "search_string" => $request->search_string ?? ''
            ];
            $users = $this->userRepository->findTeamEmployees($org->id, $managerId, $data, $limit);
            return response()->json([
                'status' => 'success',
                'message' => 'Employee list returned',
                'data' => $users
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function createEmployeeTransfer(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $reason = $request->reason;
            $type = $request->type;
            $employeeId = $request->employeeId;


            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access employee transfer settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'reason' => 'string',
                'type' => 'string',
                'employeeId' => 'required|integer'
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $data = [
                "reason" => $reason,
                "type" => $type,
                "organisation_id" => $org->id,
                "employee_id" => $employeeId,
                "initiated_by" => $user->id,
            ];

            $employeTransfer = $this->organisationRepository->createEmployeeTransfer($data);
            return response()->json([
                'status' => 'success',
                'message' => 'Employee Transfer created successfully',
                'data' => $employeTransfer
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }


    public function getAllEmployeeTransfers(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $start = $request->start ?? '2020-01-01';
            $end = $request->end ?? '2500-01-01';
            $employeeId = $request->employeeId;
            $limit = $request->limit ?? 20;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access employee transfers settings at the moment',
                ], 400);
            }

            $employeeTransfers = $this->organisationRepository->getAllEmployeeTransfer($org->id, $start, $end, $limit, $employeeId);
            return response()->json([
                'status' => 'success',
                'message' => 'Employee Transfers returned successfully',
                'data' => $employeeTransfers
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get Single Paygrades
    public function getSingleEmployeeTransfers(Request $request)
    {
        try {
            $user = Auth::user();
            $transferId = $request->transferId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access employee transfers settings at the moment',
                ], 400);
            }

            $employeeTransfer = $this->organisationRepository->getOneEmployeeTransfer($transferId);
            if (empty($employeeTransfer)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Employee Transfer Record not found',
                    'data' => $employeeTransfer
                ], 400);
            }
            return response()->json([
                'status' => 'success',
                'message' => 'Employee Transfer Returned Successfully',
                'data' => $employeeTransfer
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function updateEmployeeTransfer(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $transferId = $request->transferId;
            $reason = $request->reason;
            $type = $request->type;
            $status = $request->status;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access employee transfers settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'reason' => 'string',
                'type' => 'string',
                'status' => 'string'
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $data = [
                "reason" => $reason,
                "type" => $type,
                "status" => $status
            ];


            $employeeTransfer = $this->organisationRepository->getOneEmployeeTransfer($transferId);
            if (empty($employeeTransfer)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Employee Transfer Record not found',
                    'data' => $employeeTransfer
                ], 400);
            }


            $orgEmployeeTransfer = $this->organisationRepository->updateEmployeeTransfer($transferId, $data);
            return response()->json([
                'status' => 'success',
                'message' => 'Employee Transfer Updated Successfully',
                'data' => $orgEmployeeTransfer
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function deleteEmployeeTransfer(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $transferId = $request->transferId;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access employee transfers settings at the moment',
                ], 400);
            }

            $employeeTransfer = $this->organisationRepository->deleteEmployeeTransfer($transferId);
            return response()->json([
                'status' => 'success',
                'message' => 'Employee Transfer Deleted Successfully',
                'data' => $employeeTransfer
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function createDisciplineAction(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $reason = $request->reason;
            $type = $request->type;
            $employeeId = $request->employeeId;


            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access employee transfer settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'reason' => 'string',
                'type' => 'string',
                'employeeId' => 'required|integer'
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $data = [
                "reason" => $reason,
                "type" => $type,
                "organisation_id" => $org->id,
                "employee_id" => $employeeId,
                "initiated_by" => $user->id,
            ];

            $disciplineAction = $this->organisationRepository->createDisciplineAction($data);
            return response()->json([
                'status' => 'success',
                'message' => 'Disciplinary Action created successfully',
                'data' => $disciplineAction
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }


    public function getAllDisciplineAction(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $start = $request->start ?? '2020-01-01';
            $end = $request->end ?? '2500-01-01';
            $employeeId = $request->employeeId;
            $limit = $request->limit ?? 20;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access discipline actions settings at the moment',
                ], 400);
            }

            $disciplineAction = $this->organisationRepository->getAllDisciplineAction($org->id, $start, $end, $limit, $employeeId);
            return response()->json([
                'status' => 'success',
                'message' => 'Discipline Actions returned successfully',
                'data' => $disciplineAction
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function getAllOrgExpenses(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $start = $request->start ?? '2020-01-01';
            $end = $request->end ?? '2500-01-01';
            $employeeId = $request->employeeId;
            $limit = $request->limit ?? 20;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access expenses settings at the moment',
                ], 400);
            }

            $expenses = $this->organisationRepository->getOrgExpenses($org->id, $start, $end, $limit, $employeeId);
            return response()->json([
                'status' => 'success',
                'message' => 'Expenses returned successfully',
                'data' => $expenses
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function getAllOrgLeaves(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $start = $request->start ?? '2020-01-01';
            $end = $request->end ?? '2500-01-01';
            $employeeId = $request->employeeId;
            $limit = $request->limit ?? 20;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access leaves settings at the moment',
                ], 400);
            }

            $leaves = $this->organisationRepository->getOrgLeaves($org->id, $start, $end, $limit, $employeeId);
            return response()->json([
                'status' => 'success',
                'message' => 'Leaves returned successfully',
                'data' => $leaves
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }


    //Get Single Paygrades
    public function getOneDisciplineAction(Request $request)
    {
        try {
            $user = Auth::user();
            $disciplineId = $request->disciplineId;
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access discipline actions settings at the moment',
                ], 400);
            }

            $disciplineAction = $this->organisationRepository->getOneEmployeeTransfer($disciplineId);
            if (empty($disciplineAction)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Discipline Action Record not found',
                    'data' => $disciplineAction
                ], 400);
            }
            return response()->json([
                'status' => 'success',
                'message' => 'Discipline Action Returned Successfully',
                'data' => $disciplineAction
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function updateDisciplineAction(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $disciplineId = $request->disciplineId;
            $reason = $request->reason;
            $type = $request->type;
            $status = $request->status;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access discipline actions settings at the moment',
                ], 400);
            }
            //Add Validations
            $validator = Validator::make($request->all(), [
                'reason' => 'string',
                'type' => 'string',
                'status' => 'string'
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $data = [
                "reason" => $reason,
                "type" => $type,
                "status" => $status
            ];


            $disciplineAction = $this->organisationRepository->getOneDisciplineAction($disciplineId);
            if (empty($disciplineAction)) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Discipline Action Record not found',
                    'data' => $disciplineAction
                ], 400);
            }


            $orgDisciplineAction = $this->organisationRepository->updateDisciplineAction($disciplineId, $data);
            return response()->json([
                'status' => 'success',
                'message' => 'Discipline Action Updated Successfully',
                'data' => $orgDisciplineAction
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function deleteDisciplineAction(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $disciplineId = $request->disciplineId;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access discipline actions settings at the moment',
                ], 400);
            }

            $disciplineAction = $this->organisationRepository->deleteDisciplineAction($disciplineId);
            return response()->json([
                'status' => 'success',
                'message' => 'Discipline Action Deleted Successfully',
                'data' => $disciplineAction
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Manager Dashboard Metrics
    public function getManagerMetrics(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access manager metrics settings at the moment',
                ], 400);
            }

            //Get Team USers First
            $teamUsers = $this->organisationRepository->getTeamMembers($org->id, $user->id);

            if (empty($teamUsers)) {
                return response()->json([
                    'status' => 'success',
                    'data' => [],
                    'message' => 'No team members at the moment'
                ]);
            }

            //Get Payslip for each user 
            $userIds = $teamUsers->pluck('user_id')->toArray();
            $metrics = $this->organisationRepository->managerDashboardMetrics($user->id, $teamUsers);

            return response()->json([
                'status' => 'success',
                'message' => 'Allowance returned successfully',
                'data' => $metrics
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function getTeamEmployeeTransfers(Request $request)
    {
        try {
            $start = $request->start ?? '2020-01-01';
            $end = $request->end ?? '2500-01-01';
            $employeeId = $request->employeeId;
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access transfers request data at the moment',
                ], 400);
            }


            //Get Team USers First
            $teamUsers = $this->organisationRepository->getTeamMembers($org->id, $user->id);

            if (empty($teamUsers)) {
                return response()->json([
                    'status' => 'success',
                    'data' => [],
                    'message' => 'No team members at the moment'
                ]);
            }

            //Get transfers for each user 
            $userIds = $teamUsers->pluck('user_id')->toArray();
            $transfers = $this->organisationRepository->getTeamTransfers($userIds, $start, $end, $employeeId);
            return response()->json([
                'status' => 'success',
                'data' => $transfers,
                'message' => 'Transfers Returned Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function getTeamEmployeeDiscipline(Request $request)
    {
        try {
            $start = $request->start ?? '2020-01-01';
            $end = $request->end ?? '2500-01-01';
            $employeeId = $request->employeeId;
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access discipline actions request data at the moment',
                ], 400);
            }


            //Get Team USers First
            $teamUsers = $this->organisationRepository->getTeamMembers($org->id, $user->id);

            if (empty($teamUsers)) {
                return response()->json([
                    'status' => 'success',
                    'data' => [],
                    'message' => 'No team members at the moment'
                ]);
            }

            //Get transfers for each user 
            $userIds = $teamUsers->pluck('user_id')->toArray();
            $disciplineActions = $this->organisationRepository->getTeamDisciplineActions($userIds, $start, $end, $employeeId);
            return response()->json([
                'status' => 'success',
                'data' => $disciplineActions,
                'message' => 'Discipline Actions Returned Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Create Group Account
    public function createGroupAccount(Request $request)
    {
        try {
            $name = $request->name;
            $address = $request->address;
            $email = $request->email;
            $password = $request->password;

            //Add Validations
            $validator = Validator::make($request->all(), [
                'name' => 'string',
                'address' => 'string',
                'logo' => 'nullable|file|mimes:jpg,jpeg,png,pdf,doc,docx|max:2048',
                'email' => 'required|string'
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            // Use a DB transaction
            DB::beginTransaction();

            $data = [
                "name" => $name,
                "email" => $email,
                "address" => $address,
            ];

            // Handle file upload
            if ($request->hasFile('logo') && $request->file('logo')->isValid()) {
                $path = $request->file('logo')->store('uploads', 's3');
                $data['logo'] = Storage::disk('s3')->url($path);
            }
            $groupAccount = $this->organisationRepository->createGroupAccount($data);

            //Create Auth For Account
            $userData = [
                "email" => $email,
                "password" => Hash::make($password),
                'user_type' => 'admin',
                'is_registered' => true,
                'is_active' => true,
                'type' => 'company',
                'role' => 'Admin',
                'is_group_account' => true,
                'group_account_id' => $groupAccount->id
            ];

            $user = $this->userRepository->createUser($userData);

            //TODO:Send EMAIL

            // Create token
            $token = Auth::login($user);

            // Commit transaction
            DB::commit();
            return response()->json([
                'status' => 'success',
                'message' => 'Group account created successfully',
                'data' => $groupAccount
            ], 200);
        } catch (\Exception $e) {
            // Rollback the transaction on failure
            DB::rollBack();
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function updateCompanyProfile(Request $request)
    {
        try {
            $user = Auth::user();
            $groupId = $request->groupId;
            $name = $request->name;
            $logo = $request->logo;
            $address = $request->address;

            //Add Validations
            $validator = Validator::make($request->all(), [
                'name' => 'string',
                'address' => 'string',
                'logo' => 'nullable|file|mimes:jpg,jpeg,png,pdf,doc,docx|max:2048',
            ]);

            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            $data = [
                "name" => $name,
                "address" => $address,
            ];

            // Handle file upload
            if ($request->hasFile('logo') && $request->file('logo')->isValid()) {
                $path = $request->file('logo')->store('uploads', 's3');
                $data['logo'] = Storage::disk('s3')->url($path);
            }
            $groupAccount = $this->organisationRepository->updateGroupAccount($groupId, $data);

            return response()->json([
                'status' => 'success',
                'message' => 'Group Account Updated Successfully',
                'data' => $groupAccount
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function loadDefaults($orgId, $userId)
    {
        // Create Default Org Pension Agreement
        $singlePensionData = [
            "type" => "single",
            "employee_contribution" => 0,
            "company_contribution" => 20,
            "org_id" => $orgId
        ];

        $sharedPensionData = [
            "type" => "shared",
            "employee_contribution" => 8,
            "company_contribution" => 10,
            "org_id" => $orgId
        ];

        // Create Default Tax Rules
        $taxData = [
            [
                "salary_range" => 300000,
                "percentage" => 7,
                "org_id" => $orgId,
            ],
            [
                "salary_range" => 400000,
                "percentage" => 15,
                "org_id" => $orgId,
            ],
            [
                "salary_range" => 600000,
                "percentage" => 19,
                "org_id" => $orgId,
            ],
            [
                "salary_range" => 100000,
                "percentage" => 10,
                "org_id" => $orgId,
            ],
        ];

        // Create Default Time Settings
        $timeData = [
            "resumption_time" => Carbon::parse('09:00')->format('Y-m-d H:i:s'),
            "closing_time" => Carbon::parse("17:00")->format('Y-m-d H:i:s'),
            "default_late_period" => 30,
            "name" => 'Default Shift',
            "org_id" => $orgId,
        ];


        // Create Allowances
        $allowanceData = [
            [
                "org_id" => $orgId,
                "type" => "percentage",
                "name" => "Transport Allowance",
                "description" => "This covers transport allowance",
                "added_by" => $userId,
                "is_default" => 1,
                "status" => true,
                "default_type" => "transport",
            ],
            [
                "org_id" => $orgId,
                "type" => "percentage",
                "name" => "House Allowance",
                "description" => "This covers housing allowance",
                "added_by" => $userId,
                "is_default" => 1,
                "status" => true,
                "default_type" => "housing",
            ],
        ];


        //Create Chart of accounts for accounting
        $chartAccountTypes = [
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Assets"
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Liabilities"
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Equity"
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Income"
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Costs of Goods Sold"
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Expenses"
            ]
        ];

        $chartTypeIds = [];

        foreach ($chartAccountTypes as $data) {
            $chartTypes = $this->organisationRepository->createChartTypes($data);
            $chartTypeIds[$chartTypes->name] = $chartTypes->id;
        }

        //Create Chart sub types  of accounts for accounting
        $chartAccountSubTypes = [
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Current Asset",
                "type" => $chartTypeIds['Assets'] ?? null
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Inventory Asset",
                "type" => $chartTypeIds['Assets'] ?? null
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Non-current Asset",
                "type" => $chartTypeIds['Assets'] ?? null
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Current Liabilities",
                "type" => $chartTypeIds['Liabilities'] ?? null
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Long Term Liabilities",
                "type" => $chartTypeIds['Liabilities'] ?? null
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Share Capital",
                "type" => $chartTypeIds['Liabilities'] ?? null
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Retained Earnings",
                "type" => $chartTypeIds['Liabilities'] ?? null
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Owners Equity",
                "type" => $chartTypeIds['Equity'] ?? null
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Sales Revenue",
                "type" => $chartTypeIds['Income'] ?? null
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Other Revenue",
                "type" => $chartTypeIds['Income'] ?? null
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Costs of Goods Sold",
                "type" => $chartTypeIds['Costs of Goods Sold'] ?? null
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "Payroll Expenses",
                "type" => $chartTypeIds['Expenses'] ?? null
            ],
            [
                "organisation_id" => $orgId,
                "created_by" => $userId,
                "name" => "General and Administrative expenses",
                "type" => $chartTypeIds['Expenses'] ?? null
            ],
        ];

        foreach ($chartAccountSubTypes as $data) {
            $this->organisationRepository->createChartSubTypes($data);
        }

        // Find and register products for the organisation
        $products = $this->organisationRepository->getPayratyProducts();
        foreach ($products as $product) {
            $orgProducts = [
                "organisation_id" => $orgId,
                "product_id" => $product->id,
                "is_active" => false,
            ];
            $this->organisationRepository->registerOrgProduct($orgProducts);
        }

        // Create Pension Agreements
        $this->organisationRepository->createPensionAgreement($singlePensionData);
        $this->organisationRepository->createPensionAgreement($sharedPensionData);

        // Create Time and Tax Settings
        $this->organisationRepository->createTimeSettings($timeData);
        foreach ($taxData as $data) {
            $this->organisationRepository->createTaxSettings($data);
        }

        //Create Alloance Settings
        foreach ($allowanceData as $data) {
            $this->organisationRepository->createOrgAllowance($data);
        }
    }
    //Assign To Org To Group
    public function assignOrgToGroup(Request $request)
    {
        try {
            $user = Auth::user();
            $companyName = $request->companyName;
            $email = $request->email;
            $address = $request->address;
            $description = $request->description;
            $groupId = $user->group_account_id;
            $type = $request->type;

            $org = $this->organisationRepository->findById($user->organisation_id);
            if (!$org || $org->is_active === false) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access group accout data at the moment',
                ], 400);
            }


            if ($type == "new") {
                //Create Group Account Data
                $data = [
                    "name" => $org->name,
                    "email" => $org->email,
                    "address" => $org->address,
                    "logo" => $org->logo
                ];

                //Check for exisiting group with email
                $existingGroup = $this->organisationRepository->getGroupAccountByEmail($org->email);
                if ($existingGroup) {
                    return response()->json([
                        'status' => 'failed',
                        'message' => 'Group account already exists',
                    ], 400);
                }
                ;
                $groupAccount = $this->organisationRepository->createGroupAccount($data);

                //Update User Information
                $userData = [
                    "email" => $org->email,
                    'is_group_account' => true,
                    'group_account_id' => $groupAccount->id,
                    'password' => Auth::user()->password
                ];

                $user = $this->userRepository->createUser($userData);

                $organisationData = [
                    'name' => $companyName,
                    'email' => $email,
                    'address' => $address,
                    'is_active' => false,
                    "description" => $description
                ];

                // Handle file upload
                if ($request->hasFile('logo') && $request->file('logo')->isValid()) {
                    $path = $request->file('logo')->store('uploads', 's3');
                    $organisationData['logo'] = Storage::disk('s3')->url($path);
                }

                // Create Organisation
                $organisation = $this->organisationRepository->createNewOrg($organisationData);

                //load Defaults
                $this->loadDefaults($organisation->id, $user->id);
                $email = $organisation->email;
                $token = Str::random(22);
                // $confirmation_url = env("FRONTEND_URL") . "/accept-group-account/{$token}";
                $mailData = [
                    "name" => $organisation->name,
                    "account_name" => $groupAccount->name,
                ];
                $groupAccount = $this->organisationRepository->assignOrgToGroup($organisation->id, $groupAccount->id);

                //Send Email 
                try {
                    Mail::to($email)->send(new GroupInvitationMail($mailData));
                } catch (\Exception $e) {
                    return response()->json([
                        'status' => 'failed',
                        'message' => $e->getMessage(),
                        'data' => []
                    ], 500);
                }
                ;
                return response()->json([
                    'status' => 'success',
                    'data' => $groupAccount,
                    'message' => 'Organisation Assigned To Group Successfully'
                ]);
            } else {
                $groupAccountData = $this->organisationRepository->getGroupAccount($groupId);

                // Check if organization account already exists with the same email
                $existingOrg = Organisation::where('email', $email)->first();
                if ($existingOrg) {
                    return response()->json([
                        'status' => 'failed',
                        'message' => 'Organisation with the provided email already exists',
                    ], 400);
                }

                $organisationData = [
                    'name' => $companyName,
                    'email' => $email,
                    'address' => $address,
                    'is_active' => false,
                    "description" => $description
                ];

                // Handle file upload
                if ($request->hasFile('logo') && $request->file('logo')->isValid()) {
                    $path = $request->file('logo')->store('uploads', 's3');
                    $organisationData['logo'] = Storage::disk('s3')->url($path);
                }

                // Create Organisation
                $organisation = $this->organisationRepository->createNewOrg($organisationData);

                //load Defaults
                $this->loadDefaults($organisation->id, $user->id);
                $email = $organisation->email;
                $token = Str::random(22);
                //$confirmation_url = env("FRONTEND_URL") . "/accept-group-account/{$token}";
                $mailData = [
                    "name" => $organisation->name,
                    "account_name" => $groupAccountData->name,
                ];
                $groupAccount = $this->organisationRepository->assignOrgToGroup($organisation->id, $groupId);

                //Send Email 
                try {
                    Mail::to($email)->send(new GroupInvitationMail($mailData));
                } catch (\Exception $e) {
                    return response()->json([
                        'status' => 'failed',
                        'message' => $e->getMessage(),
                        'data' => []
                    ], 500);
                }
                ;
                return response()->json([
                    'status' => 'success',
                    'data' => $groupAccount,
                    'message' => 'Organisation Assigned To Group Successfully.'
                ]);
            }
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //deactivate Org From Group
    public function removeOrgFromGroup(Request $request)
    {
        try {
            $user = Auth::user();
            $orgId = $request->orgId;
            $groupId = $user->group_account_id;

            if (!$user->is_group_account) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Not a group account'
                ], 400);
            }

            $deletedOrg = $this->organisationRepository->removeOrgFromGroup($orgId, $groupId);
            return response()->json([
                'status' => 'success',
                'data' => $deletedOrg,
                'message' => 'Organisation Removed Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }


    //Activate Org From Group
    public function activateOrg(Request $request)
    {
        try {
            $user = Auth::user();
            $orgId = $request->orgId;
            $groupId = $user->group_account_id;

            if (!$user->is_group_account) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Not a group account'
                ], 400);
            }

            $isGroupOrg = $this->organisationRepository->getSingleOrgInGroup($orgId, $groupId);
            if (empty($isGroupOrg)) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Organisation not under your group'
                ], 400);
            }
            ;
            $org = $this->organisationRepository->activateOrg($orgId);
            return response()->json([
                'status' => 'success',
                'data' => $org,
                'message' => 'Organisation Activated Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }


    //deactivate Org From Group
    public function deactivateOrg(Request $request)
    {
        try {
            $user = Auth::user();
            $orgId = $request->orgId;
            $groupId = $user->group_account_id;

            if (!$user->is_group_account) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Not a group account'
                ], 400);
            }

            $isGroupOrg = $this->organisationRepository->getSingleOrgInGroup($orgId, $groupId);
            if (empty($isGroupOrg)) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Organisation not under your group'
                ], 400);
            }
            ;
            $org = $this->organisationRepository->deactivateOrg($orgId);
            return response()->json([
                'status' => 'success',
                'data' => $org,
                'message' => 'Organisation Deactivated Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //List Org From Group
    public function listGroupOrg(Request $request)
    {
        try {
            $user = Auth::user();
            $groupId = $user->group_account_id;

            if (!$user->is_group_account) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Not a group account'
                ], 400);
            }

            $groupOrgs = $this->organisationRepository->listGroupOrgs($groupId);
            return response()->json([
                'status' => 'success',
                'data' => $groupOrgs,
                'message' => 'Organisation Returned Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function acceptGroupLink(Request $request)
    {
        try {
            $user = Auth::user();
            $orgId = $request->orgId;
            $token = $request->token;
            $groupId = $user->group_account_id;


            $isGroupOrg = $this->organisationRepository->getSingleOrgInGroupByToken($orgId, $token);
            if (empty($isGroupOrg)) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Token is invalid'
                ], 400);
            }
            ;

            //Update Org/Group State
            $updateData = [
                "is_active" => true,
                "token" => ""
            ];
            $org = $this->organisationRepository->updateGroupAccountOrg($isGroupOrg->id, $updateData);
            return response()->json([
                'status' => 'success',
                'data' => $org,
                'message' => 'Organisation Linked Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //List Org Metrics From Group
    public function listGroupOrgMetrics(Request $request)
    {
        try {
            $user = Auth::user();
            $groupId = $user->group_account_id;


            if (!$user->is_group_account) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Not a group account'
                ], 400);
            }

            $metrics = $this->organisationRepository->getGroupMetrics($groupId);
            return response()->json([
                'status' => 'success',
                'data' => $metrics,
                'message' => 'Organisation Metrics Returned Successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Create Exchange List
    public function createExchangeList(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $currency = $request->currency;
            $rate = $request->exchange_rate;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access settings at the moment',
                ], 400);
            }


            $exchangeRateData = [
                "currency" => $currency,
                "exchange_rate" => $rate,
                "organisation_id" => $org->id,
            ];

            $orgExchangeRate = $this->organisationRepository->createExchangeRate($exchangeRateData);
            return response()->json([
                'status' => 'success',
                'message' => 'Exchange Rate created successfully',
                'data' => $orgExchangeRate
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Update Exchange List
    public function updateExchangeList(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $currency = $request->currency;
            $rate = $request->exchange_rate;
            $rateId = $request->id;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access settings at the moment',
                ], 400);
            }


            //Check if rate exisits
            $existingRate = $this->organisationRepository->getOneExchangeRate($rateId);
            if (!$existingRate) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Exchange rate does not exist',
                ], 400);
            }
            $exchangeRateData = [
                "currency" => $currency,
                "exchange_rate" => $rate,
            ];

            $orgExchangeRate = $this->organisationRepository->updateExchangeRate($rateId, $exchangeRateData);
            return response()->json([
                'status' => 'success',
                'message' => 'Exchange Rate Updated successfully',
                'data' => $orgExchangeRate
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }


    //Get One Exchange List
    public function getOneExchangeList(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $rateId = $request->id;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access settings at the moment',
                ], 400);
            }


            //Check if rate exisits
            $existingRate = $this->organisationRepository->getOneExchangeRate($rateId);
            if (!$existingRate) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Exchange rate does not exist',
                ], 400);
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Exchange Rate Returned successfully',
                'data' => $existingRate
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Exchange List
    public function getAllExchangeList(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);


            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access settings at the moment',
                ], 400);
            }

            //Check if rate exisits
            $rates = $this->organisationRepository->getAllExchangeRate($org->id);


            return response()->json([
                'status' => 'success',
                'message' => 'Exchange Rates Returned successfully',
                'data' => $rates
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Delete One Exchange List
    public function deleteExchangeList(Request $request)
    {
        try {
            $user = Auth::user();
            $org = $this->organisationRepository->findById($user->organisation_id);
            $rateId = $request->id;

            if (!$org || $org->is_active === false) {

                return response()->json([
                    'status' => 'failed',
                    'message' => 'You cannot access settings at the moment',
                ], 400);
            }


            //Check if rate exisits
            $existingRate = $this->organisationRepository->getOneExchangeRate($rateId);
            if (!$existingRate) {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Exchange rate does not exist',
                ], 400);
            }

            $exchangeRate = $this->organisationRepository->deleteExchangeRate($rateId);

            return response()->json([
                'status' => 'success',
                'message' => 'Exchange Rate Deleted successfully',
                'data' => $existingRate
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
}
