<?php

// default config setting
$boolean_ssl_lock = true ;

include '../connect/cms-config.php' ;
include '../requires/function.php' ;

// defualt parameter
$get_type         = $_GET['get_type'] ;
$get_date         = $_GET['get_date'] ;
$get_staff_id     = $_GET['get_staff_id'] ;

$status           = '500' ; 
$message          = 'Failed' ;

if ( $get_type   == 'custom' ){
    // today is generate selected date report
    $date_yesterday  = $get_date ;
}else{
    // today is generate yesterday report
    $date_today      = TODAYDATE ;
    $date_yesterday  = date('Y-m-d', strtotime($date_today . ' -1 day')) ;
}

$current_hour     = date('H', time()) ;
$date_next        = date('Y-m-d', strtotime($date_yesterday . ' +1 day')) ;
$yesterday_day    = date('N', strtotime($date_yesterday)) ;

// check if is holiday
$boolean_holiday  = false ;
$holiday_name     = '' ;

$holiday_q        = $mysqli->query("SELECT holiday_name FROM setting_holiday
                                    WHERE deleted_at IS NULL AND holiday_date = '".$date_yesterday."' LIMIT 1") ;
if ( $holiday_q->num_rows ){
    $boolean_holiday = true ;
    $holiday         = $holiday_q->fetch_assoc() ;
    $holiday_name    = $holiday['holiday_name'] ;
}

// loop all staff
if ( $get_type == 'custom' ){
    $staffs_q   = $mysqli->query("SELECT staff_id, staff_idno, staff_name, group_id, country_id, staff_settings, work_type_id FROM staff
                                  WHERE deleted_at IS NULL AND staff_id = '".$get_staff_id."' LIMIT 1") ;
}else{
    $staffs_q =   $mysqli->query("SELECT staff_id, staff_idno, staff_name, group_id, country_id, staff_settings, work_type_id FROM staff
                                  WHERE deleted_at IS NULL AND ( staff_date_resigned >= '".date("Y-m-d",time())."' OR staff_date_resigned = '0000-00-00' OR staff_date_resigned IS NULL )") ;
}


if ( $staffs_q->num_rows > 0 ){

    $status   = '210' ;
    $message  = 'No staff found.' ;

    $staffs   = [] ;
    while ( $row = $staffs_q->fetch_assoc() ){
        $staffs[] = $row ;
    }

    // get all staff deparment
    $staff_department = [] ;
    $get_department   = $mysqli->query("SELECT staff_id, department_id FROM staff_department
                                        WHERE deleted_at IS NULL ORDER BY department_id") ;
    if ( $get_department->num_rows > 0 ){
        while ( $row_department = $get_department->fetch_assoc() ){
            $staff_department[$row_department['staff_id']][] = $row_department['department_id'] ;
        }
    }

    // cut off attendance report
    foreach ( $staffs as $key => $staff ){

        $status           = '201' ;
        $message          = 'Attendance list report was generated already.' ;

        $staff_id         = $staff['staff_id'] ;
        $list_type        = 'normal' ;
        $list_type_remark = 'WD' ;
        $list_remark      = '' ;
        $list_work_day    = '0' ;
        $list_ot_day      = '0' ;

        $list_work        = '00:00:00' ;

        $list_rest        = '00:00:00' ;
        $list_rest_more   = '00:00:00' ;
        $list_time_off    = '00:00:00' ;

        $list_rest2       = '00:00:00' ;
        $list_rest_more2  = '00:00:00' ;
        $list_time_off2   = '00:00:00' ;

        $list_early       = '00:00:00' ;
        $list_early_out   = '00:00:00' ;
        $list_late        = '00:00:00' ;
        $list_ot_normal   = '00:00:00' ;
        $list_leave_day   = 0 ;

        $wrong_punch      = [] ;
        $array_abnormal   = [] ;

        // staff setting
        $staff_settings   = $staff['staff_settings'] ;
        if ( $staff_settings   != '' ){
            $staff_settings     = JsonEncodeDecode('decode', $staff_settings) ;
        }else{
            $staff_settings     = [] ;
        }

        // check if not exists
        $attendance_list_q = $mysqli->query("SELECT list_id FROM staff_attendance_list
                                             WHERE deleted_at IS NULL AND staff_id = '".$staff_id."' AND list_date = '".$date_yesterday."' LIMIT 1") ;
        if ( $attendance_list_q->num_rows == 0 ){

            $status  = '209' ;
            $message = 'Selected staff no setting working hours.' ;

            // check staff working time, if not exists create
            $boolean_setting_working = false ;
            $working_q = $mysqli->query("SELECT working_id, working_on, working_next_day, working_if_flexi, working_if_include_rest, working_if_ot, working_direct_day, working_if_fixed_work, working_day_calculation, working_period_from, working_period_to, working_period_before, working_from, working_to, working_to_include_ot, working_total_hours, working_total_rest_hours, working_rest_range_from, working_rest_range_to, working_rest_include_ot, working_rounding_ot, working_if_ot_morning, working_if_offduty, working_count_offduty, working_if_deduct_offduty, working_max_ot,working_total_rest_hours2,working_rest_range_from2,working_rest_range_to2 FROM staff_attendance_working
                                         WHERE deleted_at IS NULL AND staff_id = '".$staff_id."' AND working_date = '".$date_yesterday."' LIMIT 1") ;
            if ( $working_q->num_rows == 0 ){

                // get staff working hours
                $working_q2 = $mysqli->query("SELECT group_id, working_on, working_next_day, working_if_flexi, working_if_include_rest, working_if_ot, working_direct_day, working_if_fixed_work, working_day_calculation, working_morning_start as working_period_from, working_morning_end as working_period_to, working_period_before, working_break_start as working_from, working_break_end as working_to, working_break_end_include_ot as working_to_include_ot, working_total_hours, working_total_rest_hours, working_rest_range_from, working_rest_range_to, working_rest_include_ot, working_rounding_ot, working_if_ot_morning, working_if_offduty, working_count_offduty, working_if_deduct_offduty, working_max_ot,working_total_rest_hours2,working_rest_range_from2,working_rest_range_to2 FROM setting_working
                                             WHERE deleted_at IS NULL AND group_id = '".$staff['group_id']."' AND working_day = '".$yesterday_day."' LIMIT 1") ;
                
                // check if working setting got set
                if ( $working_q2->num_rows > 0 ){
                    $boolean_setting_working = true ;
                    $working                 = $working_q2->fetch_assoc() ;
                    $mysqli->query("INSERT INTO staff_attendance_working
                                    (staff_id, working_group_id, working_date, working_on, working_next_day, working_if_flexi, working_if_include_rest, working_if_ot, working_direct_day, working_if_fixed_work, working_day_calculation, working_period_from, working_period_to, working_period_before, working_from, working_to, working_to_include_ot, working_total_hours, working_total_rest_hours, working_rest_range_from, working_rest_range_to, working_rest_include_ot, working_rounding_ot, working_if_ot_morning, working_if_offduty, working_count_offduty, working_if_deduct_offduty, working_max_ot, created_at, updated_at,working_total_rest_hours2,working_rest_range_from2,working_rest_range_to2) VALUES
                                    ('".$staff_id."', '".$working['group_id']."', '".$date_yesterday."', '".$working['working_on']."', '".$working['working_next_day']."', '".$working['working_if_flexi']."', '".$working['working_if_include_rest']."', '".$working['working_if_ot']."', '".$working['working_direct_day']."', '".$working['working_if_fixed_work']."', '".$working['working_day_calculation']."', '".$working['working_period_from']."', '".$working['working_period_to']."', '".$working['working_period_before']."', '".$working['working_from']."', '".$working['working_to']."', '".$working['working_to_include_ot']."', '".$working['working_total_hours']."', '".$working['working_total_rest_hours']."', ".( $working['working_rest_range_from'] != '' ? "'".$working['working_rest_range_from']."'" : "NULL" ).", ".( $working['working_rest_range_to'] != '' ? "'".$working['working_rest_range_to']."'" : "NULL" ).", ".( $working['working_rest_include_ot'] != '' ? "'".$working['working_rest_include_ot']."'" : "NULL" ).", '".$working['working_rounding_ot']."', '".$working['working_if_ot_morning']."', '".$working['working_if_offduty']."', '".$working['working_count_offduty']."', '".$working['working_if_deduct_offduty']."', '".$working['working_max_ot']."', '".TODAYDATE."', '".TODAYDATE."','".$working['working_total_rest_hours2']."',".($working['working_rest_range_from2'] !='' ? "'".$working['working_rest_range_from2']."'" : "NULL" ).",".($working['working_rest_range_to2'] != '' ? "'".$working['working_rest_range_to2']."'": "NULL" ).")") ;
                }
            }else{
                $boolean_setting_working = true ;
                $working                 = $working_q->fetch_assoc() ;
            }
            
            if ( $boolean_setting_working ){

                $status                  = '208' ;
                $message                 = 'Selected staff cannot generate attendance report currently.' ;

                // default parameter
                $total_hours             = $working['working_total_hours'] ;
                $total_rest_hours        = $working['working_total_rest_hours'] ;
                $total_rest_hours2       = $working['working_total_rest_hours2'] ;
                $boolean_rest_hours2     = ( $total_rest_hours2 != '' && $total_rest_hours2 != '00:00:00' ? 'yes' : 'no' ) ;
                $array_atten_ls          = [] ;
                $array_atten             = [] ;
                $punchiscorrect          = true ;

                // check if allow to insert attendances
                $check_current_datetime  = $date_yesterday.' '.$working['working_period_from'] ;
                $check_next_datetime     = $date_next.' '.$working['working_period_to'] ;
                if ( $working['working_to_include_ot'] > 0 ){
                    $check_next_datetime = date( 'Y-m-d H:i:s', strtotime('-'.$working['working_to_include_ot'].' hour', strtotime($check_next_datetime)) ) ;
                }

                // set running schedule time + 1 hours
                $check_running_datetime  = date( 'Y-m-d H:i:s', strtotime('+1 hour', strtotime($check_next_datetime)) ) ;


                $after_rest1             = date( 'Y-m-d', strtotime( $check_current_datetime ) ) . ' ' . $working['working_rest_range_from'] ;
                $after_rest2             = date( 'Y-m-d', strtotime( $check_current_datetime ) ) . ' ' . $working['working_rest_range_to'] ;

                if ( TODAYDATE > $check_running_datetime ){

                    // check if today got apply leave
                    $check_leave_q = $mysqli->query("SELECT a.leave_type, a.leave_work_day, b.leave_reason FROM staff_leave_date a
                                                     LEFT JOIN staff_leave b ON ( a.leave_id = b.leave_id )
                                                     WHERE a.deleted_at IS NULL AND a.staff_id = '".$staff_id."' AND a.leave_date = '".$date_yesterday."' AND b.deleted_at IS NULL AND b.leave_status = 'confirmed' LIMIT 1") ;
                    if ( $check_leave_q->num_rows > 0 ){

                        $check_leave    = $check_leave_q->fetch_assoc() ;
                        $list_type      = 'leave' ;
                        $list_remark    = $check_leave['leave_reason'] ;
                        $list_leave_day = $check_leave['leave_work_day'] ; 

                        switch ( $check_leave['leave_type'] ){
                            case 'unpaid' :
                                $list_type_remark = 'UL' ;
                            break ;
                            case 'annual' :
                                $list_type_remark = 'AL' ;
                            break ;
                            case 'sick' :
                                $list_type_remark = 'MC' ;
                            break ;
                        }
                    }

                    // check today is holiday or weekend
                    if ( $working['working_on'] == 'no' ){
                        $list_type            = 'weekend' ;
                        $list_type_remark     = 'OD' ;
                        $list_remark          = 'Off Day' ;
                        $list_work_day        = '0' ;
                    }else{
                        // if is holiday
                        if ( $boolean_holiday ){
                            $list_type        = 'holiday' ;
                            $list_type_remark = 'HL' ;
                            $list_remark      = $holiday_name ;
                            $list_work_day    = '0' ;
                        }
                    }

                    // filter between time period attendance
                    $attendance_q = $mysqli->query("SELECT attendance_id, created_at FROM staff_attendance
                                                    WHERE deleted_at IS NULL AND staff_id = '".$staff_id."' AND list_id = '0' AND created_at >= '".$check_current_datetime."' AND created_at <= '".$check_next_datetime."' ORDER BY created_at ASC") ;
                                                    
                    if ( $attendance_q->num_rows > 0 ){

                        $total_atten   = $attendance_q->num_rows ;
                        $last_atten    = '' ;
                        $working_from  = '00:00:00' ;
                        $first_in_time = '00:00:00' ;
                        $count_atten   = 0 ;
                        
                        // keep all attendance in array
                        while ( $attendance = $attendance_q->fetch_assoc() ){

                            $last_atten   = $attendance['created_at'] ;

                            // check working to
                            $working_to   = date('Y-m-d H:i:s', strtotime( date('Y-m-d', strtotime($last_atten)).' '.$working['working_to'] )) ;
                            if ( $working['working_if_flexi'] != 'yes' && $working['working_if_fixed_work'] == 'yes' ){
                                if ( $last_atten >= $working_to ){
                                    $last_atten = $working_to ;
                                }
                            }
                            
                            if ( $count_atten == 0 ){

                                if ( $working['working_if_flexi'] == 'yes' ){
                                    $working_from = $last_atten ;
                                }else{
                                    $working_from = date('Y-m-d H:i:s', strtotime( date('Y-m-d', strtotime($last_atten)).' '.$working['working_from'] )) ;
                                }
                                
                                $first_in_time = $last_atten ;
                                if ( $working_from >= $last_atten ){
                                    $last_atten = $working_from ;
                                }
                            }

                            $array_atten_ls[] = $attendance['attendance_id'] ;
                            $array_atten[]    = $last_atten ;
                            $count_atten++ ;

                        }

                        // generate new attendance if attendance is odd
                        if ( $total_atten%2 == 1 ){
                            $array_atten[]  = $last_atten ;
                            $punchiscorrect = false ;
                        }

                        if ( $array_atten['1'] >= $array_atten['0'] ){

                            // calculate work and rest and keep in array
                            $array_hours    = [] ;
                            $array_abnormal = [] ;
                            $next_hours     = '' ;
                            $rest_1_out     = '' ;
                            $rest_1_in      = '' ;
                            $rest_2_out     = '' ;
                            $rest_2_in      = '' ;
                            $count_rest     = 0 ;
                            foreach ( $array_atten as $k => $v ){
                                if ( $next_hours != '' ){
                                    $array_hours[] = subtractTime($v, $next_hours) ;
                                    if ( $count_rest == 1 ){
                                        $rest_1_out  = $v ;
                                    }
                                    if ( $count_rest == 2 ){
                                        $rest_1_in   = $v ;
                                    }
                                    if ( $count_rest == 3 ){
                                        $rest_2_out  = $v ;
                                    }
                                    if ( $count_rest == 4 ){
                                        $rest_2_in   = $v ;
                                    }
                                }
                                $next_hours = $v ;
                                $count_rest++ ;
                            }


                            // get total work & rest
                            foreach ( $array_hours as $k => $v ){
                                if ( $k%2 == 1 ){
                                    if ( $k == 1 ){
                                        $list_rest      = addTime($list_rest, $v) ;
                                    }else{
                                        if ( $boolean_rest_hours2 == 'yes' ){
                                            $list_rest2 = addTime($list_rest2, $v) ;
                                        }else{
                                            $list_rest  = addTime($list_rest, $v) ;
                                        }
                                    }
                                }else{
                                    $list_work = addTime($list_work, $v) ;
                                }
                                $prev_hours = $v ;
                            }


                            // check rest in & out if got time, and attendance time more than 2
                            // if range from and range to setting is empty do nothing
                            // check if under the range time, if yes do nothing, else checking total time off
                            $rest_array[] = [
                                'current_rest'            => '1',
                                'boolean_rest_hours'      => 'yes',
                                'array_atten_ls_1'        => 1,
                                'array_atten_ls_2'        => 2,
                                'total_rest_hours'        => $total_rest_hours,
                                'list_rest'               => $list_rest,
                                'list_rest_more'          => $list_rest_more,
                                'list_time_off'           => $list_time_off,
                                'rest_out'                => $rest_1_out,
                                'rest_in'                 => $rest_1_in,
                                'count_rest'              => 2,
                                'working_rest_range_from' => $working['working_rest_range_from'],
                                'working_rest_range_to'   => $working['working_rest_range_to']
                            ] ;
                            if ( $boolean_rest_hours2 ){
                                $rest_array[] = [
                                    'current_rest'            => '2',
                                    'boolean_rest_hours'      => $boolean_rest_hours2,
                                    'array_atten_ls_1'        => 3,
                                    'array_atten_ls_2'        => 4,
                                    'total_rest_hours'        => $total_rest_hours2,
                                    'list_rest'               => $list_rest2,
                                    'list_rest_more'          => $list_rest_more2,
                                    'list_time_off'           => $list_time_off2,
                                    'rest_out'                => $rest_2_out,
                                    'rest_in'                 => $rest_2_in,
                                    'count_rest'              => 4,
                                    'working_rest_range_from' => $working['working_rest_range_from2'],
                                    'working_rest_range_to'   => $working['working_rest_range_to2']
                                ] ;
                            }

                            foreach ( $rest_array as $krest => $vrest ){

                                $temp_list_time_off            = $vrest['list_time_off'] ;
                                $more_rest                     = '00:00:00' ;

                                if ( $vrest['boolean_rest_hours'] == 'yes' ){

                                    if ( $working['working_if_flexi'] == 'no' && $vrest['rest_out']   != '' && $vrest['rest_in'] != '' && $count_rest > $vrest['count_rest'] ){

                                        $rest_range_from       = $vrest['working_rest_range_from'] ;
                                        $rest_range_to         = $vrest['working_rest_range_to'] ;

                                        if ( ( $rest_range_from != '' && $rest_range_from != '00:00:00' ) && 
                                             ( $rest_range_to   != '' && $rest_range_to   != '00:00:00' ) ){

                                            $rest_range_from   = $date_yesterday . ' ' . $rest_range_from ;
                                            $rest_range_to     = $date_yesterday . ' ' . $rest_range_to ;

                                            if ( $rest_range_from > $vrest['rest_out'] || $rest_range_to < $vrest['rest_out'] || $rest_range_from > $vrest['rest_in'] || $rest_range_to < $vrest['rest_in'] ){
                                                
                                                // if situation 1 - early out
                                                // else - late out
                                                if ( $rest_range_from > $vrest['rest_out'] || $rest_range_to >= $vrest['rest_out'] ){

                                                    if ( $rest_range_from > $vrest['rest_in'] ){
                                                        $temp_list_time_off    = subtractTime($rest_range_from, $vrest['rest_out']) ;

                                                        $array_abnormal[] = $array_atten_ls[$vrest['array_atten_ls_1']] ;
                                                        $array_abnormal[] = $array_atten_ls[$vrest['array_atten_ls_2']] ;
                                                    }else{

                                                        if ( $rest_range_from > $vrest['rest_out'] && $rest_range_to < $vrest['rest_in'] ){
                                                            $deduct_out    = subtractTime($rest_range_from, $vrest['rest_out']) ;
                                                            $deduct_in     = subtractTime($vrest['rest_in'], $rest_range_to) ;
                                                            $temp_list_time_off = addTime($deduct_out, $deduct_in) ;

                                                            $array_abnormal[] = $array_atten_ls[$vrest['array_atten_ls_1']] ;
                                                            $array_abnormal[] = $array_atten_ls[$vrest['array_atten_ls_2']] ;
                                                        }elseif ( $rest_range_from <= $vrest['rest_out'] && $rest_range_to < $vrest['rest_in'] ){
                                                            $temp_list_time_off = subtractTime($vrest['rest_in'], $rest_range_to) ;

                                                            $array_abnormal[] = $array_atten_ls[$vrest['array_atten_ls_2']] ;
                                                        }else{
                                                            $temp_list_time_off = subtractTime($rest_range_from, $vrest['rest_out']) ;

                                                            $array_abnormal[] = $array_atten_ls[$vrest['array_atten_ls_1']] ;
                                                        }

                                                    }

                                                }else{
                                                    $temp_list_time_off    = subtractTime($vrest['rest_in'], $vrest['rest_out']) ;

                                                    $array_abnormal[] = $array_atten_ls[$vrest['array_atten_ls_2']] ;
                                                }

                                            }

                                        }
                                    }

                                    $boolean_rest     = false ;
                                    if ( $vrest['current_rest'] == '1' ){
                                        $boolean_rest = true ;
                                    }
                                    if ( $vrest['current_rest'] == '2' ){
                                        if ( $vrest['working_rest_range_from'] != '00:00:00' && $vrest['working_rest_range_to'] != '00:00:00' ){
                                            $setting_rest2_time = date( 'Y-m-d', strtotime( $check_current_datetime ) ) . ' ' . $vrest['working_rest_range_to'] ;
                                        }else{
                                            $setting_rest2_time = date( 'Y-m-d', strtotime( $check_current_datetime ) ) . ' ' . $working['working_to'] ;
                                            $setting_rest2_time = date( 'Y-m-d H:i:s', strtotime( $setting_rest2_time . ' +'.convertMinutes($vrest['total_rest_hours']).' minutes' ) ) ;
                                        }

                                        if ( $last_atten >= $working_to && $last_atten >= $setting_rest2_time ){
                                            $check_atten_hours  = subtractTime($last_atten, $working_to) ;
                                            $boolean_rest       = true ;
                                        }else{
                                            $list_rest2         = '00:00:00' ;
                                            $list_rest_more2    = '00:00:00' ;
                                            $list_time_off2     = '00:00:00' ;
                                        }
                                    }


                                    // calculate rest 
                                    if ( $vrest['total_rest_hours'] != '00:00:00' && $vrest['total_rest_hours'] != '' ){
                                        
                                        if ( $boolean_rest ){
                                            if ( $vrest['total_rest_hours'] > $vrest['list_rest'] ){
                                                $diff_rest                  = subtractTime($vrest['total_rest_hours'], $vrest['list_rest']) ;
                                                if ( $list_work             > '00:00:00' ){
                                                    $list_work              = subtractTime($list_work, $diff_rest) ;
                                                }
                                            }
                                        }

                                        if ( $vrest['list_rest']            > $vrest['total_rest_hours'] ){
                                            $more_rest                      = subtractTime($vrest['list_rest'], $vrest['total_rest_hours']) ;

                                            if ( $boolean_rest ){
                                                $list_work                  = addTime($list_work, $more_rest) ;
                                                $array_abnormal[]           = $array_atten_ls[$vrest['array_atten_ls_2']] ;
                                            }
                                        }
                                    }

                                    // if rest hour more than real rest hours within working hours
                                    if ( $boolean_rest ){
                                        if ( $vrest['total_rest_hours'] == '00:00:00' || $vrest['total_rest_hours'] == '' ){
                                            if ( $temp_list_time_off   != '00:00:00' && $temp_list_time_off != '' ){
                                                if ( $temp_list_time_off  > $vrest['total_rest_hours'] ){
                                                    $list_work          = addTime($list_work, $vrest['total_rest_hours']) ;
                                                    $temp_list_time_off = subtractTime($temp_list_time_off, $vrest['total_rest_hours']) ;
                                                }else{
                                                    $list_work          = addTime($list_work, $temp_list_time_off) ;
                                                    $temp_list_time_off = '00:00:00' ;
                                                }
                                            }
                                        }
                                    }

                                    // if ( $working['working_direct_day'] == 'no' ){
                                    if ( $list_type_remark != 'OD' && $list_type_remark != 'HL' ){
                                        switch ( $vrest['current_rest'] ){
                                            case '1' :
                                                $list_rest              = $vrest['total_rest_hours'] ;
                                                $list_rest_more         = $more_rest ;
                                                $list_time_off          = $temp_list_time_off ;
                                            break ;
                                            case '2' :
                                                $list_rest2             = $vrest['total_rest_hours'] ;
                                                $list_rest_more2        = $more_rest ;
                                                $list_time_off2         = $temp_list_time_off ;
                                            break ;
                                        }
                                    }

                                }
                            }


                            // get early / late / ot
                            if ( $working_from > $first_in_time ){
                                $list_early = subtractTime($working_from, $first_in_time) ;
                            }

                            $new_first_in_time = $first_in_time ;
                            if ( $working['working_rest_range_from'] != '00:00:00' ){
                                $new_first_in_time = date( 'Y-m-d', strtotime( $first_in_time ) ) . ' ' . $working['working_rest_range_from'] ;
                            }
                            if ( $first_in_time >= $working_from && $working_from < $new_first_in_time ){
                                if ( $new_first_in_time >= $first_in_time ){
                                    $list_late  = subtractTime($first_in_time, $working_from) ;
                                }else{
                                    $list_late  = subtractTime($new_first_in_time, $working_from) ;
                                }
                            }

                            // echo $list_late ;
                            // exit ;

                            // check if OT is count as total work?
                            // add the late hours to the total work
                            $list_work_total   = $list_work ;
                            // if ( $working['working_direct_day'] == 'yes' ){
                            if ( $list_type_remark == 'OD' || $list_type_remark == 'HL' ){
                                $total_hours   = '00:00:00' ;
                            }else{
                                if ( $working['working_if_flexi'] != 'yes' ){
                                    $list_work = addTime($list_work, $list_late) ;
                                }
                            }

                            // check if work enough hours
                            if ( $list_work >= $total_hours ){

                                // check if ot
                                if ( $working['working_if_ot'] == 'yes' ){

                                    if ( $list_work > $total_hours ){
                                        $list_ot_normal = subtractTime($list_work, $total_hours) ;
                                        $list_work      = subtractTime($list_work, $list_ot_normal) ;
                                    }

                                    // if off duty is yes
                                    if ( $working['working_if_offduty'] == 'yes' ){
                                        if ( $list_ot_normal >= $working['working_count_offduty'] ){
                                            if ( $working['working_if_deduct_offduty'] == 'no' ){
                                                $list_work      = addTime($list_work, $working['working_count_offduty']) ;
                                                $list_ot_normal = subtractTime($list_ot_normal, $working['working_count_offduty']) ;
                                            }
                                        }else{
                                            $list_work      = addTime($list_work, $list_ot_normal) ;
                                            $list_ot_normal = '00:00:00' ;
                                        }
                                    }

                                    // if ot rounding is greater than 1
                                    if ( $working['working_rounding_ot'] > 1 ){

                                        $working_rounding_ot  = strPad(2, $working['working_rounding_ot']) ;
                                        if ( $working_rounding_ot == '60' ){
                                            $rounding_ot      = '01:00:00' ;
                                        }else{
                                            $rounding_ot      = '00:'.$working_rounding_ot.':00' ;
                                        }
                                        $reset_list_ot_normal = $list_ot_normal ;
                                        $list_ot_normal       = '00:00:00' ;
                                        $boolean_ot           = true ;
                                        if ( $rounding_ot    <= $reset_list_ot_normal ){
                                            while ( $boolean_ot ){

                                                $reset_list_ot_normal = subtractTime($reset_list_ot_normal, $rounding_ot) ;
                                                $list_ot_normal       = addTime($list_ot_normal, $rounding_ot) ;
                                                if ( $rounding_ot > $reset_list_ot_normal ){
                                                    $boolean_ot = false ;
                                                }
                                            }


                                            // check if morning is count as ot
                                            if ( $working['working_if_ot_morning'] == 'yes' ){
                                                if ( $list_early   != '' && $list_early != '00:00:00' ){

                                                    $reset_list_ot_normal = $list_early ;
                                                    $boolean_ot           = true ;
                                                    if ( $rounding_ot <= $reset_list_ot_normal ){
                                                        while ( $boolean_ot ){

                                                            $reset_list_ot_normal = subtractTime($reset_list_ot_normal, $rounding_ot) ;
                                                            $list_ot_normal       = addTime($list_ot_normal, $rounding_ot) ;
                                                            if ( $rounding_ot > $reset_list_ot_normal ){
                                                                $boolean_ot = false ;
                                                            }
                                                        }
                                                    }
                                                    
                                                }
                                            }

                                        }
                                    }

                                    // check if OT is count as total work?
                                    // delete back the total work hours
                                    if ( $working['working_if_flexi'] != 'yes' ){
                                        $list_work = subtractTime($list_work, $list_late) ;
                                    }

                                    // check max ot hours
                                    $working_max_ot = $working['working_max_ot'] ;
                                    if ( $working_max_ot != '' && $working_max_ot != '00:00:00' ){
                                        if ( $list_ot_normal > $working_max_ot ){
                                            $list_work      = addTime( $list_work, subtractTime($working_max_ot, $list_ot_normal) ) ;
                                            $list_ot_normal = $working_max_ot ;
                                        }
                                    }

                                }

                            }else{
                                $list_early_out = subtractTime($total_hours, $list_work_total) ;
                                if ( $list_late != '00:00:00' ){
                                    $list_early_out = subtractTime($list_early_out, $list_late) ;
                                }
                                if ( $after_rest2 > $last_atten ){
                                    // $rest_exclude_early_out = subtractTime($after_rest2, $last_atten) ;
                                    // $list_early_out = subtractTime( $list_early_out, $rest_exclude_early_out ) ;
                                }
                            }
                        }
                    }else{
                        if ( $working['working_on'] == 'yes' && $list_type == 'normal' ){
                            $list_type_remark = 'AS' ;
                            $list_remark      = 'Absent' ;
                        }
                    }


                    // inside into db
                    // start commit
                    $error      = 0 ;
                    $mysqli->autocommit( false ) ;

                    try{

                        // check if normal working hours
                        if ( $list_work         != '00:00:00' ){

                            // reset late
                            $count_total_less    = 0 ;
                            $boolean_less        = true ;
                            $rounding_less       = $working['working_day_calculation'] ;
                            $get_list_early_out  = $list_early_out ;
                            $reset_list_less     = addTime($list_late, $get_list_early_out) ;
                            $reset_list_less     = addTime($reset_list_less, $list_time_off) ;

                            if ( $list_leave_day == '0.5' ){
                                if ( $list_late > $list_early_out ){
                                    $reset_list_less = subtractTime($reset_list_less, $total_rest_hours) ;
                                }
                            }

                            $reset_work          = $working['working_total_hours'] ;
                            $reset_ot_normal     = $list_ot_normal ;

                            if ( $reset_list_less != '00:00:00' && $reset_list_less > '00:01:00'){
                                $reset_list_less = subtractTime($reset_list_less, '00:01:00') ;

                                $rounding_less   = ( $rounding_less != '00:00:00' ? $rounding_less : '00:01' ) ;
                                if ( $rounding_less <= $reset_list_less ){
                                    while ( $boolean_less ){
                                        $reset_list_less = subtractTime($reset_list_less, $rounding_less) ;
                                        if ( $rounding_less > $reset_list_less ){
                                            $boolean_less = false ;
                                        }
                                        $count_total_less++ ;
                                    }
                                }

                                if ( $reset_list_less != '00:00:00' ){
                                    $count_total_less++ ;
                                }
                            }

                            // check if local / oversea worker, 1 = local, else oversea
                            if ( $count_total_less > 0 ){
                                for ( $a = $count_total_less ; $a > 0 ; $a-- ){
                                    // $deduct_from_day = true ;
                                    // if ( $staff['country_id'] == '1' ){

                                    // }else{
                                    //     if ( $working['working_if_ot'] == 'yes' && $reset_ot_normal != '00:00:00' ){
                                    //         $deduct_from_day = false ;
                                    //     }
                                    // }

                                    // // check if deduct from day or ot
                                    // if ( $deduct_from_day ){
                                        
                                    // }else{
                                    //     if ( $rounding_less > $reset_ot_normal ){
                                    //         $reset_ot_normal = '00:00:00' ;
                                    //     }else{
                                    //         $reset_ot_normal = subtractTime($reset_ot_normal, $rounding_less) ;
                                    //     }
                                    // }

                                    if ( $rounding_less > $reset_work ){
                                        $reset_work = '00:00:00' ;
                                    }else{
                                        $reset_work = subtractTime($reset_work, $rounding_less) ;
                                    }
                                }
                            }

                            // get working & ot day
                            if ( $reset_work != '00:00:00' ){
                                $reset_total_work   = numberFormat( convertMinutes($working['working_total_hours']), 2 ) ;
                                $reset_work         = numberFormat( convertMinutes($reset_work), 2 ) ;
                                $list_work_day     += numberFormat( ( $reset_work / $reset_total_work ), 2 ) ;
                                $list_work_day      = ( $list_leave_day == 0.5 ? 0.5 : ( $list_work_day > 0.5 ? 1 : ( $list_work_day > 0 ? 0.5 : 0 ) ) ) ;
                            }
                            if ( $reset_ot_normal != '00:00:00' ){
                                $explode_ot_normal  = explode(':', $reset_ot_normal) ;
                                $list_ot_day        = numberFormat ( ( $explode_ot_normal[0] . '.' . ( $explode_ot_normal[1] > 0 ? ( $explode_ot_normal[1] / 60 * 100 ) : '' ) ), 2 ) ;
                            }

                        }

                        // over x minutes just count as late
                        if ( $working['working_period_before'] > 0 ){
                            $count_late_minutes      = convertToTimes($working['working_period_before']) ;

                            if ( $list_late         != '00:00:00' ){
                                if ( $count_late_minutes > $list_late ){
                                    $list_work       = addTime($list_work, $list_late) ;
                                    $list_late       = '00:00:00' ;
                                }else{     
                                    $list_work       = addTime($list_work, $count_late_minutes) ;
                                    $list_late       = subtractTime($list_late, $count_late_minutes) ;
                                }
                            }
                        }

                        // work_type_id == 3 mean part time job
                        if ( $list_type_remark == 'WD' && $staff['work_type_id'] == '3' ){
                            $list_type_remark   = 'PT' ;
                        }

                        // check if abnormal attendance
                        if ( $list_late        != '00:00:00' ){
                            $array_abnormal[]   = $array_atten_ls[0] ;
                        }
                        if ( $list_early_out   != '00:00:00' ){
                            $array_abnormal[]   = end($array_atten_ls) ;
                        }

                        // if only work half day
                        $boolean_move_towork     = false ;
                        if ( ( $list_work_day + $list_leave_day ) == '0.5' ){
                            if ( convertMinutes( $list_late ) > 0 ){
                                $list_work_day  += 0.5 ;

                                if ( $working['working_rest_range_to'] != '00:00:00' ){
                                    if ( $first_in_time >= $after_rest1 && $after_rest2 > $first_in_time && $list_late != '00:00:00' ){
                                        $late_includerest = subtractTime( $after_rest2, $first_in_time ) ;  
                                        $list_late  = subtractTime( $list_late, $late_includerest ) ;
                                    }else{
                                        $boolean_move_towork = true ;
                                    }

                                }else{
                                    $boolean_move_towork = true ;
                                }
                            }else{
                                $boolean_move_towork = true ;
                            }
                        }
                        if ( $boolean_move_towork ){
                            if ( $list_rest    != '00:00:00' ){
                                $list_work      = addTime($list_work, $list_rest) ;
                            }
                            $list_rest          = '00:00:00' ;
                            $list_time_off      = '00:00:00' ;
                        }

                        if ( $list_work_day    == 0.5 && $list_leave_day == 0 ){
                            $list_work_day      = 1 ;
                        }

                        // combine all working hours as ot
                        // if ( $working['working_direct_day'] == 'yes' ){
                        if ( $list_type_remark == 'OD' || $list_type_remark == 'HL' ){
                            $list_work_day      = '0' ;
                            $list_ot_day        = '0' ;
                            $list_work          = '00:00:00' ;
                            $list_late          = '00:00:00' ;
                            $list_early         = '00:00:00' ;
                            $list_early_out     = '00:00:00' ;
                        }

                        // if leave half day, then filter out late / early out
                        if ( $working['working_if_flexi']    == 'no' ){
                            if ( $list_type_remark           == 'AL' || $list_type_remark == 'UL' || $list_type_remark == 'MC' ){
                                if ( $list_leave_day         == '0.5' ){
                                    $half_day_minutes         = ( convertMinutes( $total_hours ) / 2 ) ;
                                    $half_day_hours           = convertToTimes( $half_day_minutes ) ;
                                    
                                    if ( $list_late          >= $half_day_hours ){
                                        $list_late            = subtractTime( $list_late, $half_day_hours ) ;
                                        if ( $list_late      >= $total_rest_hours ){
                                            $list_late        = subtractTime( $list_late, $total_rest_hours ) ;
                                        }else{
                                            $list_late        = '00:00:00' ;
                                        }
                                    }else{
                                        $list_late            = '00:00:00' ;
                                    }

                                    if ( $list_early_out     >= $half_day_hours ){
                                        $list_early_out       = subtractTime( $list_early_out, $half_day_hours ) ;
                                        if ( $list_early_out >= $total_rest_hours ){
                                            $list_early_out   = subtractTime( $list_early_out, $total_rest_hours ) ;
                                        }else{
                                            $list_early_out   = '00:00:00' ;
                                        }
                                    }else{
                                        $list_early_out       = '00:00:00' ;
                                    }
                                }
                            }
                        }

                        if ( $working['working_rest_include_ot'] != '00:00:00' ){
                            if ( $list_rest != '00:00:00' ){
                                $temp_ot_rest          = addTime( $list_ot_normal, $list_rest ) ;
                                if ( $working['working_rest_include_ot'] >= $temp_ot_rest ){
                                    $list_ot_normal    = $temp_ot_rest ;
                                    $list_rest         = '00:00:00' ;
                                }
                            }
                        }

                        if ( !$punchiscorrect ){
                            $list_work_day    = 0 ;
                            $list_ot_day      = 0 ;
                            
                            $list_work        = '00:00:00' ;

                            $list_rest        = '00:00:00' ;
                            $list_rest_more   = '00:00:00' ;
                            $list_time_off    = '00:00:00' ;

                            $list_rest2       = '00:00:00' ;
                            $list_rest_more2  = '00:00:00' ;
                            $list_time_off2   = '00:00:00' ;

                            $list_early       = '00:00:00' ;
                            $list_early_out   = '00:00:00' ;
                            $list_late        = '00:00:00' ;
                            $list_ot_normal   = '00:00:00' ;

                            $array_abnormal   = [] ;
                        }

                        // show log
                        echo 'staff : <br />' ;
                        foreach ( $staff as $kk => $vv ){
                            echo $kk . ' -> ' . $vv ;
                            echo '<br />' ;
                        }
                        echo '<br />' ;
                        echo '<br />' ;

                        echo 'array_atten : <br />' ;
                        foreach ( $array_atten as $kk => $vv ){
                            echo $kk . ' -> ' . $vv ;
                            echo '<br />' ;
                        }
                        echo '<br />' ;
                        echo '<br />' ;

                        echo 'array_abnormal : <br />' ;
                        foreach ( $array_abnormal as $kk => $vv ){
                            echo $kk . ' -> ' . $vv ;
                            echo '<br />' ;
                        }
                        echo '<br />' ;
                        echo '<br />' ;

                        echo 'working : <br />' ;
                        foreach ( $working as $kk => $vv ){
                            echo $kk . ' -> ' . $vv ;
                            echo '<br />' ;
                        }
                        echo '<br />' ;
                        echo '<br />' ;

                        echo 'staff_id -> ' . $staff_id ;
                        echo '<br />' ;
                        echo 'list_type -> ' . $list_type ;
                        echo '<br />' ;
                        echo 'list_date -> ' . $date_yesterday ;
                        echo '<br />' ;
                        echo 'list_work_day -> ' . $list_work_day ;
                        echo '<br />' ;
                        echo 'list_ot_day -> ' . $list_ot_day ;
                        echo '<br />' ;
                        echo 'list_leave_day -> ' . $list_leave_day ;
                        echo '<br />' ;
                        echo 'list_early -> ' . $list_early ;
                        echo '<br />' ;
                        echo 'list_early_out -> ' . $list_early_out ;
                        echo '<br />' ;
                        echo 'list_late -> ' . $list_late ;
                        echo '<br />' ;
                        echo 'list_rest -> ' . $list_rest ;
                        echo '<br />' ;
                        echo 'list_rest_more -> ' . $list_rest_more ;
                        echo '<br />' ;
                        echo 'list_time_off -> ' . $list_time_off ;
                        echo '<br />' ;
                        echo 'list_rest2 -> ' . $list_rest2 ;
                        echo '<br />' ;
                        echo 'list_rest_more2 -> ' . $list_rest_more2 ;
                        echo '<br />' ;
                        echo 'list_time_off2 -> ' . $list_time_off2 ;
                        echo '<br />' ;
                        echo 'list_type -> ' . $list_type ;
                        echo '<br />' ;
                        echo 'list_type_remark -> ' . $list_type_remark ;
                        echo '<br />' ;
                        echo 'list_remark -> ' . $list_remark ;
                        echo '<br />' ;
                        echo 'list_work -> ' . $list_work ;
                        echo '<br />' ;
                        echo 'list_ot_normal -> ' . $list_ot_normal ;
                        echo '<br />' ;
                        echo '<br />' ;
                        echo '<br />' ;
                        // exit ;

                        $list_insert = $mysqli->query("INSERT INTO staff_attendance_list
                                                       (staff_id, list_date, list_checkinout, created_at, updated_at, list_work_day, list_ot_day, list_leave_day, list_early, list_early_out, list_late, list_rest, list_rest_more, list_time_off, list_rest2, list_rest_more2, list_time_off2, list_type, list_type_remark, list_remark, list_work, list_ot_normal) VALUES
                                                       ('".$staff_id."', '".$date_yesterday."', '".json_encode($array_atten)."', '".TODAYDATE."', '".TODAYDATE."', '".$list_work_day."', '".$list_ot_day."', '".$list_leave_day."', '".$list_early."', '".$list_early_out."', '".$list_late."', '".$list_rest."', '".$list_rest_more."', '".$list_time_off."', '".$list_rest2."', '".$list_rest_more2."', '".$list_time_off2."', '".$list_type."', '".$list_type_remark."', '".$list_remark."', '".$list_work."', '".$list_ot_normal."')") ;

                        if ( $mysqli->affected_rows > 0 ){

                            $last_insert  = $mysqli->insert_id ;
                            if ( count($array_atten_ls) > 0 ){

                                foreach ( $array_atten_ls as $k_atten => $v_atten ){
                                    $merge_insert = $mysqli->query("UPDATE staff_attendance SET
                                                                    " . ( in_array($v_atten, $array_abnormal) ? "abnormal = 'yes'," : '' ) . "
                                                                    list_id     = '".$last_insert."',
                                                                    check_group = '".$date_yesterday."'
                                                                    WHERE attendance_id = '".$v_atten."' ") ;
                                    if ( $mysqli->affected_rows > 0 ){ }else{
                                        $error++ ;
                                    }
                                }
                            }

                        }else{
                            $error++ ;
                        }

                    }catch( Exception $e ){
                        $error++;
                    }

                    if( $error == 0 ) {

                        // commit query
                        $mysqli->commit() ; 
                        $status  = '200' ;
                        $message = 'Success' ;

                    }else{
                        $mysqli->rollback() ;
                        $status  = '300' ;
                        $message = 'Something error, please try again later.' ;
                    } 

                }


            }


        }


    }

}

echo json_encode([
    'status'  => $status,
    'message' => $message
]) ;

?>