<?php
require_once __DIR__ . '/../init.php';
require_once PROJECT_ROOT . '/backend/controllers/common_function.php';
require_once PROJECT_ROOT . '/backend/controllers/db_select_helper.php';

// include other controller
require_once PROJECT_ROOT . '/backend/controllers/ActivityController.php';
require_once PROJECT_ROOT . '/backend/controllers/UserAksesController.php';

class BarangSpesifikasiController
{
    private $conn;
    private $table = "
        barang_spesifikasi BS
        LEFT JOIN barang B ON BS.IDBarang = B.IDBarang
    ";
    private $pk = "IDBarangSpesifikasi";
    private $sv = "Barang";
    protected $displayedColumn = [
        'BS.IDBarangSpesifikasi',
        'BS.IDBarang',
        'B.KodeBarang',
        'B.NamaBarang',
        'B.Slug',
        'BS.NamaSpesifikasi',
        'BS.NilaiSpesifikasi',
        'BS.CreateBy',
        'BS.CreateAt',
        'BS.LastUpdateBy',
        'BS.LastUpdateAt'
    ];

    public function __construct($conn)
    {
        $this->conn = $conn;
        $this->activityController = new ActivityController($this->conn);
        $this->userAksesController = new UserAksesController($this->conn);
    }

    public function select($post)
    {
        // Kolom yang boleh di exclude (opsional)
        $listExclude = [];

        // Kolom searchable
        $listSearch = [
            'BS.NamaSpesifikasi',
            'BS.NilaiSpesifikasi',
            'B.KodeBarang',
            'B.NamaBarang'
        ];

        return runSelect(
            $this->conn,
            $this->table,
            $this->pk,
            $this->displayedColumn,
            $post,
            $listExclude,
            $listSearch
        );
    }

    /*
    var_dump($post);
                var_dump($files);
                throw new Exception("stop");
    */

