<?php

namespace App\Http\Controllers\Website;

use App\Http\Controllers\Controller;
use App\Models\CriteriaData;
use App\Models\HeightVillage;
use App\Models\PhVillage;
use App\Models\PreferenceResultPlant;
use App\Models\PreferenceResultVillage;
use App\Models\SubDistrict;
use App\Models\Village;
use App\Models\VillageAlternatif;
use App\Models\WeatherVillage;
use Illuminate\Http\Request;

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

        $listSubDistrict = SubDistrict::all();

        $criterias = CriteriaData::all();

        return view('website.app.village-alternatif', compact('listSubDistrict', 'criterias', 'years'));
    }

    public function getVillage($id)
    {
        $village = Village::where('sub_district_id', $id)->get();
        return response()->json([
            'village' => $village
        ]);
    }

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

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

        // mengecek apakah sudah tersedia atau belum
        $villageAlternatifs = VillageAlternatif::where('village_id', $villageId)
            ->where('month', $month)
            ->where('year', $year)
            ->get();

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

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

    public function updateAlternatifVillage($month, $years, $subDistrictId)
    {
        $villageBySubDistrictId = Village::select('id', 'sub_district_id', 'village', 'latitude', 'longitude')
            ->where('sub_district_id', $subDistrictId)->get();

        try {
            foreach ($villageBySubDistrictId as $village) {
                $weatherVillage = WeatherVillage::where('village_id', $village['id'])
                    ->where('month', $month)
                    ->where('year', $years)
                    ->get();
                $heightVillage = HeightVillage::where('village_id', $village['id'])
                    ->where('year', $years)
                    ->first();
                $phVillage = PhVillage::where('village_id', $village['id'])
                    ->first();

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

                if ($heightVillage['height']) {
                    VillageAlternatif::updateOrCreate(
                        [
                            'village_id' => $village['id'],
                            'month' => $weatherVillage[0]['month'],
                            'year' => $weatherVillage[0]['year'],
                            'criteria_id' => '1'
                        ],
                        [
                            'value_alternatif' => $heightVillage['height'],
                        ]
                    );
                }

                foreach ($weatherVillage as $key => $weather) {
                    if ($weather["allsky_sfc_sw_dwn"]) {
                        VillageAlternatif::updateOrCreate(
                            [
                                'village_id' => $village['id'],
                                'month' => $weather['month'],
                                'year' => $weather['year'],
                                'criteria_id' => '2'
                            ],
                            [
                                'value_alternatif' => $weather["allsky_sfc_sw_dwn"],
                            ]
                        );
                    }
                    if ($weather["prectotcorr"]) {
                        VillageAlternatif::updateOrCreate(
                            [
                                'village_id' => $village['id'],
                                'month' => $weather['month'],
                                'year' => $weather['year'],
                                'criteria_id' => '3'
                            ],
                            [
                                'value_alternatif' => $weather["prectotcorr"],
                            ]
                        );
                    }
                    if ($weather["rh2m"]) {
                        VillageAlternatif::updateOrCreate(
                            [
                                'village_id' => $village['id'],
                                'month' => $weather['month'],
                                'year' => $weather['year'],
                                'criteria_id' => '4'
                            ],
                            [
                                'value_alternatif' => $weather["rh2m"],
                            ]
                        );
                    }
                    if ($weather["t2m"]) {
                        VillageAlternatif::updateOrCreate(
                            [
                                'village_id' => $village['id'],
                                'month' => $weather['month'],
                                'year' => $weather['year'],
                                'criteria_id' => '5'
                            ],
                            [
                                'value_alternatif' => $weather["t2m"],
                            ]
                        );
                    }
                    if ($weather["ws2m"]) {
                        VillageAlternatif::updateOrCreate(
                            [
                                'village_id' => $village['id'],
                                'month' => $weather['month'],
                                'year' => $weather['year'],
                                'criteria_id' => '6'
                            ],
                            [
                                'value_alternatif' => $weather["ws2m"],
                            ]
                        );
                    }
                }

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

    public function deleteAlternatifVillage($id, $month, $year)
    {
        // hapus referensi alternatif
        $villageAlternatif = VillageAlternatif::where('village_id', '=', $id)->where('month', $month)->where('year', $year)->get();
        foreach ($villageAlternatif as $value) {
            $value->delete();
        }

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

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

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

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

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

    public function getAlternatifVillage($month, $years, $subDistrictId)
    {
        $listAlternatifVillage = VillageAlternatif::select(
            'village_alternatifs.id as village_alternatifs_id',
            'village_alternatifs.village_id as va_village_id',
            'village_alternatifs.criteria_id as va_criteria_id',
            'village_alternatifs.value_alternatif',
            'village_alternatifs.month',
            'village_alternatifs.year',
            'village.id as village_id',
            'village.village',
            'village.sub_district_id',
            'criteria_data.id as criteria_data_id',
            'criteria_data.criteria',
            'criteria_data.bobot',
            'criteria_data.status'
        )
            ->join('village', 'village.id', '=', 'village_alternatifs.village_id')
            ->join('criteria_data', 'criteria_data.id',  '=', 'village_alternatifs.criteria_id')
            ->where('village_alternatifs.month', '=', $month)
            ->where('village_alternatifs.year', '=', $years)
            ->where('village.sub_district_id', '=', $subDistrictId)
            ->get();

        $listCriteria = CriteriaData::all();

        // apakah ada list desa
        $villageBySubDistrictId = Village::where('sub_district_id', $subDistrictId)->get();

        if (count($villageBySubDistrictId) > 0) {
            if (count($listAlternatifVillage) != 0) {
                $groupByVillage = $listAlternatifVillage->groupBy('va_village_id')->map(function ($villageData) {
                    $village = $villageData->first();

                    return [
                        'village_id' => $village->village_id,
                        'village' => $village->village,
                        'month' => $village->month,
                        'year' => $village->year,
                        'criteria' => $villageData->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
                $valueFirstIndex = array_key_first($groupByVillage->toArray());
                $firstGroupByVillage = count($groupByVillage[$valueFirstIndex]['criteria']);
                $checkGroupByVillage = true;
                foreach ($groupByVillage as $village) {
                    if (count($village['criteria']) !== $firstGroupByVillage) {
                        $checkGroupByVillage  = false;
                        break;
                    }
                }

                if ($checkGroupByVillage == false) {
                    return response()->json([
                        'listCriterias' => $listCriteria,
                        'groupByVillage' => $groupByVillage,
                        'message' => 'fail'
                    ]);
                } else {

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

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

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

                    // data matriks ternomalisasi desa
                    $matriksTernomalisasiVillage = [];
                    foreach ($groupByVillage 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']
                            ];
                        }
                        $matriksTernomalisasiVillage[] = [
                            'village_id' => $item['village_id'],
                            'village' => $item['village'],
                            'criteria' => $valueBaru
                        ];
                    }

                    // data matriks ternomalisasi terbobot kecamatan
                    $ternomalisasiTerbobotVillage = [];
                    foreach ($groupByVillage 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']
                            ];
                        }
                        $ternomalisasiTerbobotVillage[] = [
                            'village_id' => $item['village_id'],
                            'village' => $item['village'],
                            'criteria' => $valueBaru
                        ];
                    }

                    // data solusi ideal positif dan negatif
                    // 1. pengumpulan hasil data terbobot berdasarkan criteria
                    $criteria_values = [];
                    foreach ($ternomalisasiTerbobotVillage 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 desa
                    $determinanVillage = [];
                    foreach ($ternomalisasiTerbobotVillage 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);
                        }
                        $determinanVillage[] = [
                            'id' => $ternomalisasi['village_id'],
                            'village' => $ternomalisasi['village'],
                            'determinanPositif' => round((sqrt($jumlahDeterminanPositif)), 5),
                            'determinanNegatif' => round((sqrt($jumlahDeterminanNegatif)), 5)
                        ];
                    }

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

                    // ambil hasil preferensi village di database
                    $preferenceResultVillage = PreferenceResultVillage::select(
                        'preference_result_villages.id',
                        'preference_result_villages.village_id as prv_village_id',
                        'preference_result_villages.value_preference',
                        'preference_result_villages.plant_name',
                        'preference_result_villages.month',
                        'preference_result_villages.year',
                        'village.id as v_id',
                        'village.village'
                    )
                        ->join('village', 'village.id', '=', 'preference_result_villages.village_id')
                        ->where('preference_result_villages.month', '=', $month)
                        ->where('preference_result_villages.year', '=', $years)
                        ->where('village.sub_district_id', '=', $subDistrictId)
                        ->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();

                    $prVillageArray = [];
                    $prPlantArray = [];
                    $resultPlantByVillage = [];
                    if (count($preferenceResultVillage) != 0 && count($preferenceResultPlant) != 0) {
                        foreach ($preferenceResultVillage as $prVillage) {
                            $prVillageArray[$prVillage['village']] = $prVillage['value_preference'];
                        }

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

                        foreach ($prVillageArray as $village => $valuePreferenceVillage) {
                            $PlantByChoice = collect($prPlantArray)
                                ->sortBy(fn($valuePreferencePlant) => abs($valuePreferencePlant - $valuePreferenceVillage))
                                ->keys()
                                ->first();

                            $resultPlantByVillage[$village] = $PlantByChoice;
                        }

                        // menambah atau update data reference kecamatan (tanaman)
                        foreach ($preferenceResultVillage as $prVillage) {
                            PreferenceResultVillage::updateOrCreate(
                                [
                                    'village_id' => $prVillage['prv_village_id'],
                                    'month' => $month,
                                    'year' => $years,
                                ],
                                [
                                    'value_preference' => $prVillage['value_preference'],
                                    'plant_name' => $resultPlantByVillage[$prVillage['village']]
                                ]
                            );
                        }
                    }

                    return response()->json([
                        'listCriterias' => $listCriteria,
                        'groupByVillage' => $groupByVillage,
                        'pembagiMatriksTernomalisasi' => $pembagiMatriksTernomalisasi,
                        'matriksTernomalisasiVillage' => $matriksTernomalisasiVillage,
                        'ternomalisasiTerbobotVillage' => $ternomalisasiTerbobotVillage,
                        'solusiIdealPositif' => $ideal_positif,
                        'solusiIdealNegatif' => $ideal_negatif,
                        'determinanVillage' => $determinanVillage,
                        'resultPlantByVillage' => $resultPlantByVillage
                    ]);
                }
            }
        } else {
            return response()->json([
                'message' => "Data tidak ditemukan"
            ]);
        }
    }
}
