<?php

namespace App\Http\Controllers\Website;

use App\Http\Controllers\Controller;
use App\Models\CriteriaData;
use App\Models\HeightSubDistrict;
use App\Models\PhSubDistrict;
use App\Models\PreferenceResultPlant;
use App\Models\PreferenceResultSubDistrict;
use App\Models\SubDistrict;
use App\Models\SubDistrictAlternatif;
use App\Models\WeatherSubDistrict;
use Exception;
use Illuminate\Http\Request;

class SubDistrictAlternatifController extends Controller
{
    public function index()
    {
        // mengambil list tahun
        $listResultPreference = SubDistrictAlternatif::all();
        $years = array_unique(array_column($listResultPreference->toArray(), 'year'));
        sort($years);

        $subDistricts = SubDistrict::all();

        $criterias = CriteriaData::all();

        return view('website.app.sub-district-alternatif', compact('subDistricts', 'criterias', 'years'));
    }

    public function addAlternatifSubDistrict(Request $request)
    {
        $criterias = CriteriaData::all();

        $subDistrictId = $request->input('subDistrictId');
        $month = $request->input('month');
        $year = $request->input('year');

        // mengecek apakah sudah tersedia atau belum
        $subDistrictAlternatifs = SubDistrictAlternatif::where('sub_district_id', $subDistrictId)
            ->where('month', $month)
            ->where('year', $year)
            ->get();

        if (count($subDistrictAlternatifs) == 0) {
            foreach ($criterias as $key => $value) {
                SubDistrictAlternatif::create([
                    'sub_district_id' => $subDistrictId,
                    'month' => $month,
                    'year' => $year,
                    'criteria_id' => $value->id,
                    'value_alternatif' => $request->input(str_replace(' ', '_', $value->criteria)),
                ]);
            }

            toast('Data alternatif kecamatan berhasil ditambahkan!', 'success');
            return redirect()->back();
        } else {
            toast('Gagal, Data alternatif kecamatan bulan ' . $month . ' tahun ' . $year . ' sudah tersedia!', 'error');
            return redirect()->back();
        }
    }

