<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;

class AdminController extends Controller
{
    public function dashboard()
    {
        // Ambil data total peminjaman berdasarkan jangka waktu
        $data_peminjaman = DB::table('nasabah')
            ->selectRaw('jangka_waktu, SUM(jumlah_pinjaman) as total_pinjaman')
            ->groupBy('jangka_waktu')
            ->orderBy('jangka_waktu')
            ->get();

        // Format data untuk Chart.js
        $jangka_waktu = $data_peminjaman->pluck('jangka_waktu');
        $total_pinjaman = $data_peminjaman->pluck('total_pinjaman');

        // Ambil total nasabah
        $total_nasabah = DB::table('nasabah')->count();

        // Ambil data dari tabel nasabah
        $nasabah = DB::table('nasabah')
            ->select(
                'id_nasabah',
                'nama',
                'jumlah_pinjaman',
                'jangka_waktu',
                'jumlah_setoran',
                'history_pinjaman',
                DB::raw('jumlah_pinjaman / jangka_waktu AS setoran_per_bulan'),
                DB::raw('(jumlah_pinjaman * 0.1) AS bunga'),
                DB::raw('(jumlah_pinjaman / jangka_waktu) + (jumlah_pinjaman * 0.1) AS setoran_dan_bunga'),
                DB::raw('jumlah_pinjaman - jumlah_setoran AS sisa_pinjaman')
            )
            ->get();

        // Konversi data ke array untuk clustering
        $data = [];
        foreach ($nasabah as $n) {
            $data[] = [
                $n->history_pinjaman,
                $n->setoran_per_bulan,
                $n->bunga,
                $n->setoran_dan_bunga,
                $n->sisa_pinjaman
            ];
        }

        // Lakukan perhitungan K-Means Clustering (3 cluster)
        $result = $this->kmeans($data, 2);

        // Hitung jumlah nasabah layak dan tidak layak berdasarkan cluster
        $layak = 0;
        $tidak_layak = 0;
        foreach ($result['clusters'] as $cluster) {
            if ($cluster == 1) {
                $layak++;
            } else {
                $tidak_layak++;
            }
        }


        return view('admin.dashboard', compact('jangka_waktu', 'total_pinjaman', 'total_nasabah', 'layak', 'tidak_layak'));
    }


    public function nasabahdaftar()
    {
        $nasabah = DB::table('nasabah')->get();
        return view('admin.nasabahdaftar', compact('nasabah'));
    }

    public function nasabahtambah()
    {
        return view('admin.nasabahtambah');
    }

    public function nasabahsimpan(Request $request)
    {
        $request->validate([
            'nama' => 'required|string|max:255',
            'golongan_pekerjaan' => 'required|string|max:255',
            'status_pekerjaan' => 'required|string|max:255',
            'jumlah_pinjaman' => 'required|numeric',
            'alamat' => 'required|string',
            'history_pinjaman' => 'required|string',
            'tabungan_simpanan_wajib' => 'required|numeric',
            'slip_gaji' => 'nullable|file|mimes:pdf,jpg,png|max:2048', // Maks 2MB
        ]);

        $filePath = null;
        if ($request->hasFile('slip_gaji')) {
            $file = $request->file('slip_gaji');
            $fileName = time() . '_' . $file->getClientOriginalName();
            $filePath = 'uploads/' . $fileName;
            $file->move(public_path('uploads'), $fileName);
        }

        DB::table('nasabah')->insert([
            'nama' => $request->nama,
            'golongan_pekerjaan' => $request->golongan_pekerjaan,
            'status_pekerjaan' => $request->status_pekerjaan,
            'jumlah_pinjaman' => $request->jumlah_pinjaman,
            'alamat' => $request->alamat,
            'history_pinjaman' => $request->history_pinjaman,
            'tabungan_simpanan_wajib' => $request->tabungan_simpanan_wajib,
            'slip_gaji' => $filePath,
            'setoran_per_bulan' => $request->setoran_per_bulan,
            'bunga' => $request->bunga,
            'setoran_dan_bunga' => $request->setoran_dan_bunga,
            'sisa_pinjaman' => $request->sisa_pinjaman,
            'jumlah_setoran' => $request->jumlah_setoran,
            'jangka_waktu' => $request->jangka_waktu,
            'created_at' => date('Y-m-d H:i:s'),
        ]);

        return redirect()->route('nasabah.daftar')->with('success', 'Data nasabah berhasil disimpan.');
    }

