<?php

namespace App\Jobs;

use App\Models\Confidence;
use App\Models\Itemset1;
use App\Models\Itemset2;
use App\Models\Itemset3;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class ProcessEclatJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $proses;
    protected $transaksi;
    protected $min_support;
    protected $min_confidance;
    protected $totalTransactions;

    /**
     * Create a new job instance.
     */
    public function __construct($proses, $transaksi, $min_support, $min_confidance, $totalTransactions)
    {
        $this->proses = $proses;
        $this->transaksi = $transaksi;
        $this->min_support = $min_support;
        $this->min_confidance = $min_confidance;
        $this->totalTransactions = $totalTransactions;
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        try {
            Log::info('Memulai eksekusi job ProcessEclatJob...');
            $itemsets = $this->generateItemsets($this->transaksi);
            list($itemset1, $itemset2, $itemset3, $confidenceResults) = $this->calculateEclat($itemsets, $this->min_support, $this->min_confidance, $this->totalTransactions);

            // Store results in the database
            $this->storeItemset1($itemset1);
            $this->storeItemset2($itemset2, $confidenceResults);
            $this->storeItemset3($itemset3, $confidenceResults);

            Log::info('Selesai eksekusi job ProcessEclatJob.');
        } catch (\Exception $e) {
            Log::error('Error saat mengeksekusi job ProcessEclatJob: ' . $e->getMessage());
            throw $e; // Anda dapat melemparkan kembali pengecualian untuk memunculkan peringatan atau penanganan lebih lanjut
        }
    }

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

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

        return $itemsets;
    }

    private function calculateEclat($itemsets, $min_support, $min_confidance, $totalTransactions)
    {
        $min_support_count = $min_support * $totalTransactions;
        $itemset1 = [];
        $itemset2 = [];
        $itemset3 = [];
        $confidenceResults = [];

        foreach ($itemsets as $item => $transactions) {
            $support = count($transactions);
            $supportValue = $support / $totalTransactions;
            $itemset1[] = [
                'item' => $item,
                'support' => $supportValue,
                'keterangan' => $supportValue >= $min_support ? 'Lolos' : 'Tidak Lolos'
            ];
        }

        $items = array_keys($itemsets);
        for ($i = 0; $i < count($items); $i++) {
            for ($j = $i + 1; $j < count($items); $j++) {
                $itemA = $items[$i];
                $itemB = $items[$j];
                $transactionsA = $itemsets[$itemA];
                $transactionsB = $itemsets[$itemB];
                $commonTransactions = array_intersect($transactionsA, $transactionsB);
                $support = count($commonTransactions);
                $supportValue = $support / $totalTransactions;

                $confidence = $support / count($transactionsA);
                $liftRatio = $supportValue / ((count($transactionsA) / $totalTransactions) * (count($transactionsB) / $totalTransactions));
                $keterangan = ($supportValue >= $min_support && $confidence >= $min_confidance) ? 'Lolos' : 'Tidak Lolos';

                $itemset2[] = [
                    'items' => "$itemA, $itemB",
                    'support_xUy' => $supportValue,
                    'support' => $supportValue,
                    'confidence' => $confidence,
                    'lift_ratio' => $liftRatio,
                    'keterangan' => $keterangan
                ];

                if ($supportValue >= $min_support) {
                    if ($confidence >= $min_confidance) {
                        $confidenceResults[] = [
                            'itemset' => "$itemA, $itemB",
                            'support_xUy' => $supportValue,
                            'support_x' => count($transactionsA) / $totalTransactions,
                            'confidence' => $confidence,
                            'lift_ratio' => $liftRatio,
                            'korelasi' => $liftRatio > 1 ? 'Positif' : 'Negatif'
                        ];
                    }
                }
            }
        }

        for ($i = 0; $i < count($items); $i++) {
            for ($j = $i + 1; $j < count($items); $j++) {
                for ($k = $j + 1; $k < count($items); $k++) {
                    $itemA = $items[$i];
                    $itemB = $items[$j];
                    $itemC = $items[$k];
                    $transactionsA = $itemsets[$itemA];
                    $transactionsB = $itemsets[$itemB];
                    $transactionsC = $itemsets[$itemC];
                    $commonTransactions = array_intersect($transactionsA, $transactionsB, $transactionsC);
                    $support = count($commonTransactions);
                    $supportValue = $support / $totalTransactions;

                    $confidence = $support / count($transactionsA);
                    $liftRatio = $supportValue / ((count($transactionsA) / $totalTransactions) * (count($transactionsB) / $totalTransactions) * (count($transactionsC) / $totalTransactions));
                    $keterangan = ($supportValue >= $min_support && $confidence >= $min_confidance) ? 'Lolos' : 'Tidak Lolos';

                    $itemset3[] = [
                        'items' => "$itemA, $itemB, $itemC",
                        'support_xUy' => $supportValue,
                        'support' => $supportValue,
                        'confidence' => $confidence,
                        'lift_ratio' => $liftRatio,
                        'keterangan' => $keterangan
                    ];

                    if ($supportValue >= $min_support) {
                        if ($confidence >= $min_confidance) {
                            $confidenceResults[] = [
                                'itemset' => "$itemA, $itemB, $itemC",
                                'support_xUy' => $supportValue,
                                'support_x' => count($transactionsA) / $totalTransactions,
                                'confidence' => $confidence,
                                'lift_ratio' => $liftRatio,
                                'korelasi' => $liftRatio > 1 ? 'Positif' : 'Negatif'
                            ];
                        }
                    }
                }
            }
        }

        return [$itemset1, $itemset2, $itemset3, $confidenceResults];
    }
    private function storeItemset1($itemset1)
    {
        foreach ($itemset1 as $item) {
            Itemset1::create([
                'atribut' => $item['item'],
                'support' => $item['support'],
                'keterangan' => $item['keterangan'],
                'proses_id' => $this->proses->id,
            ]);
        }
    }

    private function storeItemset2($itemset2, $confidenceResults)
    {
        foreach ($itemset2 as $item) {
            $itemset2Record = Itemset2::create([
                'atribut' => $item['items'],
                'support' => $item['support'],
                'keterangan' => $item['keterangan'],
                'proses_id' => $this->proses->id,
            ]);

            foreach ($confidenceResults as $confidence) {
                if ($confidence['itemset'] === $item['items']) {
                    Confidence::create([
                        'items' => $item['items'],
                        'support_xUy' => $confidence['support_xUy'],
                        'support_x' => $confidence['support_x'],
                        'confidence' => $confidence['confidence'],
                        'lift_ratio' => $confidence['lift_ratio'],
                        'korelasi' => $confidence['korelasi'],
                        'itemset2_id' => $itemset2Record->id,
                    ]);
                }
            }
        }
    }

    private function storeItemset3($itemset3, $confidenceResults)
    {
        foreach ($itemset3 as $item) {
            $itemset3Record = Itemset3::create([
                'atribut' => $item['items'],
                'support' => $item['support'],
                'keterangan' => $item['keterangan'],
                'proses_id' => $this->proses->id,
            ]);

            foreach ($confidenceResults as $confidence) {
                if ($confidence['itemset'] === $item['items']) {
                    Confidence::create([
                        'items' => $item['items'],
                        'support_xUy' => $confidence['support_xUy'],
                        'support_x' => $confidence['support_x'],
                        'confidence' => $confidence['confidence'],
                        'lift_ratio' => $confidence['lift_ratio'],
                        'korelasi' => $confidence['korelasi'],
                        'itemset3_id' => $itemset3Record->id,
                    ]);
                }
            }
        }
    }
}
