<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use App\Models\DailyAccident;
use App\Models\DailyAccidentSettings;
use App\Models\Province;
use Illuminate\Support\Facades\Storage;
use Carbon\Carbon;
use App\Http\Requests\DailyAccidentRequest;
use Spatie\Permission\Models\Permission;
use App\Services\NominatimService;


class DailyAccidentController extends Controller
{
    public function getAccidentReasons()
    {
        return response()->json(DailyAccidentSettings::where('type', 'accident_reasons')->get(), 200);
    }

    public function getAccidentIncreaseDamageReasons()
    {
        return response()->json(DailyAccidentSettings::where('type', 'increase_damage_reasons')->get(), 200);
    }

    public function getAccidentTypes()
    {
        return response()->json(DailyAccidentSettings::where('type', 'accident_type')->get(), 200);
    }

    public function getParticipants()
    {
        return response()->json(DailyAccidentSettings::where('type', 'participants')->get(), 200);
    }

    public function getAccidentCollisionType()
    {
        return response()->json(DailyAccidentSettings::where('type', 'collision_type')->get(), 200);
    }

    public function getAllAccidentForDataMining(Request $request)
    {
        if ($request->query('username') == "miner" && $request->query('password') == "!WRVf8dd_5XC(d8d") {

            $from_date = $request->query('from_date') ?? \Carbon\Carbon::now()->subDays(7);

            $to_date = $request->query('to_date') ?? \Carbon\Carbon::now();
            $province = $request->query('province') ?? null;
            
            $data = \App\Models\DailyAccident::whereBetween('accident_date', [$from_date . ' 00:00:00', $to_date . ' 23:59:59'])
                        ->select('*')
                        ->when($province, function ($query, $province) {
                            return $query->where('province_id', $province);
                        })
                        ->get();

            return response()->json($data, 200);

        }else {
            return response()->json(['message' => 'username or password is incorrect'], 402);
        }
    }

    public function show(Request $request)
    {
        $fields = ['id', 'province_fa', 'axis_name', 'axis_type_fa', 'axis_start', 'axis_end', 'distance_axis_start', 
                   'local_name', 'created_at', 'id', 'option', 'state', 'state_fa', 'number_of_injured', 'number_of_died', 
                   'collision_type_fa', 'way_geometri_fa', 'weather_condition_fa', 'day_of_the_week', 'accident_time', 
                   'accident_date', 'created_at', 'accident_type_fa', 'accident_type', 'axis_type_fa'];

        // $accidents_list = processDataTable($request, '', $fields, DailyAccident::where('excell', '>=', '0'));
        $accidents_list = processDataTable($request, DailyAccident::class, $fields);
        auth()->user()->addActivityComplete(1117);

        $result = [];
        foreach ($accidents_list['data'] as $key => $value) {

            if (Auth::user()->can('accident-investigation')) {
                $canInvestigationAccident = 1;
            } elseif (Auth::user()->can('accident-investigation-province')) {
                if ($value->province_id == Auth::user()->province_id) {
                    $canInvestigationAccident = 1;
                } else {
                    $canInvestigationAccident = 0;
                }
            } else {
                $canInvestigationAccident = 0;
            }
            
            if (Auth::user()->can('edit-accident')) {
                $canEditAccident = 1;
            } elseif (Auth::user()->can('edit-accident-province')) {
                if ($value->province_id == Auth::user()->province_id) {
                    $canEditAccident = 1;
                } else {
                    $canEditAccident = 0;
                }
            } else {
                $canEditAccident = 0;
            }

            if (Auth::user()->can('delete-accident')) {
                $canDeleteAccident = 1;
            } elseif (Auth::user()->can('delete-accident-province')) {
                if ($value->province_id == Auth::user()->province_id) {
                    $canDeleteAccident = 1;
                } else {
                    $canDeleteAccident = 0;
                }
            } else {
                $canDeleteAccident = 0;
            }

            $result[$key] = $value->toArray();
            $result[$key]['canEdit'] = $canEditAccident;
            $result[$key]['canDelete'] = $canDeleteAccident;
            $result[$key]['canInvestigation'] = $canInvestigationAccident;

        }

        return response()->json([
            "draw" => $accidents_list['draw'],
            "recordsTotal" => $accidents_list['recordsTotal'],
            "recordsFiltered" => $accidents_list['recordsFiltered'],
            'data' => $result,
        ], 200);

    }