    public function nasabahedit($id)
    {
        $nasabah = DB::table('nasabah')->where('id_nasabah', $id)->first();
        return view('admin.nasabahedit', compact('nasabah'));
    }

    public function nasabahupdate(Request $request, $id)
    {
        $request->validate([
            'nama' => 'required|string|max:255',
            'golongan_pekerjaan' => 'required|string|max:255',
            'status_pekerjaan' => 'required|string|max:255',
            'jumlah_pinjaman' => 'required|numeric',
            'alamat' => 'required|string',
            'history_pinjaman' => 'required|string',
            'tabungan_simpanan_wajib' => 'required|numeric',
            'slip_gaji' => 'nullable|file|mimes:pdf,jpg,png|max:2048',
        ]);

        $filePath = $request->slip_gaji_lama;
        if ($request->hasFile('slip_gaji')) {
            $file = $request->file('slip_gaji');
            $fileName = time() . '_' . $file->getClientOriginalName();
            $filePath = 'uploads/' . $fileName;
            $file->move(public_path('uploads'), $fileName);
        }

        DB::table('nasabah')->where('id_nasabah', $id)->update([
            'nama' => $request->nama,
            'golongan_pekerjaan' => $request->golongan_pekerjaan,
            'status_pekerjaan' => $request->status_pekerjaan,
            'jumlah_pinjaman' => $request->jumlah_pinjaman,
            'alamat' => $request->alamat,
            'history_pinjaman' => $request->history_pinjaman,
            'tabungan_simpanan_wajib' => $request->tabungan_simpanan_wajib,
            'slip_gaji' => $filePath,
            'setoran_per_bulan' => $request->setoran_per_bulan,
            'bunga' => $request->bunga,
            'setoran_dan_bunga' => $request->setoran_dan_bunga,
            'sisa_pinjaman' => $request->sisa_pinjaman,
            'jumlah_setoran' => $request->jumlah_setoran,
            'jangka_waktu' => $request->jangka_waktu,
            'updated_at' => date('Y-m-d H:i:s'),

        ]);


        return redirect()->route('nasabah.daftar')->with('success', 'Data nasabah berhasil diperbarui.');
    }

    public function nasabahhapus($id)
    {
        DB::table('nasabah')->where('id_nasabah', $id)->delete();
        return redirect()->route('nasabah.daftar')->with('success', 'Data nasabah berhasil dihapus.');
    }

    public function datanilai()
    {
        // Ambil data dari tabel nasabah
        $nasabah = DB::table('nasabah')
            ->select(
                'id_nasabah',
                'nama',
                'jumlah_pinjaman',
                'jangka_waktu',
                'jumlah_setoran',
                'history_pinjaman',
                'setoran_per_bulan',
                'bunga',
                'setoran_dan_bunga',
                'sisa_pinjaman'
            )
            ->orderBy('id_nasabah', 'asc')
            ->get();

        // Jika tidak ada data, return tanpa clustering
        if ($nasabah->isEmpty()) {
            return view('admin.datanilai', [
                'nasabah' => $nasabah,
                'iterations' => [],
                'initial_centroids' => []
            ]);
        }

        // Konversi data ke array untuk K-Means
        $data = [];
        foreach ($nasabah as $n) {
            $data[] = [
                $n->history_pinjaman,
                $n->setoran_per_bulan,
                $n->bunga,
                $n->setoran_dan_bunga,
                $n->sisa_pinjaman
            ];
        }

        // Normalisasi data agar lebih akurat
        $normalizedData = $this->normalize($data);

        // Lakukan clustering dengan 2 cluster
        $result = $this->kmeans($normalizedData, 2);

        // Gabungkan hasil cluster ke data nasabah
        foreach ($nasabah as $index => $n) {
            $n->cluster = $result['clusters'][$index];
            $n->kelayakan = ($n->cluster == 1) ? 'Layak' : 'Tidak Layak';
        }

        return view('admin.datanilai', [
            'nasabah' => $nasabah,
            'iterations' => $result['iterations'],
            'initial_centroids' => $result['initial_centroids']
        ]);
    }

    /**
     * Fungsi untuk normalisasi data menggunakan Min-Max Scaling.
     */
    private function normalize($data)
    {
        $normalizedData = [];
        foreach ($data[0] as $key => $value) {
            $column = array_column($data, $key);
            $min = min($column);
            $max = max($column);

            foreach ($data as $i => $row) {
                $normalizedData[$i][$key] = ($max - $min == 0) ? 0 : ($row[$key] - $min) / ($max - $min);
            }
        }
        return $normalizedData;
    }

