<?php

namespace App\Http\Controllers;

use App\Models\Confidence;
use App\Models\EclatCalculation;
use App\Models\EclatResult;
use App\Models\EclatResultDetail;
use App\Models\Itemset1;
use App\Models\Itemset2;
use App\Models\Itemset3;
use App\Models\Proses;
use App\Models\Transaksi;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class AlgoritmaController extends Controller
{
    public function index()
    {
        return view('layouts.pages.algoritma');
    }

    public function filter(Request $request)
    {
        $tanggal_dari = $request->input('tanggal_dari');
        $tanggal_sampai = $request->input('tanggal_sampai');
        $min_support = $request->input('min_support');
        $min_confidance = $request->input('min_confidance');

        $proses = Proses::create([
            'start' => $tanggal_dari,
            'end' => $tanggal_sampai,
            'min_support' => $min_support,
            'min_confidence' => $min_confidance,
        ]);

        $transaksi = Transaksi::whereBetween('tanggal', [$tanggal_dari, $tanggal_sampai])->get();

        $totalTransactions = $transaksi->count();

        $itemsets = $this->generateItemsets($transaksi);
        // Convert transactions to vertical format
        $verticalData = $this->convertToVerticalFormat($transaksi);

        // dd($itemsets);
        list($itemset1, $itemset2, $itemset3) = $this->calculateEclat($proses->id, $transaksi, $itemsets, $min_support, $min_confidance, $totalTransactions);
        return view('layouts.pages.algoritma', compact('totalTransactions', 'verticalData', 'itemset1', 'itemset2', 'itemset3'));
    }

    private function generateItemsets($transaksi)
    {
        $itemsets = [];

        foreach ($transaksi as $trans) {
            $items = array_unique(array_map('trim', explode(',', $trans->obat)));
            foreach ($items as $item) {
                $normalizedItem = strtolower(str_replace(' ', '', $item));
                if (!isset($itemsets[$normalizedItem])) {
                    $itemsets[$normalizedItem] = [];
                }
                $itemsets[$normalizedItem][] = $trans->id;
            }
        }

        return $itemsets;
    }



    private function convertToVerticalFormat($transaksi)
    {
        $verticalData = [];

        foreach ($transaksi as $trans) {
            $items = explode(',', $trans->obat);
            foreach ($items as $item) {
                if (!isset($verticalData[$item])) {
                    $verticalData[$item] = array_fill_keys($transaksi->pluck('id')->toArray(), 0);
                }
                $verticalData[$item][$trans->id] = 1;
            }
        }

        return $verticalData;
    }

    private function calculateEclat($prosesid, $transaksi, $itemsets, $min_support, $min_confidance, $totalTransactions)
    {
        $min_support_count = $min_support / $totalTransactions;
        $itemset1 = [];
        $itemset2 = [];
        $itemset3 = [];
        $confidenceResults2 = [];
        $confidenceResults3 = [];

        // Calculate 1-itemsets
        foreach ($itemsets as $item => $transactions) {
            $support = count($transactions);
            $supportValue = $support / $totalTransactions;
            $itemset1[] = [
                'item' => $item,
                'support' => $supportValue,
                'keterangan' => $supportValue >= $min_support_count ? 'Lolos' : 'Tidak Lolos',
                'proses_id' => $prosesid,
            ];
            $itemset1Model = new Itemset1();
            $itemset1Model->saveItemsets([
                'atribut' => $item,
                'support' => $supportValue,
                'keterangan' => $supportValue >= $min_support_count ? 'Lolos' : 'Tidak Lolos',
                'proses_id' => $prosesid,
            ]);
        }

        $filteredItemset1 = array_filter($itemset1, function ($itemset) {
            return $itemset['keterangan'] == 'Lolos';
        });


        // Calculate 2-itemsets
        foreach ($itemset1 as $item1) {
            if ($item1['keterangan'] == 'Lolos') {
                foreach ($itemset1 as $item2) {
                    if ($item2['keterangan'] == 'Lolos' && $item1['item'] != $item2['item']) {
                        $sortedItems = array_merge(array($item1['item']), array($item2['item']));
                        sort($sortedItems);
                        $itemSetKey = implode(',', $sortedItems);

                        if (!isset($itemset2[$itemSetKey])) {
                            $support = 0;
                            foreach ($transaksi as $trans) {
                                $items = array_map(function ($item) {
                                    return strtolower(str_replace(' ', '', $item));
                                }, explode(',', $trans->obat));
                                if (in_array($item1['item'], $items) && in_array($item2['item'], $items)) {
                                    $support++;
                                }
                            }

                            $supportValue = $support / $totalTransactions;

                            $jumlah = $support;

                            $itemset2[$itemSetKey] = [
                                'item1' => $sortedItems[0],
                                'item2' => $sortedItems[1],
                                'support' => $supportValue,
                                'jumlah' => $jumlah,
                                'keterangan' => $supportValue >= $min_support_count ? 'Lolos' : 'Tidak Lolos'
                            ];
                            $itemset2Model = new Itemset2();
                            $createdItemset2 = $itemset2Model->saveItemsets([
                                'atribut' => "{$itemSetKey}",
                                'support' => $supportValue,
                                'jumlah' => $jumlah,
                                'keterangan' => $supportValue >= $min_support_count ? 'Lolos' : 'Tidak Lolos',
                                'proses_id' => $prosesid
                            ]);

                            if (is_null($createdItemset2->id)) {
                                throw new Exception('Itemset2 ID is null after creation');
                            }

                            // $filteredItemset2 = array_filter($itemset2, function ($itemset) {
                            //     return $itemset['keterangan'] == 'Lolos';
                            // });

                            if ($supportValue >= $min_support_count) {
                                $countA = count($itemsets[$sortedItems[0]]);
                                $countB = count($itemsets[$sortedItems[1]]);

                                $confidenceAB = $support / $countA;
                                $confidenceBA = $support / $countB;

                                $supportA2 = $countA / $totalTransactions;
                                $supportB2 = $countB / $totalTransactions;

                                $liftAB = $supportValue / ($supportA2 * $supportB2);
                                $liftBA = $supportValue / ($supportB2 * $supportA2);

                                $confidenceKeys2 = [];

                                $confidenceResults2[] = [
                                    'item1' => $sortedItems[0],
                                    'item2' => $sortedItems[1],
                                    'support' => $supportValue,
                                    'confidence' => "{$support} / {$countA} = {$confidenceAB}",
                                    'lift' => "{$supportValue} / {$supportA2} * {$supportB2} = {$liftAB}",
                                    'korelasi' => $liftAB > 1 ? 'Korelasi Positif' : 'Korelasi Negatif',
                                    'keterangan' => $confidenceAB > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                                ];

                                $confidenceResults2[] = [
                                    'item1' => $sortedItems[1],
                                    'item2' => $sortedItems[0],
                                    'support' => $supportValue,
                                    'confidence' => "{$support} / {$countB} = {$confidenceBA}",
                                    'lift' => "{$supportValue} / {$supportB2} * {$supportA2} = {$liftBA}",
                                    'korelasi' => $liftBA > 1 ? 'Korelasi Positif' : 'Korelasi Negatif',
                                    'keterangan' => $confidenceBA > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                                ];

                                $confidenceResultsitem2[] = [
                                    'item1' => $sortedItems[1],
                                    'item2' => $sortedItems[0],
                                    'support' => $supportValue,
                                    'confidence' => "{$support} / {$countB} = {$confidenceBA}",
                                    'lift' => "{$supportValue} / {$supportB2} * {$supportA2} = {$liftBA}",
                                    'korelasi' => $liftBA > 1 ? 'Korelasi Positif' : 'Korelasi Negatif',
                                    'keterangan' => $confidenceBA > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                                ];

                                $confidenceResultsitem2[] = [
                                    'item1' => $sortedItems[0],
                                    'item2' => $sortedItems[1],
                                    'support' => $supportValue,
                                    'confidence' => "{$support} / {$countA} = {$confidenceAB}",
                                    'lift' => "{$supportValue} / {$supportA2} * {$supportB2} = {$liftAB}",
                                    'korelasi' => $liftAB > 1 ? 'Korelasi Positif' : 'Korelasi Negatif',
                                    'keterangan' => $confidenceAB > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                                ];

                                // $filteredItemset2 = array_filter($itemset2, function ($itemset) {
                                //     return $itemset['keterangan'] == 'Lolos';
                                // });

                                // dd($itemset2, $filteredItemset2, $confidenceResults2, $filteredItemset2);

                                $uniqueConfidenceResults2 = [];
                                foreach ($confidenceResults2 as $result) {
                                    $key = $result['item1'];
                                    if (!isset($confidenceKeys2[$key])) {
                                        $confidenceKeys2[$key] = true;
                                        $uniqueConfidenceResults2[] = $result;
                                    }
                                }

                                foreach ($uniqueConfidenceResults2 as $confidence2Result) {
                                    $confidence = new Confidence();
                                    $confidence->items = "{$confidence2Result['item1']},{$confidence2Result['item2']}";
                                    $confidence->confidence = $confidence2Result['confidence'];
                                    $confidence->lift_ratio = $confidence2Result['lift'];
                                    $confidence->itemset = '2-item';
                                    $confidence->proses_id = $prosesid;
                                    $confidence->keterangan = $confidence2Result['keterangan'];
                                    $confidence->korelasi = $confidence2Result['korelasi'];
                                    $confidence->save();
                                }

                                $confidenceResults2 = [];
                            }
                        }
                    }
                }
            }
        }

        // Calculate 3-itemsets (using filtered itemset2 for efficiency)
        $filteredItemset2 = array_filter($itemset2, function ($itemset) {
            return $itemset['keterangan'] == 'Lolos';
        });
        $filteredConfidenceItemset2 = array_filter($confidenceResultsitem2, function ($itemset) {
            return $itemset['keterangan'] == 'Lolos';
        });

        foreach ($filteredItemset2 as $itemset2Key => $itemset2Value) {
            $items2 = explode(',', $itemset2Key);
            foreach ($itemset1 as $item1) {
                if ($item1['keterangan'] == 'Lolos' && !in_array($item1['item'], $items2)) {
                    $sortedItems = array_merge($items2, array($item1['item']));
                    sort($sortedItems);
                    $itemSetKey = implode(',', $sortedItems);
                    if (!isset($itemset3[$itemSetKey])) {
                        $support = 0;

                        foreach ($transaksi as $trans) {
                            $items = array_map(function ($item) {
                                return strtolower(str_replace(' ', '', $item));
                            }, explode(',', $trans->obat));
                            if (in_array($sortedItems[0], $items) && in_array($sortedItems[1], $items) && in_array($sortedItems[2], $items)) {
                                $support++;
                            }
                        }

                        $supportValue = $support / $totalTransactions;
                        $jumlah = $support;

                        $itemset3[$itemSetKey] = [
                            'item1' => $sortedItems[0],
                            'item2' => $sortedItems[1],
                            'item3' => $sortedItems[2],
                            'support' => $supportValue,
                            'jumlah' => $jumlah,
                            'keterangan' => $supportValue >= $min_support_count ? 'Lolos' : 'Tidak Lolos',
                        ];
                        $itemset3Model = new Itemset3();
                        $createdItemset3 = $itemset3Model->saveItemsets([
                            'atribut' => "{$itemSetKey}",
                            'support' => $supportValue,
                            'jumlah' => $jumlah,
                            'keterangan' => $supportValue >= $min_support_count ? 'Lolos' : 'Tidak Lolos',
                            'proses_id' => $prosesid
                        ]);

                        if ($supportValue >= $min_support_count) {

                            // Convert Eloquent collection to array
                            $transaksiArray = $transaksi->toArray();

                            // Calculate total counts for confidence
                            $totalAB = $totalBC = $totalAC = 0;

                            foreach ($transaksiArray as $trans) {
                                $items = array_map(function ($item) {
                                    return strtolower(str_replace(' ', '', $item));
                                }, explode(',', $trans['obat']));
                                if (in_array($sortedItems[0], $items) && in_array($sortedItems[1], $items)) {
                                    $totalAB++;
                                }
                                if (in_array($sortedItems[1], $items) && in_array($sortedItems[2], $items)) {
                                    $totalBC++;
                                }
                                if (in_array($sortedItems[0], $items) && in_array($sortedItems[2], $items)) {
                                    $totalAC++;
                                }
                            }

                            // Calculate support for individual pairs
                            $supportAB = $totalAB / $totalTransactions;
                            $supportBC = $totalBC / $totalTransactions;
                            $supportAC = $totalAC / $totalTransactions;

                            // Calculate confidence
                            $confidenceAB_C = ($totalAB != 0) ? $support / $totalAB : 0;
                            $confidenceBC_A = ($totalBC != 0) ? $support / $totalBC : 0;
                            $confidenceAC_B = ($totalAC != 0) ? $support / $totalAC : 0;

                            // Calculate lift
                            $supportA = count(array_filter($transaksiArray, function ($trans) use ($sortedItems) {
                                $items = array_map(function ($item) {
                                    return strtolower(str_replace(' ', '', $item));
                                }, explode(',', $trans['obat']));
                                return in_array($sortedItems[0], $items);
                            })) / $totalTransactions;

                            $supportB = count(array_filter($transaksiArray, function ($trans) use ($sortedItems) {
                                $items = array_map(function ($item) {
                                    return strtolower(str_replace(' ', '', $item));
                                }, explode(',', $trans['obat']));
                                return in_array($sortedItems[1], $items);
                            })) / $totalTransactions;

                            $supportC = count(array_filter($transaksiArray, function ($trans) use ($sortedItems) {
                                $items = array_map(function ($item) {
                                    return strtolower(str_replace(' ', '', $item));
                                }, explode(',', $trans['obat']));
                                return in_array($sortedItems[2], $items);
                            })) / $totalTransactions;

                            $liftAB_C = ($supportAB != 0 && $supportC != 0) ? $supportValue / ($supportAB * $supportC) : 0;
                            $liftBC_A = ($supportBC != 0 && $supportA != 0) ? $supportValue / ($supportBC * $supportA) : 0;
                            $liftAC_B = ($supportAC != 0 && $supportB != 0) ? $supportValue / ($supportAC * $supportB) : 0;

                            // Create unique key for each confidence result
                            $confidenceKeys = [];

                            $confidenceResults3[] = [
                                'items' => "{$sortedItems[0]}, {$sortedItems[1]} -> {$sortedItems[2]}",
                                'confidence' => "{$support} / {$totalAB} = {$confidenceAB_C}",
                                'lift' => "{$supportValue} / ({$supportAB} * {$supportC}) = {$liftAB_C}",
                                'korelasi' => $liftAB_C > 1 ? 'Korelasi Positif' : 'Korelasi Negatif',
                                'keterangan' => $confidenceAB_C > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                            ];

                            $confidenceResults3[] = [
                                'items' => "{$sortedItems[1]}, {$sortedItems[2]} -> {$sortedItems[0]}",
                                'confidence' => "{$support} / {$totalBC} = {$confidenceBC_A}",
                                'lift' => "{$supportValue} / ({$supportBC} * {$supportA}) = {$liftBC_A}",
                                'korelasi' => $liftBC_A > 1 ? 'Korelasi Positif' : 'Korelasi Negatif',
                                'keterangan' => $confidenceBC_A > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                            ];

                            $confidenceResults3[] = [
                                'items' => "{$sortedItems[0]}, {$sortedItems[2]} -> {$sortedItems[1]}",
                                'confidence' => "{$support} / {$totalAC} = {$confidenceAC_B}",
                                'lift' => "{$supportValue} / ({$supportAC} * {$supportB}) = {$liftAC_B}",
                                'korelasi' => $liftAC_B > 1 ? 'Korelasi Positif' : 'Korelasi Negatif',
                                'keterangan' => $confidenceAC_B > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                            ];

                            $confidenceResults3[] = [
                                'items' => "{$sortedItems[0]} -> {$sortedItems[1]}, {$sortedItems[2]}",
                                'confidence' => count($itemsets[$sortedItems[0]]) != 0 ? $support / count($itemsets[$sortedItems[0]]) : 0,
                                'lift' => "{$supportValue} / ({$supportA} * {$supportBC})",
                                'korelasi' => ($supportA != 0 && $supportBC != 0) ? ($supportValue / ($supportA * $supportBC)) > 1 ? 'Korelasi Positif' : 'Korelasi Negatif' : 'Tidak Diketahui',
                                'keterangan' => (count($itemsets[$sortedItems[0]]) != 0 ? ($support / count($itemsets[$sortedItems[0]])) : 0) > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                            ];

                            $confidenceResults3[] = [
                                'items' => "{$sortedItems[1]} -> {$sortedItems[0]}, {$sortedItems[2]}",
                                'confidence' => count($itemsets[$sortedItems[1]]) != 0 ? $support / count($itemsets[$sortedItems[1]]) : 0,
                                'lift' => "{$supportValue} / ({$supportB} * {$supportAC})",
                                'korelasi' => ($supportB != 0 && $supportAC != 0) ? ($supportValue / ($supportB * $supportAC)) > 1 ? 'Korelasi Positif' : 'Korelasi Negatif' : 'Tidak Diketahui',
                                'keterangan' => (count($itemsets[$sortedItems[1]]) != 0 ? ($support / count($itemsets[$sortedItems[1]])) : 0) > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                            ];

                            $confidenceResults3[] = [
                                'items' => "{$sortedItems[2]} -> {$sortedItems[0]}, {$sortedItems[1]}",
                                'confidence' => count($itemsets[$sortedItems[2]]) != 0 ? $support / count($itemsets[$sortedItems[2]]) : 0,
                                'lift' => "{$supportValue} / ({$supportC} * {$supportAB})",
                                'korelasi' => ($supportC != 0 && $supportAB != 0) ? ($supportValue / ($supportC * $supportAB)) > 1 ? 'Korelasi Positif' : 'Korelasi Negatif' : 'Tidak Diketahui',
                                'keterangan' => (count($itemsets[$sortedItems[2]]) != 0 ? ($support / count($itemsets[$sortedItems[2]])) : 0) > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                            ];

                            $confidenceResultsitem3[] = [
                                'items' => "{$sortedItems[0]}, {$sortedItems[1]} -> {$sortedItems[2]}",
                                'confidence' => "{$support} / {$totalAB} = {$confidenceAB_C}",
                                'lift' => "{$supportValue} / ({$supportAB} * {$supportC}) = {$liftAB_C}",
                                'korelasi' => $liftAB_C > 1 ? 'Korelasi Positif' : 'Korelasi Negatif',
                                'keterangan' => $confidenceAB_C > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                            ];

                            $confidenceResultsitem3[] = [
                                'items' => "{$sortedItems[1]}, {$sortedItems[2]} -> {$sortedItems[0]}",
                                'confidence' => "{$support} / {$totalBC} = {$confidenceBC_A}",
                                'lift' => "{$supportValue} / ({$supportBC} * {$supportA}) = {$liftBC_A}",
                                'korelasi' => $liftBC_A > 1 ? 'Korelasi Positif' : 'Korelasi Negatif',
                                'keterangan' => $confidenceBC_A > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                            ];

                            $confidenceResultsitem3[] = [
                                'items' => "{$sortedItems[0]}, {$sortedItems[2]} -> {$sortedItems[1]}",
                                'confidence' => "{$support} / {$totalAC} = {$confidenceAC_B}",
                                'lift' => "{$supportValue} / ({$supportAC} * {$supportB}) = {$liftAC_B}",
                                'korelasi' => $liftAC_B > 1 ? 'Korelasi Positif' : 'Korelasi Negatif',
                                'keterangan' => $confidenceAC_B > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                            ];

                            $confidenceResultsitem3[] = [
                                'items' => "{$sortedItems[0]} -> {$sortedItems[1]}, {$sortedItems[2]}",
                                'confidence' => count($itemsets[$sortedItems[0]]) != 0 ? $support / count($itemsets[$sortedItems[0]]) : 0,
                                'lift' => "{$supportValue} / ({$supportA} * {$supportBC})",
                                'korelasi' => ($supportA != 0 && $supportBC != 0) ? ($supportValue / ($supportA * $supportBC)) > 1 ? 'Korelasi Positif' : 'Korelasi Negatif' : 'Tidak Diketahui',
                                'keterangan' => (count($itemsets[$sortedItems[0]]) != 0 ? ($support / count($itemsets[$sortedItems[0]])) : 0) > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                            ];

                            $confidenceResultsitem3[] = [
                                'items' => "{$sortedItems[1]} -> {$sortedItems[0]}, {$sortedItems[2]}",
                                'confidence' => count($itemsets[$sortedItems[1]]) != 0 ? $support / count($itemsets[$sortedItems[1]]) : 0,
                                'lift' => "{$supportValue} / ({$supportB} * {$supportAC})",
                                'korelasi' => ($supportB != 0 && $supportAC != 0) ? ($supportValue / ($supportB * $supportAC)) > 1 ? 'Korelasi Positif' : 'Korelasi Negatif' : 'Tidak Diketahui',
                                'keterangan' => (count($itemsets[$sortedItems[1]]) != 0 ? ($support / count($itemsets[$sortedItems[1]])) : 0) > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                            ];

                            $confidenceResultsitem3[] = [
                                'items' => "{$sortedItems[2]} -> {$sortedItems[0]}, {$sortedItems[1]}",
                                'confidence' => count($itemsets[$sortedItems[2]]) != 0 ? $support / count($itemsets[$sortedItems[2]]) : 0,
                                'lift' => "{$supportValue} / ({$supportC} * {$supportAB})",
                                'korelasi' => ($supportC != 0 && $supportAB != 0) ? ($supportValue / ($supportC * $supportAB)) > 1 ? 'Korelasi Positif' : 'Korelasi Negatif' : 'Tidak Diketahui',
                                'keterangan' => (count($itemsets[$sortedItems[2]]) != 0 ? ($support / count($itemsets[$sortedItems[2]])) : 0) > $min_confidance ? 'Lolos' : 'Tidak Lolos'
                            ];

                            // Filter duplicate data from confidenceResults3
                            $uniqueConfidenceResults3 = [];
                            foreach ($confidenceResults3 as $result) {
                                $key = $result['items'];
                                if (!isset($confidenceKeys[$key])) {
                                    $confidenceKeys[$key] = true;
                                    $uniqueConfidenceResults3[] = $result;
                                }
                            }

                            foreach ($uniqueConfidenceResults3 as $confidenceResult) {
                                $confidence = new Confidence();
                                $confidence->items = $confidenceResult['items'];
                                $confidence->confidence = $confidenceResult['confidence'];
                                $confidence->lift_ratio = $confidenceResult['lift'];
                                $confidence->keterangan = $confidenceResult['keterangan'];
                                $confidence->itemset = '3-item';
                                $confidence->proses_id = $prosesid;
                                $confidence->korelasi = $confidenceResult['korelasi'];
                                $confidence->save();
                            }

                            // Kosongkan array confidenceResults3 setelah disimpan untuk menghindari duplikasi
                            $confidenceResults3 = [];
                        }
                    }
                }
            }
        }

        $filteredItemset3 = array_filter($itemset3, function ($item) {
            return $item['keterangan'] == 'Lolos';
        });
        $filteredConfidenceItemset3 = array_filter($confidenceResultsitem3, function ($itemset) {
            return $itemset['keterangan'] == 'Lolos';
        });

        dd($totalTransactions, $itemset1, $filteredItemset1, $itemset2, $filteredItemset2,  $itemset3, $filteredItemset3, $filteredConfidenceItemset2, $confidenceResultsitem3, $filteredConfidenceItemset3);
        dd($confidenceResults2, $confidenceResults3);
        return [$itemset1, $itemset2, $itemset3];
    }
}