    public function update($post, $files)
    {
        try {

            // VALIDASI: IDBarang wajib
            if (empty($post['IDBarang'])) {
                throw new Exception("IDBarang tidak boleh kosong");
            }

            return runWithTransaction($this->conn, function ($conn) use ($post, $files) {

                $IDBarang = intval($post['IDBarang']);
                $IDBarangSpesifikasi = intval($post['IDBarangSpesifikasi'] ?? 0);

                // Tentukan mode update apabila IDBarangSpesifikasi dikirim
                $isUpdate = $IDBarangSpesifikasi > 0;

                // --------------------------------------
                // 🔹 USER AKSES
                // --------------------------------------
                $UserLogin = "";
                $AksesNeeded = $isUpdate ? $this->sv . ".Modify" : $this->sv . ".Insert";

                $userAksesFilterParam = [
                    ["IDUser", $post['IDUserLogin'], 1]
                ];

                $userAksesselectParam = [
                    "filters" => $userAksesFilterParam,
                    "rows_per_page" => 1,
                    "page_number" => 1,
                    "no_count" => true
                ];

                $userAksesresult = $this->userAksesController->select($userAksesselectParam);
                $listAkses = array_column($userAksesresult['list_data'], 'AksesName');

                if ($userAksesresult['Status'] == 1 && !empty($listAkses)) {
                    if (!in_array($AksesNeeded, $listAkses)) {
                        throw new Exception("User tidak memiliki otoritas akses - [$AksesNeeded]");
                    }
                    $UserLogin = $userAksesresult['Username'];
                } else {
                    throw new Exception($userAksesresult['Keterangan']);
                }



                // -------------------------
                // Sanitasi / bentuk final list
                // -------------------------
                $finalList = [];

                // Jika ada SpesifikasiList dan valid array — ambil, filter & unique by name (case-insensitive)
                if (isset($post['SpesifikasiList']) && is_array($post['SpesifikasiList']) && count($post['SpesifikasiList']) > 0) {
                    $rawList = $post['SpesifikasiList'];

                    // 1) filter item bukan array atau kosong (baik nama maupun nilai kosong => drop)
                    $filtered = array_filter($rawList, function ($item) {
                        if (!is_array($item))
                            return false;
                        $nama = trim($item['NamaSpesifikasi'] ?? '');
                        $nilai = trim($item['NilaiSpesifikasi'] ?? '');
                        return ($nama !== '' || $nilai !== '');
                    });

                    // 2) unique by NamaSpesifikasi (case-insensitive), skip items with empty name
                    $unique = [];
                    foreach ($filtered as $item) {
                        if (!is_array($item))
                            continue;
                        $nama = trim($item['NamaSpesifikasi'] ?? '');
                        $nilai = trim($item['NilaiSpesifikasi'] ?? '');
                        if ($nama === '')
                            continue;
                        $key = mb_strtolower($nama);
                        if (!isset($unique[$key])) {
                            $unique[$key] = true;
                            $finalList[] = [
                                'NamaSpesifikasi' => $nama,
                                'NilaiSpesifikasi' => $nilai
                            ];
                        }
                    }
                }

                // Jika finalList kosong, cek apakah nama/nilai dikirim secara terpisah
                if (empty($finalList)) {
                    $NamaSpesifikasi = trim($post['NamaSpesifikasi'] ?? '');
                    $NilaiSpesifikasi = trim($post['NilaiSpesifikasi'] ?? '');
                    if ($NamaSpesifikasi !== '' || $NilaiSpesifikasi !== '') {
                        if ($NamaSpesifikasi === '' || $NilaiSpesifikasi === '') {
                            throw new Exception("Jika SpesifikasiList kosong, NamaSpesifikasi dan NilaiSpesifikasi harus diisi berdua.");
                        }
                        $finalList[] = [
                            'NamaSpesifikasi' => $NamaSpesifikasi,
                            'NilaiSpesifikasi' => $NilaiSpesifikasi
                        ];
                    }
                }

                // Jika tetap kosong berarti input invalid
                /*
                if (empty($finalList)) {
                    throw new Exception("Spesifikasi tidak boleh kosong.");
                }*/

                // ====================================================
                // RULE: cek duplikat di input (nama)
                // ====================================================
                $inputNames = array_map(function ($x) {
                    return mb_strtolower(trim($x['NamaSpesifikasi']));
                }, $finalList);

                if (count($inputNames) !== count(array_unique($inputNames))) {
                    throw new Exception("NamaSpesifikasi duplikat di input tidak diperbolehkan.");
                }

                // =========================
                // START - ambil data lama (hanya jika update single)
                // =========================
                $oldData = [];
                if ($isUpdate) {

                    $oldDataFilter = [
                        ["IDBarangSpesifikasi", $IDBarangSpesifikasi, 1]
                    ];

                    $oldDataSelectParam = [
                        "filters" => $oldDataFilter,
                        "rows_per_page" => 1,
                        "page_number" => 1,
                        "no_count" => true
                    ];

                    $oldDataResult = $this->select($oldDataSelectParam);

                    if ($oldDataResult['Status'] == 1) {
                        $oldData = $oldDataResult['list_data'][0];
                    } else {
                        throw new Exception($oldDataResult['Keterangan']);
                    }
                }
                // =========================
                // END - ambil data lama
                // =========================

                // =====================================================
                // RULE: CEK DUPLIKASI DI DATABASE untuk IDBarang
                // =====================================================
                $sqlCheck = "SELECT IDBarangSpesifikasi, NamaSpesifikasi FROM barang_spesifikasi WHERE IDBarang = ?";
                $stmt = $conn->prepare($sqlCheck);
                $stmt->bind_param("i", $IDBarang);
                $stmt->execute();
                $rs = $stmt->get_result();

                $existingNames = []; // lowercased names
                $existingById = []; // map id => name (lower)
                while ($row = $rs->fetch_assoc()) {
                    $existingNames[] = mb_strtolower($row['NamaSpesifikasi']);
                    $existingById[intval($row['IDBarangSpesifikasi'])] = mb_strtolower($row['NamaSpesifikasi']);
                }
                $stmt->close();

                // Jika update, izinkan nama lama (hapus dari existingNames agar tidak dianggap duplikat)
                if ($isUpdate && !empty($oldData)) {
                    $oldName = mb_strtolower($oldData['NamaSpesifikasi'] ?? '');
                    $pos = array_search($oldName, $existingNames);
                    if ($pos !== false) {
                        unset($existingNames[$pos]);
                        // reindex
                        $existingNames = array_values($existingNames);
                    }
                }

                // Jika ada nama input yang sudah ada di DB (setelah pengecualian update), throw
                foreach ($inputNames as $nm) {
                    if (in_array($nm, $existingNames)) {
                        throw new Exception("NamaSpesifikasi '$nm' sudah ada pada barang ini.");
                    }
                }

                // =====================================================
                // Jika mode UPDATE (IDBarangSpesifikasi dikirim) -> hanya 1 item allowed
                // =====================================================
                if ($isUpdate) {
                    if (count($finalList) > 1) {
                        throw new Exception("Mode update hanya untuk 1 spesifikasi saja.");
                    }

                    $item = $finalList[0];

                    $sql = "UPDATE barang_spesifikasi 
                        SET NamaSpesifikasi = ?, 
                            NilaiSpesifikasi = ?, 
                            LastUpdateBy = ?, 
                            LastUpdateAt = NOW()
                        WHERE IDBarangSpesifikasi = ?";

                    $stmt = $conn->prepare($sql);
                    $stmt->bind_param(
                        "sssi",
                        $item['NamaSpesifikasi'],
                        $item['NilaiSpesifikasi'],
                        $UserLogin,
                        $IDBarangSpesifikasi
                    );
                    $stmt->execute();

                    if ($stmt->affected_rows < 0) {
                        $stmt->close();
                        throw new Exception("Gagal update spesifikasi.");
                    }
                    $stmt->close();

                    // Ambil data baru (1 item)
                    $newDataFilter = [
                        ["IDBarangSpesifikasi", $IDBarangSpesifikasi, 1]
                    ];

                    $newDataResult = $this->select([
                        "filters" => $newDataFilter,
                        "rows_per_page" => 1,
                        "page_number" => 1,
                        "no_count" => true
                    ]);

                    $newData = ($newDataResult['Status'] == 1) ? $newDataResult['list_data'][0] : [];

                    // =========================
                    // HANDLE Activity
                    // =========================
                    $di = json_decode($post['DeviceInfo'], true);
                    $Platform = $di['platform'] ?? '';
                    $DeviceName = $di['device_name'] ?? '';
                    $FullDevice = $di['FullDevice'] ?? $Platform . " - " . $DeviceName;
                    $IP = $post['IP'] ?? ($_SERVER['REMOTE_ADDR'] ?? '');

                    $Category = "barang";
                    $TipeActivity = "Modify";

                    $queryAcitivy = g_generateActivityQuery(
                        $Category,
                        $TipeActivity,
                        $newData,
                        $oldData,
                        []
                    );

                    $this->activityController->generateActivity(
                        $post['IDUserLogin'],
                        $UserLogin,
                        $queryAcitivy,
                        $FullDevice,
                        $IP,
                        $Category,
                        $IDBarang
                    );

                    return [
                        "Status" => 1,
                        "Keterangan" => "Data spesifikasi berhasil diupdate",
                        "IDBarangSpesifikasi" => $IDBarangSpesifikasi
                    ];
                }

                // =====================================================
                // INSERT (bisa multiple) ke barang_spesifikasi
                // =====================================================
                $sqlInsert = "INSERT INTO barang_spesifikasi 
                (IDBarang, NamaSpesifikasi, NilaiSpesifikasi, CreateBy, CreateAt) 
                VALUES (?, ?, ?, ?, NOW())";

                $stmt = $conn->prepare($sqlInsert);
                $newIDArray = [];

                foreach ($finalList as $sp) {
                    $nama = $sp['NamaSpesifikasi'];
                    $nilai = $sp['NilaiSpesifikasi'];

                    $stmt->bind_param(
                        "isss",
                        $IDBarang,
                        $nama,
                        $nilai,
                        $UserLogin
                    );
                    $stmt->execute();

                    if ($stmt->affected_rows <= 0) {
                        $stmt->close();
                        throw new Exception("Gagal insert spesifikasi '{$nama}'.");
                    }

                    $newIDArray[] = $stmt->insert_id;
                }

                $stmt->close();

                // =========================
                // ambil data baru (multiple)
                // =========================
                $newData = [];


                if (!empty($newIDArray)) {

                    // Ubah array menjadi string ID dipisah koma
                    $newIDString = implode(",", $newIDArray);

                    $newDataResult = $this->select([
                        "filters" => [
                            ["IDBarangSpesifikasi", $newIDString, 7] // 7 = IN
                        ],
                        "rows_per_page" => count($newIDArray),
                        "page_number" => 1,
                        "no_count" => true
                    ]);

                    if ($newDataResult['Status'] == 1) {
                        $newData = $newDataResult['list_data'];
                    } else {
                        throw new Exception($newDataResult['Keterangan']);
                    }
                }



                // =========================
                // HANDLE Activity for each inserted item
                // =========================
                $di = json_decode($post['DeviceInfo'], true);
                $Platform = $di['platform'] ?? '';
                $DeviceName = $di['device_name'] ?? '';
                $FullDevice = $di['FullDevice'] ?? $Platform . " - " . $DeviceName;
                $IP = "";

                $whitelistField = ["NamaSpesifikasi", "NilaiSpesifikasi"];

                if (isset($post['IP'])) {
                    $IP = $post['IP'];
                } else {
                    if (isset($_SERVER['REMOTE_ADDR'])) {
                        $IP = $_SERVER['REMOTE_ADDR'];
                    }
                }
                foreach ($newData as $nd) {
                    $queryAcitivy = g_generateActivityQuery(
                        "spesifikasi barang",
                        "Insert",
                        $nd,
                        [],
                        [],
                        $whitelistField
                    );

                    $this->activityController->generateActivity(
                        $post['IDUserLogin'],
                        $UserLogin,
                        $queryAcitivy,
                        $FullDevice,
                        $IP,
                        "barang",
                        $IDBarang
                    );
                }

                return [
                    "Status" => 1,
                    "Keterangan" => "Data spesifikasi berhasil ditambahkan",
                    "InsertedIDs" => $newIDArray
                ];
            });
        } catch (Exception $e) {
            return [
                "Status" => 0,
                "Keterangan" => $e->getMessage()
            ];
        }
    }