    /**
     * Fungsi K-Means Clustering
     */
    private function kmeans($data, $k, $maxIterations = 3)
    {
        $n = count($data);
        $dim = count($data[0]);

        // Inisialisasi centroid menggunakan K-Means++
        $centroids = [$data[array_rand($data)]];
        while (count($centroids) < $k) {
            $distances = [];
            foreach ($data as $point) {
                $minDist = INF;
                foreach ($centroids as $centroid) {
                    $dist = $this->euclideanDistance($point, $centroid);
                    $minDist = min($minDist, $dist);
                }
                $distances[] = $minDist;
            }
            $index = $this->weightedRandomSelection($distances);
            $centroids[] = $data[$index];
        }

        $clusters = [];
        $iterations = [];

        for ($iter = 0; $iter < $maxIterations; $iter++) {
            $clusters = array_fill(0, $n, 0);
            $distances = [];

            // Assign cluster ke data
            foreach ($data as $i => $point) {
                $minDist = INF;
                $bestCluster = 0;
                $distToCentroids = [];

                foreach ($centroids as $c => $centroid) {
                    $dist = $this->euclideanDistance($point, $centroid);
                    $distToCentroids[] = $dist;
                    if ($dist < $minDist) {
                        $minDist = $dist;
                        $bestCluster = $c;
                    }
                }

                $clusters[$i] = $bestCluster;
                $distances[$i] = $distToCentroids;
            }

            // Simpan iterasi untuk analisis
            $iterations[] = [
                'iteration' => $iter + 1, // Iterasi dimulai dari 1
                'distances' => $distances,
                'clusters' => $clusters,
                'centroids' => $centroids
            ];

            // Hitung centroid baru
            $newCentroids = array_fill(0, $k, array_fill(0, $dim, 0));
            $counts = array_fill(0, $k, 0);

            foreach ($data as $i => $point) {
                $cluster = $clusters[$i];
                foreach ($point as $dimIndex => $value) {
                    $newCentroids[$cluster][$dimIndex] += $value;
                }
                $counts[$cluster]++;
            }

            foreach ($newCentroids as $c => &$centroid) {
                if ($counts[$c] > 0) {
                    foreach ($centroid as $dimIndex => &$value) {
                        $value /= $counts[$c];
                    }
                } else {
                    $centroid = $data[array_rand($data)]; // Jika cluster kosong, pilih titik acak
                }
            }

            // Jika centroid tidak berubah, berhenti iterasi
            if ($newCentroids === $centroids) break;
            $centroids = $newCentroids;
        }

        return [
            'clusters' => $clusters,
            'iterations' => $iterations,
            'initial_centroids' => $centroids
        ];
    }


    /**
     * Fungsi untuk menghitung jarak Euclidean
     */
    private function euclideanDistance($point1, $point2)
    {
        $sum = 0;
        foreach ($point1 as $i => $value) {
            $sum += pow($value - $point2[$i], 2);
        }
        return sqrt($sum);
    }

    /**
     * Fungsi untuk memilih titik secara acak berdasarkan bobot (K-Means++)
     */
    private function weightedRandomSelection($distances)
    {
        $total = array_sum($distances);
        $rand = mt_rand() / mt_getrandmax() * $total;
        $sum = 0;
        foreach ($distances as $index => $distance) {
            $sum += $distance;
            if ($sum >= $rand) {
                return $index;
            }
        }
        return array_key_last($distances);
    }


    // public function datanilai()
    // {
    //     // Ambil data dari tabel nasabah
    //     $nasabah = DB::table('nasabah')
    //         ->select(
    //             'id_nasabah',
    //             'nama',
    //             'jumlah_pinjaman',
    //             'jangka_waktu',
    //             'jumlah_setoran',
    //             'history_pinjaman',
    //             'setoran_per_bulan',
    //             'bunga',
    //             'setoran_dan_bunga',
    //             'sisa_pinjaman'
    //         )
    //         ->orderBy('id_nasabah', 'asc')
    //         ->get();

    //     // Jika tidak ada data, return tanpa clustering
    //     if ($nasabah->isEmpty()) {
    //         return view('admin.datanilai', [
    //             'nasabah' => $nasabah,
    //             'iterations' => [],
    //             'initial_centroids' => []
    //         ]);
    //     }

    //     // Konversi data ke array untuk K-Means
    //     $data = [];
    //     foreach ($nasabah as $n) {
    //         $data[] = [
    //             $n->history_pinjaman,
    //             $n->setoran_per_bulan,
    //             $n->bunga,
    //             $n->setoran_dan_bunga,
    //             $n->sisa_pinjaman
    //         ];
    //     }