    public function store(DailyAccidentRequest $request, NominatimService $nominatimService)
    {
        DB::transaction(function () use ($request, $nominatimService) {
            $new_daily_accident = new DailyAccident();

            $new_daily_accident->province_id = $request->province_id;
            $new_daily_accident->province_fa = Province::where('id', $request->province_id)->first()->name_fa;
            $new_daily_accident->axis_name = $request->axis_name;

            $new_daily_accident->axis_type = $request->axis_type;
            $new_daily_accident->axis_type_fa = setAxisTypeFa($request->axis_type);

            $new_daily_accident->axis_start = $request->axis_start;
            $new_daily_accident->axis_end = $request->axis_end;
            $new_daily_accident->distance_axis_start = $request->distance_axis_start;
            $new_daily_accident->local_name = $request->local_name;
            $new_daily_accident->lat = $request->lat;
            $new_daily_accident->lng = $request->lng;
            $new_daily_accident->police_serial = $request->police_serial;
            $new_daily_accident->accident_date = $request->accident_date;
            $new_daily_accident->accident_time = $request->accident_time;
            $new_daily_accident->day_of_the_week = $request->day_of_the_week;

            $new_daily_accident->direction = $request->direction;
            $new_daily_accident->setAxisDirectionFa($request->direction);

            $new_daily_accident->number_of_injured = $request->number_of_injured ?? 0;
            $new_daily_accident->number_of_died = $request->number_of_died ?? 0;

            $new_daily_accident->weather_condition = $request->weather_condition;
            $new_daily_accident->setWeatherConditionFa($request->weather_condition);

            $new_daily_accident->way_geometri = $request->way_geometri;
            $new_daily_accident->setWayGeometriFa($request->way_geometri);

            $new_daily_accident->collision_type = $request->collision_type;
            $new_daily_accident->collision_type_fa = DailyAccidentSettings::where('type', 'collision_type')->where('key', $request->collision_type)->first()->value;
            $new_daily_accident->participants_heavy_vehicle = $request->participants_heavy_vehicle ?? 0;
            $new_daily_accident->participants_light_vehicle = $request->participants_light_vehicle ?? 0;
            $new_daily_accident->participants_bicycle = $request->participants_bicycle ?? 0;
            $new_daily_accident->accident_type = $request->accident_type;
            $new_daily_accident->accident_type_fa = DailyAccidentSettings::where('type', 'accident_type')->where('name', $request->accident_type)->first()->value;

            $new_daily_accident->legal_speed = $request->legal_speed;
            $new_daily_accident->avarage_speed = $request->avarage_speed;

            $new_daily_accident->increase_damage_reasons_feqdan_jodakonnande_dar_miyane_rah = $request->increase_damage_reasons_feqdan_jodakonnande_dar_miyane_rah ?? 0;
            $new_daily_accident->increase_damage_reasons_naqs_ya_adam_kefayat_hefaze_miyani = $request->increase_damage_reasons_naqs_ya_adam_kefayat_hefaze_miyani ?? 0;
            $new_daily_accident->increase_damage_reasons_naqs_ya_adam_kefayat_narde_pol = $request->increase_damage_reasons_naqs_ya_adam_kefayat_narde_pol ?? 0;
            $new_daily_accident->increase_damage_reasons_naqs_ya_adam_kefayat = $request->increase_damage_reasons_naqs_ya_adam_kefayat ?? 0;
            $new_daily_accident->increase_damage_reasons_naqs_dar_naheye_enteqali = $request->increase_damage_reasons_naqs_dar_naheye_enteqali ?? 0;
            $new_daily_accident->increase_damage_reasons_mane_solb_bedone_hefaz = $request->increase_damage_reasons_mane_solb_bedone_hefaz ?? 0;
            $new_daily_accident->increase_damage_reasons_sar_azad_hefaz = $request->increase_damage_reasons_sar_azad_hefaz ?? 0;
            $new_daily_accident->increase_damage_reasons_shirvani_tond_ya_partgah = $request->increase_damage_reasons_shirvani_tond_ya_partgah ?? 0;

            $new_daily_accident->accident_reason_dor_monaseb_dar_qus = $request->accident_reason_dor_monaseb_dar_qus ?? 0;
            $new_daily_accident->accident_reason_saraziri_tond = $request->accident_reason_saraziri_tond ?? 0;
            $new_daily_accident->accident_reason_nabod_dar_khat_sebqat_dar_sarbalaye = $request->accident_reason_nabod_dar_khat_sebqat_dar_sarbalaye ?? 0;
            $new_daily_accident->accident_reason_mantaqe_ba_rizesh_az_divar = $request->accident_reason_mantaqe_ba_rizesh_az_divar ?? 0;
            $new_daily_accident->accident_reason_mantaqe_ba_afzayesh_nagahani = $request->accident_reason_mantaqe_ba_afzayesh_nagahani ?? 0;
            $new_daily_accident->accident_reason_kahesh_na_monaseb_tedad = $request->accident_reason_kahesh_na_monaseb_tedad ?? 0;
            $new_daily_accident->accident_reason_mantaqe_ba_obor_heyvanat_ahli = $request->accident_reason_mantaqe_ba_obor_heyvanat_ahli ?? 0;
            $new_daily_accident->accident_reason_mantaqe_ba_tadakhol_terafiki = $request->accident_reason_mantaqe_ba_tadakhol_terafiki ?? 0;
            $new_daily_accident->accident_reason_arze_kam_savare_ro = $request->accident_reason_arze_kam_savare_ro ?? 0;
            $new_daily_accident->accident_reason_mantaqe_meh_gir = $request->accident_reason_mantaqe_meh_gir ?? 0;
            $new_daily_accident->accident_reason_adam_roshanaye_zarori_dar_noqte = $request->accident_reason_adam_roshanaye_zarori_dar_noqte ?? 0;
            $new_daily_accident->accident_reason_tabdil_na_monaseb_noe_rah = $request->accident_reason_tabdil_na_monaseb_noe_rah ?? 0;
            $new_daily_accident->accident_reason_oftadegi_dar_labe_asphalt = $request->accident_reason_oftadegi_dar_labe_asphalt ?? 0;
            $new_daily_accident->accident_reason_naqs_dar_ashkarsazi_navahi = $request->accident_reason_naqs_dar_ashkarsazi_navahi ?? 0;
            $new_daily_accident->accident_reason_mahal_na_monaseb_dastrasi = $request->accident_reason_mahal_na_monaseb_dastrasi ?? 0;
            $new_daily_accident->accident_reason_roye_na_monaseb = $request->accident_reason_roye_na_monaseb ?? 0;
            $new_daily_accident->accident_reason_naqs_dar_ashkar_sazi_shrayet_khas = $request->accident_reason_naqs_dar_ashkar_sazi_shrayet_khas ?? 0;
            $new_daily_accident->accident_reason_hendese_na_monaseb_vorodi_va_khoroji = $request->accident_reason_hendese_na_monaseb_vorodi_va_khoroji ?? 0;
            $new_daily_accident->accident_reason_adam_rayat_fasele_tooli = $request->accident_reason_adam_rayat_fasele_tooli ?? 0;
            $new_daily_accident->accident_reason_naqs_dar_alayem_ekhtari_va_entezami = $request->accident_reason_naqs_dar_alayem_ekhtari_va_entezami ?? 0;
            $new_daily_accident->accident_reason_qus_ofoqi_dar_saraziri_tond = $request->accident_reason_qus_ofoqi_dar_saraziri_tond ?? 0;
            $new_daily_accident->accident_reason_adam_rayat_obor = $request->accident_reason_adam_rayat_obor ?? 0;
            $new_daily_accident->accident_reason_naqs_dar_alayem_pish_agahi = $request->accident_reason_naqs_dar_alayem_pish_agahi ?? 0;
            $new_daily_accident->accident_reason_qarar_gire_qus_ofoqi = $request->accident_reason_qarar_gire_qus_ofoqi ?? 0;
            $new_daily_accident->accident_reason_adam_rayat_sebghat_mojaz = $request->accident_reason_adam_rayat_sebghat_mojaz ?? 0;
            $new_daily_accident->accident_reason_did_na_kafi = $request->accident_reason_did_na_kafi ?? 0;
            $new_daily_accident->accident_reason_qus_tond_qaem = $request->accident_reason_qus_tond_qaem ?? 0;
            $new_daily_accident->accident_reason_adam_rayat_sorat_mojaz = $request->accident_reason_adam_rayat_sorat_mojaz ?? 0;
            $new_daily_accident->accident_reason_ebham_dar_masir = $request->accident_reason_ebham_dar_masir ?? 0;
            $new_daily_accident->accident_reason_qus_tond_ofoghi = $request->accident_reason_qus_tond_ofoghi ?? 0;

            $new_daily_accident->way_id = $nominatimService->get_way_id_from_nominatim($request->lat, $request->lng);

            $new_daily_accident->save();

            if ($request->has('first_image')) {
                $new_daily_accident->first_image = $request->file('first_image')->storeAs('daily_accident_files/' . $new_daily_accident->id, 'first_image_' . $new_daily_accident->id . '_' . time() . '.' . $request->file('first_image')->extension(), 'public');
            }

            if ($request->has('second_image')) {
                $new_daily_accident->second_image = $request->file('second_image')->storeAs('daily_accident_files/' . $new_daily_accident->id, 'second_image_' . $new_daily_accident->id . '_' . time() . '.' . $request->file('second_image')->extension(), 'public');
            }

            if ($request->has('police_file')) {
                $new_daily_accident->police_file = $request->file('police_file')->storeAs('daily_accident_files/' . $new_daily_accident->id, 'police_file_' . $new_daily_accident->id . '_' . time() . '.' . $request->file('police_file')->extension(), 'public');
            }
            auth()->user()->addActivityComplete(1118);

            $new_daily_accident->save();
        });
    }

