<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ProcessPayrollController extends Controller
{

    public function index(){
        $departments = DB::table('departments')
            ->get();
        return view('ProcessPayroll.index', compact(['departments']));
    }

    Public function process_payroll(Request $request){
        $month = 2;#$request->month;
        $year = 2019;#$request->year;

        #Check if payroll has already been processed
        $payroll_status = DB::table('processed_payroll')
            ->where([
                ['month', $month],
                ['year', $year]
            ])
            ->get();

        if (count($payroll_status) > 0){
            #Respond: Failed, payroll has already been processed
            return response()->json(['status' => 1], 200);
        }else{
            try {
                DB::beginTransaction();

                ############################################################################################
                #1. Allowances
                ############################################################################################
                $allowances = DB::table('allowance_config')->get();

                $item = '1'; #1 = Allowances
                foreach ($allowances as $allowance) {
                    $item_name = $allowance->income_name;
                    $tax_option = $allowance->tax_option;

                    #Check if item is one time and the current status
                    $one_time = $allowance->one_time;

                    #If one_time is == 2, item has already been processed, skip processing
                    if ($one_time == 1){
                        continue;
                    }

                    $allowance_groups = DB::table('payroll_item_groups')
                        ->where([
                            ['payroll_item_id', $allowance->id],
                            ['payroll_item', 'allowance']
                        ])
                        ->get();

                    foreach ($allowance_groups as $allowance_group) {
                        $employees = $allowance_group->employees;
                        $employees = explode(',', $employees);
                        #Get the details of all the employees in this array
                        $employees = DB::table('main_users')
                            ->whereIn('main_users.id', $employees)
                            ->join('employee_salary_details', 'main_users.id', '=', 'employee_salary_details.user_id')
                            ->select('main_users.*', 'employee_salary_details.salary')
                            ->get();

                        #TABULATION TYPE
                        #Tabulation type determines the calculation method to be applied on the income
                        Switch ($allowance->tabulation_type) {
                            case 1: #Constant value
                                #Save in the payslip
                                foreach ($employees as $employee) {
                                    DB::table('payslips')
                                        ->insert([
                                            'user_id' => $employee->id,
                                            'month' => $month,
                                            'year' => $year,
                                            'item' => $item,
                                            'tax_option' => $tax_option,
                                            'item_name' => $item_name,
                                            'item_amount' => round($allowance_group->value, 2),
                                            'created_by' => 1,
                                            'created_at' => DB::raw('NOW()')
                                        ]);
                                }

                                break;
                            case 2: #Income percentage
                                #Save in the payslip
                                foreach ($employees as $employee) {
                                    DB::table('payslips')
                                        ->insert([
                                            'user_id' => $employee->id,
                                            'month' => $month,
                                            'year' => $year,
                                            'item' => $item,
                                            'tax_option' => $tax_option,
                                            'item_name' => $item_name,
                                            'item_amount' => round(($allowance_group->value / 100) * $employee->salary, 2),
                                            'created_by' => 1,
                                            'created_at' => DB::raw('NOW()')
                                        ]);
                                }
                                break;
                            case 3: #Range
                                $range_id = $allowance->range;
                                $range = DB::table('ranges')
                                    ->where('id', $range_id)
                                    ->first();
                                $range_calculation_method = $range->calculation_method;

                                foreach ($employees as $employee) {
                                    $range_details = DB::table('range_config')
                                        ->where([
                                            ['range_id', $range_id],
                                            ['lower_limit', '<=', $employee->salary],
                                            ['upper_limit', '>=', $employee->salary]
                                        ])
                                        ->first();

                                    $range_rate = $range_details->rate;

                                    switch ($range_calculation_method){
                                        case 1:
                                            DB::table('payslips')
                                                ->insert([
                                                    'user_id' => $employee->id,
                                                    'month' => $month,
                                                    'year' => $year,
                                                    'item' => $item,
                                                    'tax_option' => $tax_option,
                                                    'item_name' => $item_name,
                                                    'item_amount' => round($range_rate, 2),
                                                    'created_by' => 1,
                                                    'created_at' => DB::raw('NOW()')
                                                ]);
                                            break;
                                        case 2:
                                            DB::table('payslips')
                                                ->insert([
                                                    'user_id' => $employee->id,
                                                    'month' => $month,
                                                    'year' => $year,
                                                    'item' => $item,
                                                    'tax_option' => $tax_option,
                                                    'item_name' => $item_name,
                                                    'item_amount' => round((round($range_rate/100, 2)) * $employee->salary, 2),
                                                    'created_by' => 1,
                                                    'created_at' => DB::raw('NOW()')
                                                ]);
                                            break;
                                    }
                                }
                                break;
                        }
                    }

                    if ($allowance->income_type == 2){
                        DB::table('allowance_config')
                            ->where('id', $allowance->id)
                            ->update(
                                ['one_time' => 1]
                            );
                    }

                }

                ############################################################################################
                #2. Deductions
                ############################################################################################
                $deductions = DB::table('deduction_config')->get();

                $item = '2'; #2 = Deductions
                foreach ($deductions as $deduction) {
                    $item_name = $deduction->deduction_name;
                    $tax_option = $deduction->tax_option;

                    #Check if item is one time and the current status
                    $one_time = $deduction->one_time;

                    #If one_time is == 2, item has already been processed, skip processing
                    if ($one_time == 1){
                        continue;
                    }

                    $deduction_groups = DB::table('payroll_item_groups')
                        ->where([
                            ['payroll_item_id', $deduction->id],
                            ['payroll_item', 'deduction']
                        ])
                        ->get();

                    foreach ($deduction_groups as $deduction_group) {
                        $employees = $deduction_group->employees;
                        $employees = explode(',', $employees);

                        #Get the details of all the employees in this array
                        $employees = DB::table('main_users')
                            ->whereIn('main_users.id', $employees)
                            ->join('employee_salary_details', 'main_users.id', '=', 'employee_salary_details.user_id')
                            ->select('main_users.*', 'employee_salary_details.salary')
                            ->get();

                        #INCOME TYPE
                        #Income type establishes whether or not the deduction should be processed for this month


                        #TABULATION TYPE
                        #Tabulation type determines the calculation method to be applied on the income
                        Switch ($deduction->tabulation_type) {
                            case 1: #Constant value
                                #Save in the payslip
                                foreach ($employees as $employee) {
                                    DB::table('payslips')
                                        ->insert([
                                            'user_id' => $employee->id,
                                            'month' => $month,
                                            'year' => $year,
                                            'item' => $item,
                                            'tax_option' => $tax_option,
                                            'item_name' => $item_name,
                                            'item_amount' => round($deduction_group->value, 2),
                                            'created_by' => 1,
                                            'created_at' => DB::raw('NOW()')
                                        ]);
                                }

                                break;
                            case 2: #Income percentage
                                #Save in the payslip
                                foreach ($employees as $employee) {
                                    DB::table('payslips')
                                        ->insert([
                                            'user_id' => $employee->id,
                                            'month' => $month,
                                            'year' => $year,
                                            'item' => $item,
                                            'tax_option' => $tax_option,
                                            'item_name' => $item_name,
                                            'item_amount' => round(round($deduction_group->value/100, 2) * $employee->salary, 2),
                                            'created_by' => 1,
                                            'created_at' => DB::raw('NOW()')
                                        ]);
                                }
                                break;
                            case 3: #Range
                                $range_id = $deduction->range;
                                $range = DB::table('ranges')
                                    ->where('id', $range_id)
                                    ->first();
                                $range_calculation_method = $range->calculation_method;

                                foreach ($employees as $employee) {
                                    #Check whether the calculation method is for PAYE
                                    if ($range_calculation_method == 3){
                                        $range_details = DB::table('range_config')
                                            ->where([
                                                ['range_id', $range_id]
                                            ])
                                            ->orderBy('lower_limit', 'asc')
                                            ->get();
                                    }else{
                                        $range_details = DB::table('range_config')
                                            ->where([
                                                ['range_id', $range_id],
                                                ['lower_limit', '<=', $employee->salary],
                                                ['upper_limit', '>=', $employee->salary]
                                            ])
                                            ->first();

                                        $range_rate = $range_details->rate;
                                    }


                                    switch ($range_calculation_method){
                                        case 1:
                                            DB::table('payslips')
                                                ->insert([
                                                    'user_id' => $employee->id,
                                                    'month' => $month,
                                                    'year' => $year,
                                                    'item' => $item,
                                                    'tax_option' => $tax_option,
                                                    'item_name' => $item_name,
                                                    'item_amount' => round($range_rate, 2),
                                                    'created_by' => 1,
                                                    'created_at' => DB::raw('NOW()')
                                                ]);
                                            break;
                                        case 2:
                                            DB::table('payslips')
                                                ->insert([
                                                    'user_id' => $employee->id,
                                                    'month' => $month,
                                                    'year' => $year,
                                                    'item' => $item,
                                                    'tax_option' => $tax_option,
                                                    'item_name' => $item_name,
                                                    'item_amount' => round(round(round($range_rate/100, 2), 2) * $employee->salary, 2),
                                                    'created_by' => 1,
                                                    'created_at' => DB::raw('NOW()')
                                                ]);
                                            break;
                                        case 3:
                                            #Logic for PAYE calculator
                                            $salary = $employee->salary;

                                            $paye = 0;
                                            $count = 0;
                                            foreach ($range_details as $range_detail){
                                                if ($range_detail->lower_limit <= $salary && $range_detail->upper_limit >= $salary){
                                                    $paye_amount = round(($salary - $range_detail->lower_limit + 1) * round($range_detail->rate/100, 2), 2);

                                                    $paye = $paye + $paye_amount;
                                                    $count += 1;
                                                    break;
                                                }else{
                                                    if ($count == 0){
                                                        $paye_amount = round(($range_detail->upper_limit - $range_detail->lower_limit) * round($range_detail->rate/100, 2), 2);
                                                    }else{
                                                        $paye_amount = round(($range_detail->upper_limit - $range_detail->lower_limit + 1) * round($range_detail->rate/100, 2), 2);
                                                    }


                                                    $paye = $paye + $paye_amount;
                                                    $count += 1;
                                                }
                                            }

                                            DB::table('payslips')
                                                ->insert([
                                                    'user_id' => $employee->id,
                                                    'month' => $month,
                                                    'year' => $year,
                                                    'item' => $item,
                                                    'tax_option' => $tax_option,
                                                    'item_name' => $item_name,
                                                    'item_amount' => round($paye, 2),
                                                    'created_by' => 1,
                                                    'created_at' => DB::raw('NOW()')
                                                ]);
                                            break;
                                    }
                                }
                                break;
                        }
                    }

                    if ($deduction->income_type == 2){
                        DB::table('allowance_config')
                            ->where('id', $deduction->id)
                            ->update(
                                ['one_time' => 1]
                            );
                    }

                }

                ############################################################################################
                #3. Relief
                ############################################################################################
                $relief_ = DB::table('relief_config')->get();

                $item = '3'; #3 = Relief
                foreach ($relief_ as $relief) {
                    $item_name = $relief->relief_name;

                    $relief_groups = DB::table('payroll_item_groups')
                        ->where([
                            ['payroll_item_id', $relief->id],
                            ['payroll_item', 'relief']
                        ])
                        ->get();

                    foreach ($relief_groups as $relief_group) {
                        $employees = $relief_group->employees;
                        $employees = explode(',', $employees);

                        #Get the details of all the employees in this array
                        $employees = DB::table('main_users')
                            ->whereIn('main_users.id', $employees)
                            ->join('employee_salary_details', 'main_users.id', '=', 'employee_salary_details.user_id')
                            ->select('main_users.*', 'employee_salary_details.salary')
                            ->get();

                        #INCOME TYPE
                        #Income type establishes whether or not the relief should be processed for this month


                        #TABULATION TYPE
                        #Tabulation type determines the calculation method to be applied on the income
                        #Save in the payslip
                        foreach ($employees as $employee) {
                            DB::table('payslips')
                                ->insert([
                                    'user_id' => $employee->id,
                                    'month' => $month,
                                    'year' => $year,
                                    'item' => $item,
                                    'tax_option' => 0,
                                    'item_name' => $item_name,
                                    'item_amount' => round($relief_group->value, 2),
                                    'created_by' => 1,
                                    'created_at' => DB::raw('NOW()')
                                ]);
                        }
                    }

                }

                DB::commit();

            }catch(\Exception $e){

                DB::rollback();

                throw $e;

            }

            return view('ProcessPayroll.payroll_processed');
        }
    }
}