    public function updateAlternatifSubDistrict($month, $year)
    {
        $subDistrictAll = SubDistrict::all();
        try {
            foreach ($subDistrictAll as $subDistrict) {
                $weatherSubDistrict = WeatherSubDistrict::where('sub_district_id', $subDistrict['id'])
                    ->where('year', $year)
                    ->where('month', $month)
                    ->get();
                $heightSubDistrict = HeightSubDistrict::where('sub_district_id', $subDistrict['id'])
                    ->where('year', $year)
                    ->first();
                $phSubDistrict = PhSubDistrict::where('sub_district_id', $subDistrict['id'])
                    ->first();

                if ($weatherSubDistrict->isEmpty()) {
                    toast('Belum Lengkap dan cek kembali, download data cuaca tahunan terlebih dahulu !!', 'error');
                } else if (is_null($heightSubDistrict)) {
                    toast('Belum Lengkap dan cek kembali, download data ketinggian tahunan terlebih dahulu !!', 'error');
                } else if (is_null($phSubDistrict)) {
                    toast('Belum Lengkap dan cek kembali, download data pH tahunan terlebih dahulu !!', 'error');
                }

                if ($heightSubDistrict['height']) {
                    SubDistrictAlternatif::updateOrCreate(
                        [
                            'sub_district_id' => $subDistrict['id'],
                            'month' => $weatherSubDistrict[0]['month'],
                            'year' => $weatherSubDistrict[0]['year'],
                            'criteria_id' => '1'
                        ],
                        [
                            'value_alternatif' => $heightSubDistrict['height'],
                        ]
                    );
                }

                foreach ($weatherSubDistrict as $weather) {
                    if ($weather["allsky_sfc_sw_dwn"]) {
                        SubDistrictAlternatif::updateOrCreate(
                            [
                                'sub_district_id' => $subDistrict['id'],
                                'month' => $weather['month'],
                                'year' => $weather['year'],
                                'criteria_id' => '2'
                            ],
                            [
                                'value_alternatif' => $weather["allsky_sfc_sw_dwn"],
                            ]
                        );
                    }
                    if ($weather["prectotcorr"]) {
                        SubDistrictAlternatif::updateOrCreate(
                            [
                                'sub_district_id' => $subDistrict['id'],
                                'month' => $weather['month'],
                                'year' => $weather['year'],
                                'criteria_id' => '3'
                            ],
                            [
                                'value_alternatif' => $weather["prectotcorr"],
                            ]
                        );
                    }
                    if ($weather["rh2m"]) {
                        SubDistrictAlternatif::updateOrCreate(
                            [
                                'sub_district_id' => $subDistrict['id'],
                                'month' => $weather['month'],
                                'year' => $weather['year'],
                                'criteria_id' => '4'
                            ],
                            [
                                'value_alternatif' => $weather["rh2m"],
                            ]
                        );
                    }
                    if ($weather["t2m"]) {
                        SubDistrictAlternatif::updateOrCreate(
                            [
                                'sub_district_id' => $subDistrict['id'],
                                'month' => $weather['month'],
                                'year' => $weather['year'],
                                'criteria_id' => '5'
                            ],
                            [
                                'value_alternatif' => $weather["t2m"],
                            ]
                        );
                    }
                    if ($weather["ws2m"]) {
                        SubDistrictAlternatif::updateOrCreate(
                            [
                                'sub_district_id' => $subDistrict['id'],
                                'month' => $weather['month'],
                                'year' => $weather['year'],
                                'criteria_id' => '6'
                            ],
                            [
                                'value_alternatif' => $weather["ws2m"],
                            ]
                        );
                    }
                }

                if ($phSubDistrict['meter_0_5']) {
                    SubDistrictAlternatif::updateOrCreate(
                        [
                            'sub_district_id' => $subDistrict['id'],
                            'month' => $weatherSubDistrict[0]['month'],
                            'year' => $weatherSubDistrict[0]['year'],
                            'criteria_id' => '7'
                        ],
                        [
                            'value_alternatif' => $phSubDistrict['meter_0_5'],
                        ]
                    );
                } else if ($phSubDistrict['meter_0_5'] == 0) {
                    SubDistrictAlternatif::updateOrCreate(
                        [
                            'sub_district_id' => $subDistrict['id'],
                            'month' => $weatherSubDistrict[0]['month'],
                            'year' => $weatherSubDistrict[0]['year'],
                            'criteria_id' => '7'
                        ],
                        [
                            'value_alternatif' => '5.5',
                        ]
                    );
                }
            }
            return response()->json(['success' => true, 'message' => `Data alternatif kecamatan $month,$year berhasil diperbarui!`]);
        } catch (\Exception $e) {
            // Tangani kesalahan dan tampilkan pesan error
            return response()->json([
                'success' => false,
                'message' => $e->getMessage()
            ], 500);
        }
    }

    public function deleteAlternatifSubDistrict($id, $month, $year)
    {
        // hapus referensi alternatif
        $subDistrictAlternatif = SubDistrictAlternatif::where('sub_district_id', '=', $id)->where('month', $month)->where('year', $year)->get();
        foreach ($subDistrictAlternatif as $value) {
            $value->delete();
        }

        // // hapus pada relasi preference result sub district
        $preferenceResultSubDistrict = PreferenceResultSubDistrict::where('sub_district_id', '=', $id)->where('month', $month)->where('year', $year)->get();
        foreach ($preferenceResultSubDistrict as $value) {
            $value->delete();
        }
        toast('Data alternatif kecamatan berhasil dihapus', 'success');
        return redirect()->back();
    }