    public function poster(Request $request)
    {
        $request->validate([
            'province_id' => 'numeric',
            'from_date' => 'date_format:Y-m-d',
            'to_date' => 'date_format:Y-m-d',
        ]);

        $province_id = $request->province_id;
        $from_date  = $request->from_date;
        $to_date  = $request->to_date;
        $data = [];

        $data['payamad_tasadof'] = DailyAccident::when($province_id, function ($query, $province_id) {
                                                    $query->where('province_id', $province_id);
                                                })
                                                ->when(($from_date && $to_date), function ($query) use ($from_date, $to_date) {
                                                    $query->whereBetween('accident_date', [$from_date . ' 00:00:00', $to_date . ' 23:59:59']);
                                                })
                                                ->selectRaw('sum(number_of_died) as number_of_died, sum(number_of_injured) as number_of_injured, count(id) as number_of_accident')
                                                ->get();

        // ACCIDENT REPORT -> PIE CHART
        $accident_types_with_zero_accidents = DailyAccident::selectRaw('0 as cnt, accident_type, accident_type_fa, 0 as percentage')
                                                           ->whereNotIn('accident_type_fa', function ($query) use ($province_id, $from_date, $to_date) {
                                                               $query->select('accident_type_fa')->distinct()
                                                                     ->from('daily_accidents')
                                                                     ->when($province_id, function ($query, $province_id) {
                                                                         $query->where('province_id', $province_id);
                                                                     })
                                                                     ->when(($from_date && $to_date), function ($query) use ($from_date, $to_date) {
                                                                         $query->whereBetween('accident_date', [$from_date . ' 00:00:00', $to_date . ' 23:59:59']);
                                                                     });
                                                           })
                                                           ->groupBy('accident_type_fa');

        $data['accident_report']['pie_chart'] = DailyAccident::when($province_id, function ($query, $province_id) {
                                                                $query->where('province_id', $province_id);
                                                            })
                                                            ->when(($from_date && $to_date), function ($query) use ($from_date, $to_date) {
                                                                $query->whereBetween('accident_date', [$from_date . ' 00:00:00', $to_date . ' 23:59:59']);
                                                            })
                                                            ->groupBy('accident_type_fa')
                                                            ->selectRaw('count(accident_type) as cnt, accident_type, accident_type_fa, round(count(*) * 100 / sum(count(*)) over(), 1) as percentage')
                                                            ->union($accident_types_with_zero_accidents)
                                                            // ->orderBy('accident_type', 'desc')
                                                            ->get();

        // END

        // ACCIDENT REPORT -> schematic_map AND NUMBER OF ACCIDENTS PER PROVINCE
        if(!$province_id){

            $provinces_with_zero_accidents = Province::whereNotIn('id', function ($query) use ($from_date, $to_date) {
                $query->select('province_id')
                      ->distinct('province_id')
                      ->from('daily_accidents')
                      ->when(($from_date && $to_date), function ($query) use ($from_date, $to_date) {
                        $query->whereBetween('accident_date', [$from_date . ' 00:00:00', $to_date . ' 23:59:59']);
                      });
            })->selectRaw('null, id, name_fa');

            $data['accident_report']['schematic_map'] = DailyAccident::when(($from_date && $to_date), function ($query) use ($from_date, $to_date) {
                                                                        $query->whereBetween('accident_date', [$from_date . ' 00:00:00', $to_date . ' 23:59:59']);
                                                                     })
                                                                     ->groupBy('province_id')
                                                                     ->selectRaw('count(*) as cnt, province_id, province_fa')
                                                                     ->union($provinces_with_zero_accidents)
                                                                     ->orderBy('province_id', 'asc')
                                                                     //  ->orderBy('cnt', 'asc')
                                                                     ->get();
                                                                    
            $data['number_of_accidents_per_province'] = $data['accident_report']['schematic_map'];
        }
        // END

        // ACCIDENT REPORT -> bar chart
        $way_geometries_with_zero_accidents = DailyAccident::selectRaw('0 as cnt, way_geometri, way_geometri_fa')
                                                           ->whereNotIn('way_geometri', function ($query) use ($province_id, $from_date, $to_date) {
                                                               $query->select('way_geometri')->distinct()
                                                                     ->from('daily_accidents')
                                                                     ->when($province_id, function ($query, $province_id) {
                                                                         $query->where('province_id', $province_id);
                                                                     })
                                                                     ->when(($from_date && $to_date), function ($query) use ($from_date, $to_date) {
                                                                         $query->whereBetween('accident_date', [$from_date . ' 00:00:00', $to_date . ' 23:59:59']);
                                                                     });
                                                           })
                                                           ->groupBy('way_geometri');

        $data['accident_report']['bar_chart'] = DailyAccident::when($province_id, function ($query, $province_id) {
                                                                $query->where('province_id', $province_id);
                                                             })
                                                             ->when(($from_date && $to_date), function ($query) use ($from_date, $to_date) {
                                                                $query->whereBetween('accident_date', [$from_date . ' 00:00:00', $to_date . ' 23:59:59']);
                                                             })
                                                             ->groupBy('way_geometri')
                                                             ->selectRaw('count(*) as cnt, way_geometri, way_geometri_fa')
                                                             ->union($way_geometries_with_zero_accidents)
                                                             ->orderBy('cnt', 'desc')
                                                             ->get();

        // END

        // share_of_accidents_by_road_type
        $share_by_road_type_data = DailyAccident::when($province_id, function ($query, $province_id) {
                                                    $query->where('province_id', $province_id);
                                                })
                                                ->when(($from_date && $to_date), function ($query) use ($from_date, $to_date) {
                                                    $query->whereBetween('accident_date', [$from_date . ' 00:00:00', $to_date . ' 23:59:59']);
                                                })
                                                ->groupBy('axis_type', 'accident_type')
                                                ->selectRaw('count(*) as cnt, axis_type, axis_type_fa, accident_type, accident_type_fa')
                                                ->get()->toArray();

        $result = [
            ['accident_type_fa' => 'خسارتی', 'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
            ['accident_type_fa' => 'جرحی', 'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
            ['accident_type_fa' => 'فوتی', 'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
        ];

        foreach ($share_by_road_type_data as $item) {
            $key = $item['accident_type'] - 1;

            foreach ($result[$key]['data'] as $k => $axis_data) {
                if ($axis_data['axis_type_fa'] == $item['axis_type_fa']) {
                    $result[$key]['data'][$k]['cnt'] = $item['cnt'];
                    break;
                }
            }
        }

        $data['share_of_accidents_by_road_type'] = $result;
        // END

        // share_of_accidents_by_road_geometry
        $share_by_road_geometry_data = DailyAccident::when($province_id, function ($query, $province_id) {
                                                        $query->where('province_id', $province_id);
                                                    })
                                                    ->when(($from_date && $to_date), function ($query) use ($from_date, $to_date) {
                                                        $query->whereBetween('accident_date', [$from_date . ' 00:00:00', $to_date . ' 23:59:59']);
                                                    })
                                                    ->groupBy('way_geometri', 'axis_type')
                                                    ->selectRaw('count(*) as cnt, way_geometri, way_geometri_fa, axis_type, axis_type_fa')
                                                    ->get()->toArray();

        $result = [
            ['way_geometri_fa' => 'تقاطع - دسترسی',   'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
            ['way_geometri_fa' => 'قوس افقی یا قائم', 'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
            ['way_geometri_fa' => 'پل',                'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
            ['way_geometri_fa' => 'پل و قوس',          'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
            ['way_geometri_fa' => 'تونل',              'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
            ['way_geometri_fa' => 'میدان',             'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
            ['way_geometri_fa' => 'دوربرگردان',        'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
            ['way_geometri_fa' => 'بریدگی',            'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
            ['way_geometri_fa' => 'تقاطع و قوس',       'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
            ['way_geometri_fa' => 'نقطه عادی',         'data' => [['axis_type_fa' => 'آزادراه', 'cnt' => 0], ['axis_type_fa' => 'بزرگراه', 'cnt' => 0], ['axis_type_fa' => 'اصلی', 'cnt' => 0], ['axis_type_fa' => 'فرعی', 'cnt' => 0]]],
        ];

        foreach ($share_by_road_geometry_data as $item) {
            $key = $item['way_geometri'] - 1;

            foreach ($result[$key]['data'] as $k => $axis_data) {
                if ($axis_data['axis_type_fa'] == $item['axis_type_fa']) {
                    $result[$key]['data'][$k]['cnt'] = $item['cnt'];
                    break;
                }
            }
        }

        $data['share_of_accidents_by_road_geometry'] = $result;
        // END

        // collision type
        $collision_types_with_zero_accidents = DailyAccident::selectRaw('0 as percentage, collision_type, collision_type_fa')
                                                            ->whereNotIn('collision_type', function ($query) use ($province_id, $from_date, $to_date) {
                                                                $query->select('collision_type')->distinct()
                                                                      ->from('daily_accidents')
                                                                      ->when($province_id, function ($query, $province_id) {
                                                                          $query->where('province_id', $province_id);
                                                                      })
                                                                      ->when(($from_date && $to_date), function ($query) use ($from_date, $to_date) {
                                                                        $query->whereBetween('accident_date', [$from_date . ' 00:00:00', $to_date . ' 23:59:59']);
                                                                      });
                                                                        
                                                            })
                                                            ->groupBy('collision_type');

        // dd($collision_types_with_zero_accidents->get())                                                            ;

        $data['collision_type'] = DailyAccident::when($province_id, function ($query, $province_id) {
                                                    $query->where('province_id', $province_id);
                                               })
                                               ->when(($from_date && $to_date), function ($query) use ($from_date, $to_date) {
                                                    $query->whereBetween('accident_date', [$from_date . ' 00:00:00', $to_date . ' 23:59:59']);
                                               })
                                               ->whereNotNull(['collision_type', 'collision_type_fa'])
                                               ->groupBy('collision_type')
                                               ->selectRaw('round(count(*) * 100 / sum(count(*)) over(), 1) as percentage, collision_type, collision_type_fa')
                                               ->union($collision_types_with_zero_accidents)
                                               ->orderBy('percentage', 'desc')
                                               ->get();
        // END


        // per day
        $where_province_exists = ($province_id) ? "province_id = $province_id and" : '';
        $where_date_exists = ($from_date && $to_date) ? "accident_date BETWEEN '$from_date 00:00:00' and '$to_date 23:59:59' and" : '';
        // dd($where_date_exists);
        $per_day_array = DB::select("SELECT t1.*,  round(sum(t1.cnt) over(PARTITION by day_part) * 100 / sum(t1.cnt) over(), 1) as day_percentage
                                            from
                                                (select count(*) as cnt, sum(count(*)) over() as total, round(count(*) * 100/ sum(count(*)) over(), 1) as percent, accident_type, accident_type_fa, 'day' as day_part 
                                                        from daily_accidents da where $where_province_exists $where_date_exists accident_time BETWEEN '06:00:00' and '18:00:00' group by accident_type
                                                    UNION 
                                                select count(*) as cnt, sum(count(*)) over() as total, round(count(*) * 100/ sum(count(*)) over(), 1) as percent, accident_type, accident_type_fa, 'night' as day_part 
                                                        from daily_accidents da where $where_province_exists $where_date_exists accident_time not BETWEEN '06:00:00' and '18:00:00' group by accident_type)t1
                                            order by day_part");

        // dd($per_day_array);

        $per_day_result = [
            ['accident_type_fa' => 'خسارتی', 'night' => ['cnt' => 0, 'percent' => 0, 'total_percentage' => 0], 'day' => ['cnt' => 0, 'percent' => 0, 'total_percentage' => 0]],
            ['accident_type_fa' => 'جرحی', 'night' => ['cnt' => 0, 'percent' => 0, 'total_percentage' => 0], 'day' => ['cnt' => 0, 'percent' => 0, 'total_percentage' => 0]],
            ['accident_type_fa' => 'فوتی', 'night' => ['cnt' => 0, 'percent' => 0, 'total_percentage' => 0], 'day' => ['cnt' => 0, 'percent' => 0, 'total_percentage' => 0]]
        ];

        $per_day_array = json_decode(json_encode($per_day_array), true);

        foreach ($per_day_array as $item) {
            $key = $item['accident_type'] - 1;
            $per_day_result[$key][$item['day_part']]['cnt'] = $item['cnt'];
            $per_day_result[$key][$item['day_part']]['percent'] = $item['percent'];
            // $per_day_result[$key][$item['day_part']]['total_percentage'] = $item['day_percentage'];

            for ($i=0; $i < count($per_day_result); $i++) { 
                $per_day_result[$i][$item['day_part']]['total_percentage'] = $item['day_percentage'];
            }
        }

        $data['per_day'] = $per_day_result;
        // END

        return view('posters.DailyAccidentPoster', compact("data"));
    }

    // public function getPosterInformation(Request $request)
    // {
    //     $data = [];

    //     $data['amir'] = DailyAccident::groupBy('accident_type')
    //     ->whereIn('accident_type',[2,3])
    //     ->select('accident_type_fa', 'accident_type', DB::raw('sum(number_of_died) as number_of_died'), DB::raw('sum(number_of_injured) as number_of_injured'))
    //     ->get();


    //     if ($request->develop) {
    //         dd(DailyAccident::groupBy('accident_type')->whereIn('accident_type',[2,3])->select('accident_type_fa', 'accident_type', DB::raw('sum(number_of_died) as number_of_died'), DB::raw('sum(number_of_injured) as number_of_injured'))->get());
    //     }

    //     return response()->json(
    //         $data,
    //         200
    //     );
    // }

    public function details(DailyAccident $accident)
    {
        return response()->json(
            $accident,
            200
        );
    }

    public function delete(DailyAccident $accident)
    {
        Storage::deleteDirectory('public/' . 'daily_accident_files/' . $accident->id);
        auth()->user()->addActivityComplete(1120, $accident);
        $accident->delete();
        return response()->json([
            'message' => 'delete process is successfully'
        ], 200);
    }

    public function update(DailyAccident $accident, Request $request, NominatimService $nominatimService)
    {
        DB::transaction(function () use ($request, $accident, $nominatimService) {
            ;
            auth()->user()->addActivityComplete(1119, $accident);

            $accident->province_id = $request->province_id;
            $accident->province_fa = Province::where('id', $request->province_id)->first()->name_fa;
            $accident->axis_name = $request->axis_name;

            $accident->axis_type = $request->axis_type;
            $accident->axis_type_fa = setAxisTypeFa($request->axis_type);

            $accident->axis_start = $request->axis_start;
            $accident->axis_end = $request->axis_end;
            $accident->distance_axis_start = (float) $request->distance_axis_start;
            $accident->local_name = $request->local_name;
            $accident->lat = $request->lat;
            $accident->lng = $request->lng;
            $accident->police_serial = $request->police_serial;
            $accident->accident_date = $request->accident_date;
            $accident->accident_time = $request->accident_time;
            $accident->day_of_the_week = $request->day_of_the_week;

            $accident->direction = $request->direction;
            $accident->setAxisDirectionFa($request->direction);

            $accident->number_of_injured = $request->number_of_injured ?? 0;
            $accident->number_of_died = $request->number_of_died ?? 0;

            $accident->weather_condition = $request->weather_condition;
            $accident->setWeatherConditionFa($request->weather_condition);

            $accident->way_geometri = $request->way_geometri;
            $accident->setWayGeometriFa($request->way_geometri);

            $accident->collision_type = $request->collision_type;
            $accident->collision_type_fa = DailyAccidentSettings::where('type', 'collision_type')->where('key', $request->collision_type)->first()->value;
            $accident->participants_heavy_vehicle = $request->participants_heavy_vehicle ?? 0;
            $accident->participants_light_vehicle = $request->participants_light_vehicle ?? 0;
            $accident->participants_bicycle = $request->participants_bicycle ?? 0;
            $accident->accident_type = $request->accident_type;
            $accident->accident_type_fa = DailyAccidentSettings::where('type', 'accident_type')->where('name', $request->accident_type)->first()->value;

            $accident->legal_speed = $request->legal_speed;
            $accident->avarage_speed = $request->avarage_speed;

            $accident->increase_damage_reasons_feqdan_jodakonnande_dar_miyane_rah = $request->increase_damage_reasons_feqdan_jodakonnande_dar_miyane_rah ?? 0;
            $accident->increase_damage_reasons_naqs_ya_adam_kefayat_hefaze_miyani = $request->increase_damage_reasons_naqs_ya_adam_kefayat_hefaze_miyani ?? 0;
            $accident->increase_damage_reasons_naqs_ya_adam_kefayat_narde_pol = $request->increase_damage_reasons_naqs_ya_adam_kefayat_narde_pol ?? 0;
            $accident->increase_damage_reasons_naqs_ya_adam_kefayat = $request->increase_damage_reasons_naqs_ya_adam_kefayat ?? 0;
            $accident->increase_damage_reasons_naqs_dar_naheye_enteqali = $request->increase_damage_reasons_naqs_dar_naheye_enteqali ?? 0;
            $accident->increase_damage_reasons_mane_solb_bedone_hefaz = $request->increase_damage_reasons_mane_solb_bedone_hefaz ?? 0;
            $accident->increase_damage_reasons_sar_azad_hefaz = $request->increase_damage_reasons_sar_azad_hefaz ?? 0;
            $accident->increase_damage_reasons_shirvani_tond_ya_partgah = $request->increase_damage_reasons_shirvani_tond_ya_partgah ?? 0;

            $accident->accident_reason_dor_monaseb_dar_qus = $request->accident_reason_dor_monaseb_dar_qus ?? 0;
            $accident->accident_reason_saraziri_tond = $request->accident_reason_saraziri_tond ?? 0;
            $accident->accident_reason_nabod_dar_khat_sebqat_dar_sarbalaye = $request->accident_reason_nabod_dar_khat_sebqat_dar_sarbalaye ?? 0;
            $accident->accident_reason_mantaqe_ba_rizesh_az_divar = $request->accident_reason_mantaqe_ba_rizesh_az_divar ?? 0;
            $accident->accident_reason_mantaqe_ba_afzayesh_nagahani = $request->accident_reason_mantaqe_ba_afzayesh_nagahani ?? 0;
            $accident->accident_reason_kahesh_na_monaseb_tedad = $request->accident_reason_kahesh_na_monaseb_tedad ?? 0;
            $accident->accident_reason_mantaqe_ba_obor_heyvanat_ahli = $request->accident_reason_mantaqe_ba_obor_heyvanat_ahli ?? 0;
            $accident->accident_reason_mantaqe_ba_tadakhol_terafiki = $request->accident_reason_mantaqe_ba_tadakhol_terafiki ?? 0;
            $accident->accident_reason_arze_kam_savare_ro = $request->accident_reason_arze_kam_savare_ro ?? 0;
            $accident->accident_reason_mantaqe_meh_gir = $request->accident_reason_mantaqe_meh_gir ?? 0;
            $accident->accident_reason_adam_roshanaye_zarori_dar_noqte = $request->accident_reason_adam_roshanaye_zarori_dar_noqte ?? 0;
            $accident->accident_reason_tabdil_na_monaseb_noe_rah = $request->accident_reason_tabdil_na_monaseb_noe_rah ?? 0;
            $accident->accident_reason_oftadegi_dar_labe_asphalt = $request->accident_reason_oftadegi_dar_labe_asphalt ?? 0;
            $accident->accident_reason_naqs_dar_ashkarsazi_navahi = $request->accident_reason_naqs_dar_ashkarsazi_navahi ?? 0;
            $accident->accident_reason_mahal_na_monaseb_dastrasi = $request->accident_reason_mahal_na_monaseb_dastrasi ?? 0;
            $accident->accident_reason_roye_na_monaseb = $request->accident_reason_roye_na_monaseb ?? 0;
            $accident->accident_reason_naqs_dar_ashkar_sazi_shrayet_khas = $request->accident_reason_naqs_dar_ashkar_sazi_shrayet_khas ?? 0;
            $accident->accident_reason_hendese_na_monaseb_vorodi_va_khoroji = $request->accident_reason_hendese_na_monaseb_vorodi_va_khoroji ?? 0;
            $accident->accident_reason_adam_rayat_fasele_tooli = $request->accident_reason_adam_rayat_fasele_tooli ?? 0;
            $accident->accident_reason_naqs_dar_alayem_ekhtari_va_entezami = $request->accident_reason_naqs_dar_alayem_ekhtari_va_entezami ?? 0;
            $accident->accident_reason_qus_ofoqi_dar_saraziri_tond = $request->accident_reason_qus_ofoqi_dar_saraziri_tond ?? 0;
            $accident->accident_reason_adam_rayat_obor = $request->accident_reason_adam_rayat_obor ?? 0;
            $accident->accident_reason_naqs_dar_alayem_pish_agahi = $request->accident_reason_naqs_dar_alayem_pish_agahi ?? 0;
            $accident->accident_reason_qarar_gire_qus_ofoqi = $request->accident_reason_qarar_gire_qus_ofoqi ?? 0;
            $accident->accident_reason_adam_rayat_sebghat_mojaz = $request->accident_reason_adam_rayat_sebghat_mojaz ?? 0;
            $accident->accident_reason_did_na_kafi = $request->accident_reason_did_na_kafi ?? 0;
            $accident->accident_reason_qus_tond_qaem = $request->accident_reason_qus_tond_qaem ?? 0;
            $accident->accident_reason_adam_rayat_sorat_mojaz = $request->accident_reason_adam_rayat_sorat_mojaz ?? 0;
            $accident->accident_reason_ebham_dar_masir = $request->accident_reason_ebham_dar_masir ?? 0;
            $accident->accident_reason_qus_tond_ofoghi = $request->accident_reason_qus_tond_ofoghi ?? 0;

            $accident->way_id = $nominatimService->get_way_id_from_nominatim($request->lat, $request->lng);

            $accident->save();

            if ($request->has('first_image')) {
                Storage::delete('public/' . $accident->first_image);
                $accident->first_image = $request->file('first_image')->storeAs('daily_accident_files/' . $accident->id, 'first_image_' . $accident->id . '_' . time() . '.' . $request->file('first_image')->extension(), 'public');
            } elseif ($request->has('first_image_is_deleted') && (int)$request->first_image_is_deleted) {
                Storage::delete('public/' . $accident->first_image);
                $accident->first_image = null;
            }

            if ($request->has('second_image')) {
                Storage::delete('public/' . $accident->second_image);
                $accident->second_image = $request->file('second_image')->storeAs('daily_accident_files/' . $accident->id, 'second_image_' . $accident->id . '_' . time() . '.' . $request->file('second_image')->extension(), 'public');
            } elseif ($request->has('second_image_is_deleted') && (int)$request->second_image_is_deleted) {
                Storage::delete('public/' . $accident->second_image);
                $accident->second_image = null;
            }

            if ($request->has('police_file')) {
                Storage::delete('public/' . $accident->police_file);
                $accident->police_file = $request->file('police_file')->storeAs('daily_accident_files/' . $accident->id, 'police_file_' . $accident->id . '_' . time() . '.' . $request->file('police_file')->extension(), 'public');
            } elseif ($request->has('police_file_is_deleted') && (int)$request->police_file_is_deleted) {
                Storage::delete('public/' . $accident->police_file);
                $accident->police_file = null;
            }

            $accident->save();

            // $new_daily_accident_history = new DailyAccidentHistory();
            // $new_daily_accident_history->state = 2;
            // $new_daily_accident_history->state_fa = 'در حال بررسی';
            // $new_daily_accident_history->subject_id = $accident->id;
            // $new_daily_accident_history->user_id = Auth::user()->id;
            // $new_daily_accident_history->user_name = Auth::user()->first_name." ".Auth::user()->last_name."(".Auth::user()->name.")";
            // $new_daily_accident_history->save();
        });
    }

    public function setState(DailyAccident $accident, Request $request)
    {
        $request->validate(
            [
                'state' => 'required|boolean',
                'message' => 'exclude_if:state,1|required|max:300',
            ],
        );

        if ($request->state) {
            $accident->state_fa = 'تایید شده';
            $accident->state = 1;
        } else {
            $accident->state_fa = 'عدم تایید';
            $accident->state = 0;
            $accident->message = $request->message;
        }

        $accident->state_updated_at = Carbon::now();
        $accident->save();
        auth()->user()->addActivityComplete(1121, $accident);
        return response()->json([
            'message' => 'change status successfuly'
        ], 200);
    }

    public function get_way_id_from_nominatim($lat, $lng)
    {
        $url = "https://testmap.141.ir/nominatim/reverse?format=jsonv2&lat=" . $lat . "&lon=" . $lng . "&zoom=16&addressdetails=16";
        $arrContextOptions = array(
            "ssl" => array(
                "verify_peer" => false,
                "verify_peer_name" => false,
            ),
        );

        $result = file_get_contents($url, false, stream_context_create($arrContextOptions));
        $result = json_decode($result);
        if (isset($result->osm_type)) {
            if ($result->osm_type == 'way') {
                return $result->osm_id;
            }
        }
        return 0;
    }

    public function getAccidents(Request $request)
    {
        $request->validate([
            'province_ids' => 'regex:/^(\d+)(,\d+)*$/',
            'axis_types' => 'regex:/^(\d+)(,\d+)*$/',
            'way_geometries' => 'regex:/^(\d+)(,\d+)*$/',
            'collision_types' => 'regex:/^(\d+)(,\d+)*$/',
            // 'from_date' => 'date:Y-m-d',
            // 'to_date' => 'date:Y-m-d',
            'accident_types' => 'regex:/^(\d+)(,\d+)*$/',
            'days_of_the_week' => 'string',
            'day_part' => 'in:day,night',
        ]);

        // dd($request->province_ids);

        $from_date = $request->from_date;
        $to_date = $request->to_date;

        $data = DailyAccident::select('lat', 'lng', 'id')
            ->when($request->province_ids, function ($query, $province_ids) {
                $query->whereIn('province_id', explode(",", $province_ids));
            })
            ->when($request->collision_types, function ($query, $collision_types) {
                $query->whereIn('collision_type', explode(",", $collision_types));
            })
            ->when($request->axis_types, function ($query, $axis_types) {
                $query->whereIn('axis_type', explode(",", $axis_types));
            })
            ->when($request->way_geometries, function ($query, $way_geometries) {
                $query->whereIn('way_geometri', explode(",", $way_geometries));
            })
            ->when(($from_date && $to_date), function ($query) use ($from_date, $to_date) {
                foreach ($from_date as $key => $value) {
                    $query->orWhereBetween('accident_date', [$value . ' 00:00:00', $to_date[$key] . ' 23:59:59']);
                }
            })
            ->when($request->accident_types, function ($query, $accident_types) {
                $query->whereIn('accident_type', explode(",", $accident_types));
            })
            ->when($request->days_of_the_week, function ($query, $days_of_the_week) {
                $query->whereIn('day_of_the_week', explode(",", $days_of_the_week));
            })
            ->when($request->day_part, function ($query, $day_part) {
                if ($day_part == 'day') {
                    $query->whereBetween('accident_time', ['06:00:00', '18:00:00']);
                } else {
                    $query->whereNotBetween('accident_time', ['06:00:00', '18:00:00']);
                }
            })
            ->get();


        return response()->json([
            'succuss' => true,
            'data' => $data
        ]);
    }

    public function getPendingAccidentsCount(Request $request)
    {
        if (auth()->user()->hasPermissionTo('accident-investigation')) {
            $count = DailyAccident::where('state', 2)
                    ->count();

        } elseif (auth()->user()->hasPermissionTo('provincial-accident-investigation')) {
            $province_id = auth()->user()->province_id;
            $count = DailyAccident::where('state', 2)
                    ->where('province_id', $province_id)
                    ->count();
        } else {
            $count = -1;
        }

        return response()->json([
            'status' => 200,
            'count'   => $count,
        ]);
    }
}