    public function delete($post)
    {
        try {
            $MainID = $post[$this->pk];
            if (empty($MainID)) {
                throw new Exception("Parameter tidak lengkap");
            }

            return runWithTransaction($this->conn, function ($conn) use ($MainID, $post) {

                // --------------------------------------
                // VALIDASI AKSES USER
                // --------------------------------------
                $UserLogin = "";
                $AksesNeeded = $this->sv . ".Delete"; // BarangSpesifikasi.Delete
                $userAksesFilterParam = [
                    ["IDUser", $post['IDUserLogin'], 1]
                ];

                $userAksesselectParam = [
                    "filters" => $userAksesFilterParam,
                    "rows_per_page" => 1,
                    "page_number" => 1,
                    "no_count" => true
                ];

                $userAksesresult = $this->userAksesController->select($userAksesselectParam);
                $listAkses = array_column($userAksesresult['list_data'], 'AksesName');

                if ($userAksesresult['Status'] == 1 && !empty($listAkses)) {
                    if (!in_array($AksesNeeded, $listAkses)) {
                        throw new Exception("User tidak memiliki otoritas akses - [" . $AksesNeeded . "]");
                    }
                    $UserLogin = $userAksesresult['Username'];
                } else {
                    throw new Exception($userAksesresult['Keterangan'] ?? "Akses pengguna tidak valid");
                }

                // --------------------------------------
                // AMBIL DATA LAMA 
                // --------------------------------------
                $oldData = [];
                $idArray = is_array($MainID)
                    ? $MainID
                    : array_filter(array_unique(array_map('trim', explode(',', $MainID))));

                if (empty($idArray)) {
                    throw new Exception("Tidak ada ID valid untuk dihapus.");
                }

                if (count($idArray) > 1000) {
                    throw new Exception("Maksimal 1000 data yang dapat dihapus sekaligus.");
                }

                $oldDataFilter = [
                    ["IDBarangSpesifikasi", $MainID, 7]
                ];

                $oldDataSelectParam = [
                    "filters" => $oldDataFilter,
                    "rows_per_page" => 0,
                    "page_number" => 1,
                    "no_count" => true
                ];

                $oldDataResult = $this->select($oldDataSelectParam);

                
                if ($oldDataResult['Status'] == 1) {
                    $oldData = $oldDataResult['list_data'];
                } else {
                    $msg = $oldDataResult['Keterangan'];
                    throw new Exception($msg);
                }
 

                $errorList = [];
                $deleteID = []; 
                foreach ($oldData as $row) {
                    $canDelete = true; 
                    
                    if ($canDelete) {
                        $deleteID[] = $row['IDBarangSpesifikasi'];
                    }
                } 
                // --------------------------------------
                // PROSES DELETE
                // --------------------------------------
                $statusDelete = 2;
 
                if (!empty($deleteID)) {
                    $statusDelete = 1;
                    try {
                        $conn->begin_transaction();

                        $placeholders = implode(',', array_fill(0, count($deleteID), '?'));
                        $types = str_repeat('i', count($deleteID));

                        $sqlDelBarangSpesifikasi = "DELETE FROM barang_spesifikasi WHERE IDBarangSpesifikasi IN ($placeholders)";
                        $stmtDel = $conn->prepare($sqlDelBarangSpesifikasi);
                        if (!$stmtDel) {
                            throw new Exception("Gagal prepare delete barang_spesifikasi: " . $conn->error);
                        }
                        $stmtDel->bind_param($types, ...$deleteID);
                        $stmtDel->execute();

                        if ($stmtDel->affected_rows <= 0) {
                            $statusDelete = 2;
                            $errorList[] = [
                                "IDBarangSpesifikasi" => implode(',', $deleteID),
                                "NamaBarangSpesifikasi" => "-",
                                "Keterangan" => "Tidak ada data yang dihapus dari tabel barang_spesifikasi."
                            ];
                        }

                        $stmtDel->close();
                        $conn->commit();
                    } catch (Exception $e) {
                        $conn->rollback();
                        $statusDelete = 2;
                        $errorList[] = [
                            "IDBarangSpesifikasi" => implode(',', $deleteID),
                            "NamaBarangSpesifikasi" => "-",
                            "Keterangan" => "Terjadi kesalahan saat menghapus data: " . $e->getMessage()
                        ];
                    }
                }

             

                // --------------------------------------
                // LOG AKTIVITAS
                // --------------------------------------
                $di = json_decode($post['DeviceInfo'], true);
                $Platform = $di['platform'] ?? '';
                $DeviceName = $di['device_name'] ?? '';
                $FullDevice = $di['FullDevice'] ?? $Platform . " - " . $DeviceName;
                $IP = $post['IP'] ?? ($_SERVER['REMOTE_ADDR'] ?? '');
                $Category = "barang";

                if (!empty($deleteID)) {
                    foreach ($oldData as $row) {
                        if (in_array($row['IDBarangSpesifikasi'], $deleteID)) {
                            $KodeUnik = $row['IDBarang'];
                            $blacklist = [];
                            $whitelist = ["NamaSpesifikasi", "NilaiSpesifikasi"];
                            $queryAcitivy = g_generateActivityQuery("barang_spesifikasi", "Delete", $row, null, $blacklist, $whitelist);
                            $this->activityController->generateActivity(
                                $post['IDUserLogin'],
                                $UserLogin,
                                $queryAcitivy,
                                $FullDevice,
                                $IP,
                                $Category,
                                $KodeUnik
                            );
                        }
                    }
                }

                // --------------------------------------
                // FINAL RETURN
                // --------------------------------------
                if ($statusDelete === 1 && empty($errorList)) {
                    return [
                        "Status" => 1,
                        "Keterangan" => "Semua data berhasil dihapus",
                        "listErrorMessage" => []
                    ];
                } else {
                    return [
                        "Status" => 0,
                        "Keterangan" => "",
                        "listErrorMessage" => $errorList
                    ];
                }
            });
        } catch (Exception $e) {
            return [
                "Status" => 0,
                "Keterangan" => $e->getMessage(),
                "listErrorMessage" => []
            ];
        }
    }


}
?>