    public function updateAlternatifBySubDistrict(Request $request)
    {
        $criterias = CriteriaData::all();

        $subDistrictId = $request->input('subDistrictId');
        $month = $request->input('month');
        $year = $request->input('year');

        foreach ($criterias as $key => $value) {
            SubDistrictAlternatif::updateOrCreate(
                [
                    'sub_district_id' => $subDistrictId,
                    'criteria_id' => $value->id,
                    'month' => $month,
                    'year' => $year,
                ],
                [
                    'value_alternatif' => $request->input(str_replace(' ', '_', $value->criteria))
                ]
            );
        }

        toast('Data alternatif kecamatan berhasil diubah!', 'success');
        return redirect()->back();
    }

    public function getAlternatifSubDistrict($month, $year)
    {
        $listAlternatifSubDistrict = SubDistrictAlternatif::select(
            'sub_district_alternatifs.id as sub_district_alternatifs_id',
            'sub_district_alternatifs.sub_district_id as sda_sub_district_id',
            'sub_district_alternatifs.criteria_id as sda_criteria_id',
            'sub_district_alternatifs.value_alternatif',
            'sub_district_alternatifs.month',
            'sub_district_alternatifs.year',
            'sub_district.id as sub_district_id',
            'sub_district.sub_district',
            'criteria_data.id as criteria_data_id',
            'criteria_data.criteria',
            'criteria_data.bobot',
            'criteria_data.status'
        )
            ->join('sub_district', 'sub_district.id', '=', 'sub_district_alternatifs.sub_district_id')
            ->join('criteria_data', 'criteria_data.id',  '=', 'sub_district_alternatifs.criteria_id')
            ->where('sub_district_alternatifs.month', '=', $month)
            ->where('sub_district_alternatifs.year', '=', $year)
            ->get();

        $listCriteria = CriteriaData::all();

        if (count($listAlternatifSubDistrict) != 0) {
            // data alternatif kecamatan
            $groupBySubDistrict = $listAlternatifSubDistrict->groupBy('sda_sub_district_id')->map(function ($subDistrictData) {
                $subDistrict = $subDistrictData->first();

                return [
                    'sub_district_id' => $subDistrict->sub_district_id,
                    'sub_district' => $subDistrict->sub_district,
                    'month' => $subDistrict->month,
                    'year' => $subDistrict->year,
                    'criteria' => $subDistrictData->map(function ($item) {
                        return [
                            'criteria_id' => $item->criteria_data_id,
                            'criteria' => $item->criteria,
                            'value_alternatif' => $item->value_alternatif,
                            'status' => $item->status,
                            'bobot' => $item->bobot
                        ];
                    })->toArray()
                ];
            });

            // mengecek apakah jumlah pada setiap criteria sama
            $firstGroupBySubDistrict = count($groupBySubDistrict[1]['criteria']);
            $checkGroupBySubDistrict = true;
            foreach ($groupBySubDistrict as $subDistrict) {
                if (count($subDistrict['criteria']) !== $firstGroupBySubDistrict) {
                    $checkGroupBySubDistrict = false;
                    break;
                }
            }

            // jika jumlah pada setiap criteria berbeda
            if ($checkGroupBySubDistrict == false) {
                return response()->json([
                    'listCriterias' => $listCriteria,
                    'groupBySubDistrict' => $groupBySubDistrict,
                    'message' => 'fail'
                ]);
            } else {

                // pembagi matriks ternomalisasi
                $countCriteria = count($groupBySubDistrict[1]['criteria']);
                $pembagiMatriksTernomalisasi = [];
                for ($i = 0; $i < $countCriteria; $i++) {
                    $sumKuadrat = 0;

                    foreach ($groupBySubDistrict as $item) {
                        $sumKuadrat += pow($item["criteria"][$i]["value_alternatif"], 2);
                    }

                    // Hitung akar dari jumlah kuadrat
                    $pembagiMatriksTernomalisasi[$i] = round((sqrt($sumKuadrat)), 5);
                }

                // data matriks ternomalisasi kecamatan
                $matriksTernomalisasiSubDistrict = [];
                foreach ($groupBySubDistrict as $item) {
                    $valueBaru = [];
                    foreach ($item['criteria'] as $index => $value) {
                        $value['value_alternatif'] = round(($value['value_alternatif'] / $pembagiMatriksTernomalisasi[$index]), 5);
                        $valueBaru[] = [
                            'criteria_id' => $value['criteria_id'],
                            'criteria' => $value['criteria'],
                            'value_alternatif' => $value['value_alternatif'],
                            'status' => $value['status'],
                            'bobot' => $value['bobot']
                        ];
                    }
                    $matriksTernomalisasiSubDistrict[] = [
                        'sub_district_id' => $item['sub_district_id'],
                        'sub_district' => $item['sub_district'],
                        'criteria' => $valueBaru
                    ];
                }

                // data matriks ternomalisasi terbobot kecamatan
                $ternomalisasiTerbobotSubDistrict = [];
                foreach ($groupBySubDistrict as $item) {
                    $valueBaru = [];
                    foreach ($item['criteria'] as $index => $value) {
                        $value['value_alternatif'] = round(($value['value_alternatif'] / $pembagiMatriksTernomalisasi[$index]), 5);
                        $valueBaru[] = [
                            'criteria_id' => $value['criteria_id'],
                            'criteria' => $value['criteria'],
                            'value_alternatif' => round(($value['value_alternatif'] * $value['bobot']), 5),
                            'status' => $value['status'],
                            'bobot' => $value['bobot']
                        ];
                    }
                    $ternomalisasiTerbobotSubDistrict[] = [
                        'sub_district_id' => $item['sub_district_id'],
                        'sub_district' => $item['sub_district'],
                        'criteria' => $valueBaru
                    ];
                }

                // data solusi ideal positif dan negatif
                // 1. pengumpulan hasil data terbobot berdasarkan criteria
                $criteria_values = [];
                foreach ($ternomalisasiTerbobotSubDistrict as $ternomalisasi) {
                    foreach ($ternomalisasi['criteria'] as $index => $criteria) {
                        $criteria_values[$index]['criteria_id'] = $criteria['criteria_id'];
                        $criteria_values[$index]['criteria'] = $criteria['criteria'];
                        $criteria_values[$index]['status'] = $criteria['status'];
                        $criteria_values[$index]['values'][] = $criteria['value_alternatif'];
                    }
                }

                // 2. menentukan ideal positif dan ideal negatif
                $ideal_positif = [];
                $ideal_negatif = [];

                foreach ($criteria_values as $index => $criteria) {
                    if ($criteria['status'] === "benefit") {
                        $ideal_positif[$index] = max($criteria['values']);
                        $ideal_negatif[$index] = min($criteria['values']);
                    } else {
                        $ideal_positif[$index] = min($criteria['values']);
                        $ideal_negatif[$index] = max($criteria['values']);
                    }
                }

                // solusi ideal terbobot kecamatan
                $determinanSubDistrict = [];
                foreach ($ternomalisasiTerbobotSubDistrict as $ternomalisasi) {
                    $jumlahDeterminanPositif = 0;
                    $jumlahDeterminanNegatif = 0;
                    foreach ($ternomalisasi['criteria'] as $index => $criteria) {
                        $jumlahDeterminanPositif += pow(($criteria['value_alternatif'] - $ideal_positif[$index]), 2);
                        $jumlahDeterminanNegatif += pow(($criteria['value_alternatif'] - $ideal_negatif[$index]), 2);
                    }
                    $determinanSubDistrict[] = [
                        'id' => $ternomalisasi['sub_district_id'],
                        'sub_district' => $ternomalisasi['sub_district'],
                        'determinanPositif' => round((sqrt($jumlahDeterminanPositif)), 5),
                        'determinanNegatif' => round((sqrt($jumlahDeterminanNegatif)), 5)
                    ];
                }

                // menyimpan hasil preferensi setiap kecamatan
                if (count($determinanSubDistrict) != 0 && count($determinanSubDistrict) != 1) {
                    foreach ($determinanSubDistrict as $preference) {
                        PreferenceResultSubDistrict::updateOrCreate(
                            [
                                'sub_district_id' => $preference['id'],
                                'month' => $month,
                                'year' => $year,
                            ],
                            [
                                'value_preference' => round($preference['determinanNegatif'] / ($preference['determinanNegatif'] + $preference['determinanPositif']), 5),
                                'plant_name' => ''
                            ]
                        );
                    }
                }

                // ambil hasil preferensi kecamatan di database
                $preferenceResultSubDistrict = PreferenceResultSubDistrict::select(
                    'preference_result_sub_districts.id',
                    'preference_result_sub_districts.sub_district_id as prsd_sub_district_id',
                    'preference_result_sub_districts.value_preference',
                    'preference_result_sub_districts.plant_name',
                    'preference_result_sub_districts.month',
                    'preference_result_sub_districts.year',
                    'sub_district.id as sd_id',
                    'sub_district.sub_district'
                )
                    ->join('sub_district', 'sub_district.id', '=', 'preference_result_sub_districts.sub_district_id')
                    ->where('preference_result_sub_districts.month', '=', $month)
                    ->where('preference_result_sub_districts.year', '=', $year)
                    ->get();

                $preferenceResultPlant = PreferenceResultPlant::select(
                    'preference_result_plants.id',
                    'preference_result_plants.plant_id as prp_plant_id',
                    'preference_result_plants.value_preference',
                    'plants.id as pl_id',
                    'plants.plant'
                )
                    ->join('plants', 'plants.id', '=', 'preference_result_plants.plant_id')
                    ->get();

                $prSubDistrictArray = [];
                $prPlantArray = [];
                $resultPlantBySubDistrict = [];
                if (count($preferenceResultSubDistrict) != 0 && count($preferenceResultPlant) != 0) {
                    foreach ($preferenceResultSubDistrict as $prSubDistrict) {
                        $prSubDistrictArray[$prSubDistrict['sub_district']] = $prSubDistrict['value_preference'];
                    }

                    foreach ($preferenceResultPlant as $prPlant) {
                        $prPlantArray[$prPlant['plant']] = $prPlant['value_preference'];
                    }

                    foreach ($prSubDistrictArray as $subDistrict => $valuePreferenceSubDistrict) {
                        $PlantByChoice = collect($prPlantArray)
                            ->sortBy(fn($valuePreferencePlant) => abs($valuePreferencePlant - $valuePreferenceSubDistrict))
                            ->keys()
                            ->first();

                        $resultPlantBySubDistrict[$subDistrict] = $PlantByChoice;
                    }

                    // menambah atau update data reference kecamatan (tanaman)
                    foreach ($preferenceResultSubDistrict as $prSubDistrict) {
                        PreferenceResultSubDistrict::updateOrCreate(
                            [
                                'sub_district_id' => $prSubDistrict['prsd_sub_district_id'],
                                'month' => $month,
                                'year' => $year,
                            ],
                            [
                                'value_preference' => $prSubDistrict['value_preference'],
                                'plant_name' => $resultPlantBySubDistrict[$prSubDistrict['sub_district']]
                            ]
                        );
                    }
                }

                return response()->json([
                    // 'month' => $month,
                    // 'year' => $year,
                    'listCriterias' => $listCriteria,
                    'groupBySubDistrict' => $groupBySubDistrict,
                    'pembagiMatriksTernomalisasi' => $pembagiMatriksTernomalisasi,
                    'matriksTernomalisasiSubDistrict' => $matriksTernomalisasiSubDistrict,
                    'ternomalisasiTerbobotSubDistrict' => $ternomalisasiTerbobotSubDistrict,
                    'solusiIdealPositif' => $ideal_positif,
                    'solusiIdealNegatif' => $ideal_negatif,
                    'determinanSubDistrict' => $determinanSubDistrict,
                    'resultPlantBySubDistrict' => $resultPlantBySubDistrict,
                ]);
            }
        } else {
            return response()->json([
                'message' => 'Data tidak ditemukan'
            ]);
        }
    }
}
