<?php

namespace App\Http\Controllers\tables;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Placement;
use App\Models\Classification;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use App\Models\Siswa;
use App\Models\Sertifikat;
use App\Models\Nilai;
use App\Imports\PlacementImport;
use Maatwebsite\Excel\Facades\Excel;

class PlacementController extends Controller
{
    public function index()
    {
        $placement = Placement::all();
        return view('content.placement.index', compact('placement'));
    }

    public function create()
    {
        return view('content.placement.create');
    }

    public function edit(Request $request, $placementId)
    {
        $placement = Placement::find($placementId);
        return view('content.placement.edit', compact('placement'));
    }

    public function calculate(Request $request)
    {
        $scorePerItem = intval(100 / count($request->data));
        $user = Auth::user();
        $siswa = Siswa::where("user_id", $user->id)->get();

        // Fungsi untuk menghitung jarak Euclidean antara dua vektor
        function euclideanDistance($vector1, $vector2)
        {
            $sum = 0;
            for ($i = 0; $i < count($vector1); $i++) {
                $sum += pow($vector1[$i] - $vector2[$i], 2);
            }
            return sqrt($sum);
        }

        // Fungsi untuk mencari tetangga terdekat
        function findNeighbors($X_train, $y_train, $new_sample, $k)
        {
            $distances = [];
            foreach ($X_train as $index => $sample) {
                $dist = euclideanDistance($sample, $new_sample);
                $distances[] = [$dist, $y_train[$index]];
            }
            usort($distances, function ($a, $b) {
                return $a[0] - $b[0];
            });
            return array_slice($distances, 0, $k);
        }

        // Fungsi untuk memprediksi kelas dari sampel baru
        function predictClass($X_train, $y_train, $new_sample, $k)
        {
            $neighbors = findNeighbors($X_train, $y_train, $new_sample, $k);
            $counts = [];
            foreach ($neighbors as $neighbor) {
                $label = $neighbor[1];
                $counts[$label] = isset($counts[$label]) ? $counts[$label] + 1 : 1;
            }
            arsort($counts);
            $predictedClass = key($counts);
            return $predictedClass;
        }

        // Data training
        // SD -> 1
        // SMP -> 2
        // SMA -> 3
        // [BOBOT TINGKAT, BOBOT NILAI]
        $X_train = [
            [3, 82],
            [1, 86],
            [1, 70],
            [2, 88],
            [1, 94],
            [2, 78],
            [2, 94],
            [1, 76],
            [3, 90],
            [1, 72],
            [1, 88],
            [3, 80]

        ];

        $y_train = ['Beginner', 'Beginner', 'Pre-Kids', 'Intermediate', 'Beginner', 'Beginner', 'Intermediate', 'Pre-Kids', 'Intermediate', 'Pre-Kids', 'Beginner', 'Beginner'];

        $X_test = [];
        $score = 0;
        foreach ($request->data as $data) {
            if ($data["jawaban_benar"] == $data["input_jawaban"]) {
                $score = $score + $scorePerItem;
            }
        }

        switch ($siswa[0]["jenjang"]) {
            case "SD":
            case "MI":
                array_push($X_test, 1);
                break;
            case "SMP":
            case "MTS":
                array_push($X_test, 2);
                break;
            case "SMA":
            case "SMK":
                array_push($X_test, 3);
                break;
            case "Kuliah":
            case "Umum":
                array_push($X_test, 4);
                break;
            default:
                array_push($X_test, 0);
        }

        array_push($X_test, $score);

        // Jumlah tetangga terdekat yang akan digunakan
        $k = 3;

        // Lakukan prediksi kelas untuk data uji
        $predictedClass = predictClass($X_train, $y_train, $X_test, $k);

        // Gate
        if ($X_test <= 1) {
            $predictedClass = "Pre-Kids";
        } else {
            if ($predictedClass == "Pre-Kids") {
                $predictedClass = "Beginner";
            }
        }

        DB::transaction(function () use ($request, $score, $predictedClass) {
            Classification::create([
                "user_id" => json_decode($request->user)->id,
                "nilai" => $score,
                "hasil_kelas" => $predictedClass,
            ]);

            Sertifikat::create([
                "user_id" => json_decode($request->user)->id,
            ]);

            Nilai::create([
                "user_id" => json_decode($request->user)->id,
                "writing" => 0,
                "reading" => 0,
                "listening" => 0,
                "speaking" => 0
            ]);

            $siswa = Siswa::where("user_id", "=", json_decode($request->user)->id)->first();
            $siswa->update([
                "level" => $predictedClass
            ]);
            $siswa->save();
        });

        return $predictedClass;
    }

    public function insert(Request $request)
    {
        if (isset($request->file)) {
            Placement::truncate();
            Excel::import(new PlacementImport, request()->file('file'));
        } else {
            Placement::create([
                "soal" => $request->soal,
                "jawaban" => $request->jawaban,
                "jawaban_benar" => $request->jawaban_benar,
            ]);
        }
        return redirect()->route("placement")->with("success", "Data Berhasil Disimpan!");
    }
    public function update(Request $request, $placementId)
    {
        $placement = Placement::find($placementId);
        $placement->update([
            "soal" => $request->soal,
            "jawaban" => $request->jawaban,
            "jawaban_benar" => $request->jawaban_benar,
        ]);

        return redirect()->route("placement")->with("success", "Data Berhasil Diperbarui!");
    }

    public function destroy(Request $request, $placementId)
    {
        $id = $placementId;
        $placement = Placement::find($id);

        $placement->delete();

        return redirect()->route("placement")->with("success", "Data Berhasil Dihapus!");
    }
}