    //     // Lakukan clustering
    //     $result = $this->kmeans($data, 2);

    //     // Gabungkan hasil cluster ke data nasabah
    //     foreach ($nasabah as $index => $n) {
    //         $n->cluster = $result['clusters'][$index];
    //         $n->kelayakan = ($n->cluster == 1) ? 'Layak' : 'Tidak Layak';
    //     }

    //     return view('admin.datanilai', [
    //         'nasabah' => $nasabah,
    //         'iterations' => $result['iterations'],
    //         'initial_centroids' => $result['initial_centroids']
    //     ]);
    // }

    // private function kmeans($data, $k)
    // {
    //     $maxIterations = 100;

    //     // Inisialisasi centroid dengan K-Means++
    //     $centroids = $this->initializeCentroids($data, $k);
    //     $clusters = array_fill(0, count($data), 0);
    //     $iterations = [];
    //     $initial_centroids = $centroids; // Simpan centroid awal untuk debugging

    //     for ($iteration = 0; $iteration < $maxIterations; $iteration++) {
    //         $newClusters = [];
    //         $distances = [];

    //         // 1. Hitung jarak setiap data ke centroid, lalu tentukan cluster terdekat
    //         foreach ($data as $i => $point) {
    //             $distances[$i] = [];
    //             foreach ($centroids as $j => $centroid) {
    //                 $distances[$i][$j] = $this->euclideanDistance($point, $centroid);
    //             }
    //             $newClusters[$i] = array_search(min($distances[$i]), $distances[$i]);
    //         }

    //         // Jika cluster tidak berubah, berhenti iterasi
    //         if ($newClusters === $clusters) {
    //             break;
    //         }
    //         $clusters = $newClusters;

    //         // 2. Update centroid berdasarkan rata-rata anggota cluster
    //         $sums = array_fill(0, $k, array_fill(0, count($data[0]), 0));
    //         $counts = array_fill(0, $k, 0);

    //         foreach ($data as $i => $point) {
    //             $clusterIndex = $clusters[$i];
    //             foreach ($point as $dim => $value) {
    //                 $sums[$clusterIndex][$dim] += $value;
    //             }
    //             $counts[$clusterIndex]++;
    //         }

    //         foreach ($centroids as $j => &$centroid) {
    //             if ($counts[$j] > 0) {
    //                 foreach ($centroid as $dim => &$value) {
    //                     $value = $sums[$j][$dim] / $counts[$j];
    //                 }
    //             } else {
    //                 // Jika cluster kosong, ambil titik acak baru
    //                 $centroid = $data[array_rand($data)];
    //             }
    //         }

    //         // Simpan data untuk setiap iterasi
    //         $iterations[] = [
    //             'iteration' => $iteration + 1,
    //             'distances' => $distances,
    //             'clusters' => $newClusters,
    //             'centroids' => $centroids
    //         ];
    //     }

    //     return [
    //         'clusters' => $clusters,
    //         'iterations' => $iterations,
    //         'initial_centroids' => $initial_centroids
    //     ];
    // }

    // // Fungsi inisialisasi centroid dengan K-Means++
    // private function initializeCentroids($data, $k)
    // {
    //     $centroids = [];
    //     $centroids[] = $data[array_rand($data)]; // Pilih satu titik pertama secara acak

    //     for ($i = 1; $i < $k; $i++) {
    //         $distances = [];

    //         // Hitung jarak data ke centroid terdekat
    //         foreach ($data as $point) {
    //             $minDistance = INF;
    //             foreach ($centroids as $centroid) {
    //                 $distance = $this->euclideanDistance($point, $centroid);
    //                 if ($distance < $minDistance) {
    //                     $minDistance = $distance;
    //                 }
    //             }
    //             $distances[] = $minDistance;
    //         }

    //         // Pilih titik dengan probabilitas berdasarkan jarak
    //         $sumDistances = array_sum($distances);
    //         $randomValue = mt_rand() / mt_getrandmax() * $sumDistances;
    //         $cumulativeDistance = 0;

    //         foreach ($data as $index => $point) {
    //             $cumulativeDistance += $distances[$index];
    //             if ($cumulativeDistance >= $randomValue) {
    //                 $centroids[] = $point;
    //                 break;
    //             }
    //         }
    //     }

    //     return $centroids;
    // }

    // // Fungsi menghitung jarak Euclidean
    // private function euclideanDistance($point1, $point2)
    // {
    //     $sum = 0;
    //     foreach ($point1 as $i => $value) {
    //         $sum += pow($value - $point2[$i], 2);
    //     }
    //     return sqrt($sum);
    // }


    public function laporan()
    {
        // Ambil data dari tabel nasabah
        $nasabah = DB::table('nasabah')
            ->select(
                'id_nasabah',
                'nama',
                'golongan_pekerjaan',
                'status_pekerjaan',
                'jumlah_pinjaman',
                'history_pinjaman',
                'tabungan_simpanan_wajib',
                DB::raw('jumlah_pinjaman / jangka_waktu AS setoran_per_bulan'),
                DB::raw('(jumlah_pinjaman * 0.1) AS bunga'),
                DB::raw('(jumlah_pinjaman / jangka_waktu) + (jumlah_pinjaman * 0.1) AS setoran_dan_bunga'),
                DB::raw('jumlah_pinjaman - jumlah_setoran AS sisa_pinjaman')
            )
            ->get();

        // Konversi data ke array untuk clustering
        $data = [];
        foreach ($nasabah as $n) {
            $data[] = [
                $n->history_pinjaman,
                $n->setoran_per_bulan,
                $n->bunga,
                $n->setoran_dan_bunga,
                $n->sisa_pinjaman
            ];
        }

        // Lakukan perhitungan K-Means Clustering (3 cluster)
        $result = $this->kmeans($data, 2);

        // Gabungkan hasil cluster ke data nasabah
        foreach ($nasabah as $index => $n) {
            $n->cluster = $result['clusters'][$index];
            $n->kelayakan = ($n->cluster == 1) ? 'Layak' : 'Tidak Layak';  // Modify based on your classification logic
        }

        // Return ke view dengan data dan cluster
        return view('admin.laporan', compact('nasabah'));
    }


    public function laporancetak()
    {
        // Ambil data dari tabel nasabah
        $nasabah = DB::table('nasabah')
            ->select(
                'id_nasabah',
                'nama',
                'golongan_pekerjaan',
                'status_pekerjaan',
                'jumlah_pinjaman',
                'history_pinjaman',
                'tabungan_simpanan_wajib',
                DB::raw('jumlah_pinjaman / jangka_waktu AS setoran_per_bulan'),
                DB::raw('(jumlah_pinjaman * 0.1) AS bunga'),
                DB::raw('(jumlah_pinjaman / jangka_waktu) + (jumlah_pinjaman * 0.1) AS setoran_dan_bunga'),
                DB::raw('jumlah_pinjaman - jumlah_setoran AS sisa_pinjaman')
            )
            ->get();

        // Konversi data ke array untuk clustering
        $data = [];
        foreach ($nasabah as $n) {
            $data[] = [
                $n->history_pinjaman,
                $n->setoran_per_bulan,
                $n->bunga,
                $n->setoran_dan_bunga,
                $n->sisa_pinjaman
            ];
        }

        // Lakukan perhitungan K-Means Clustering (3 cluster)
        $result = $this->kmeans($data, 3);

        // Gabungkan hasil cluster ke data nasabah
        foreach ($nasabah as $index => $n) {
            $n->cluster = $result['clusters'][$index];
            $n->kelayakan = ($n->cluster == 1) ? 'Layak' : 'Tidak Layak';  // Modify based on your classification logic
        }

        // Return ke view dengan data untuk cetak
        return view('admin.laporancetak', compact('nasabah'));
    }

    public function pengaturan()
    {
        return view('admin.pengaturan', ['user' => Auth::user()]);
    }

    public function pengaturansimpan(Request $request)
    {
        $user = Auth::user();

        // Validasi input
        $request->validate([
            'username' => 'required|string|max:255',
            'email' => 'required|email|unique:users,email,' . $user->id,
            'password' => 'nullable|min:6|confirmed',
            'foto' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
        ]);

        // Update foto jika ada upload
        if ($request->hasFile('foto')) {


            // Simpan foto baru
            $fotoName = time() . '.' . $request->foto->extension();
            $request->foto->move(public_path('foto'), $fotoName);
            $user->foto = $fotoName;
        }

        // Update data user
        $user->username = $request->username;
        $user->email = $request->email;

        // Update password jika diisi
        if ($request->password) {
            $user->password = Hash::make($request->password);
        }

        $user->save();

        return redirect()->to('admin/pengaturan')->with('success', 'Profil berhasil diperbarui.');
    }
}
