<?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 UserGroupController
{
    private $conn;
    private $table = "user_group G";
    private $pk = "IDUserGroup";
    private $sv = "UserGroup";
    protected $displayedColumn = [
        'G.IDUserGroup',
        'G.NamaGroup',
        'G.Deskripsi',
        'G.StatusAktif',
        'G.AdminOnly',
        'G.CreateBy',
        'G.CreateAt',
        'G.LastUpdateBy',
        'G.LastUpdateAt',
        [
            'subquery' => '(SELECT COUNT(*) FROM user u WHERE u.IDGroup = G.IDUserGroup)',
            'alias' => 'TotalUser'
        ],
        [
            'subquery' => '(SELECT COUNT(*) FROM user_group_akses uga WHERE uga.IDUserGroup = G.IDUserGroup AND uga.IsAllow = 1)',
            'alias' => 'TotalAkses'
        ]
    ];

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

    public function select($post)
    {
        $listExclude = [];
        $listSearch =  ['NamaGroup', 'Deskripsi'];
        return runSelect(
            $this->conn,
            $this->table,
            $this->pk,
            $this->displayedColumn,
            $post,
            $listExclude,
            $listSearch
        );
    }

    public function update($post, $files)
    {
        try {
            if (empty($post['NamaGroup'])) {
                throw new Exception("Nama Group tidak boleh kosong");
            }


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

                // --------------------------------------
                // MULAI USER AKSES (tidak diubah)
                // --------------------------------------
                $UserLogin = "";
                $isUpdate = !empty($post['IDUserGroup']) && intval($post['IDUserGroup']) > 0;
                $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']);
                }

                // =========================
                // START - cek duplikat NamaGroup
                // ========================= 
                $duplikatFilter = [["NamaGroup", $post['NamaGroup'], 1]];
                if ($isUpdate)
                    $duplikatFilter[] = ["IDUserGroup", $post['IDUserGroup'], 6];

                $dupSelectParam = [
                    "filters" => $duplikatFilter,
                    "rows_per_page" => 1,
                    "page_number" => 1,
                    "no_count" => true
                ];
                $dupResult = $this->select($dupSelectParam);

                if ($dupResult['Status'] == 1 && count($dupResult['list_data']) > 0) {
                    throw new Exception("Nama Group sudah terpakai");
                }
                // =========================
                // END - cek duplikat
                // =========================

                // =========================
                // START - ambil data lama
                // =========================
                $oldData = [];
                if ($isUpdate) {
                    $oldFilter = [["IDUserGroup", $post['IDUserGroup'], 1]];
                    $oldSelect = [
                        "filters" => $oldFilter,
                        "rows_per_page" => 1,
                        "page_number" => 1,
                        "no_count" => true
                    ];
                    $oldResult = $this->select($oldSelect);
                    if ($oldResult['Status'] == 1) {
                        $oldData = $oldResult['list_data'][0];
                    }
                }
                // =========================
                // END - ambil data lama
                // =========================

                // =========================
                // QUERY user_group
                // =========================
                $NewID = 0;
                $NamaGroup = trim($post['NamaGroup']);
                $Deskripsi = $post['Deskripsi'] ?? '';
                $StatusAktif = intval($post['StatusAktif'] ?? 1);

                if ($isUpdate) {
                    $sql = "UPDATE user_group 
                    SET NamaGroup = ?, Deskripsi = ?, StatusAktif = ?, LastUpdateBy = ?, LastUpdateAt = NOW()
                    WHERE IDUserGroup = ?";
                    $stmt = $conn->prepare($sql);
                    $stmt->bind_param("ssisi", $NamaGroup, $Deskripsi, $StatusAktif, $UserLogin, $post['IDUserGroup']);
                    $stmt->execute();
                    if ($stmt->affected_rows < 0)
                        throw new Exception("Gagal update user group");
                    $stmt->close();
                    $NewID = intval($post['IDUserGroup']);
                } else {
                    $sql = "INSERT INTO user_group (NamaGroup, Deskripsi, StatusAktif, CreateBy, CreateAt)
                    VALUES (?,?,?,?,NOW())";
                    $stmt = $conn->prepare($sql);
                    $stmt->bind_param("ssis", $NamaGroup, $Deskripsi, $StatusAktif, $UserLogin);
                    $stmt->execute();
                    if ($stmt->affected_rows <= 0)
                        throw new Exception("Gagal insert group baru");
                    $NewID = $stmt->insert_id;
                    $stmt->close();
                }

                // =========================
                // START - ambil data baru
                // =========================
                $newData = [];
                if ($NewID > 0) {
                    $newSelect = [
                        "filters" => [["IDUserGroup", $NewID, 1]],
                        "rows_per_page" => 1,
                        "page_number" => 1,
                        "no_count" => true
                    ];
                    $newResult = $this->select($newSelect);
                    if ($newResult['Status'] == 1) {
                        $newData = $newResult['list_data'][0];
                    }
                }
                // =========================
                // END - ambil data baru
                // =========================

                // =========================
                // HANDLE Akses[]
                // =========================
                if ($NewID > 0) {
                    $conn->query("UPDATE user_group_akses SET IsAllow = 0 WHERE IDUserGroup = " . intval($NewID));
                }

                if (!empty($post['Akses']) && is_array($post['Akses'])) {

                    foreach ($post['Akses'] as $idAkses) {
                        $idAkses = intval($idAkses);
                        if ($idAkses <= 0)
                            continue;

                        $sqlCheck = "SELECT IDGroupAkses FROM user_group_akses 
                             WHERE IDUserGroup = ? AND IDAkses = ?";
                        $stmt = $conn->prepare($sqlCheck);
                        $stmt->bind_param("ii", $NewID, $idAkses);
                        $stmt->execute();
                        $stmt->store_result();

                        if ($stmt->num_rows > 0) {
                            // Update
                            $stmt2 = $conn->prepare("UPDATE user_group_akses SET IsAllow = 1 WHERE IDUserGroup = ? AND IDAkses = ?");
                            $stmt2->bind_param("ii", $NewID, $idAkses);
                            $stmt2->execute();
                            $stmt2->close();
                        } else {
                            // Insert
                            $stmt2 = $conn->prepare("INSERT INTO user_group_akses (IDUserGroup, IDAkses, IsAllow) VALUES (?,?,1)");
                            $stmt2->bind_param("ii", $NewID, $idAkses);
                            $stmt2->execute();
                            $stmt2->close();
                        }
                        $stmt->close();
                    }
                }

                // =========================
                // HANDLE User[]
                // =========================
                if (!empty($post['User']) && is_array($post['User'])) {
                    $ids = array_filter(array_map('intval', $post['User']));
                    if (count($ids) > 0) {
                        $idList = implode(",", $ids);
                        $conn->query("UPDATE user SET IDGroup = " . intval($NewID) . " WHERE IDUser IN ($idList)");
                    }
                }

                // =========================
                // 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 = "user_group";
                $KodeUnik = $NewID;
                $queryActivity = g_generateActivityQuery("user_group", "Modify", $newData, $oldData, ["NamaGroup", "AdminOnly"]);
                $this->activityController->generateActivity(
                    $post['IDUserLogin'],
                    $UserLogin,
                    $queryActivity,
                    $FullDevice,
                    $IP,
                    $Category,
                    $KodeUnik
                );

                return [
                    "Status" => 1,
                    "Keterangan" => $isUpdate ? "Group berhasil diupdate" : "Group berhasil ditambahkan",
                    "ID" => $NewID
                ];
            });
        } catch (Exception $e) {
            return [
                "Status" => 0,
                "Keterangan" => $e->getMessage()
            ];
        }

    }

    public function getDetailData($post)
    {
        try {
            if (empty($post['IDGroup'])) {
                throw new Exception("IDGroup tidak boleh kosong");
            }


            $IDGroup = intval($post['IDGroup']);
            $conn = $this->conn;

            // ============================
            // 1️⃣ Ambil data group utama
            // ============================
            $listGroup = [];
            $stmt = $conn->prepare("SELECT * FROM user_group WHERE IDUserGroup = ?");
            if (!$stmt) {
                throw new Exception("Prepare gagal (listGroup): " . $conn->error);
            }
            $stmt->bind_param("i", $IDGroup);
            $stmt->execute();
            $result = $stmt->get_result();
            if ($row = $result->fetch_assoc()) {
                $listGroup = $row;
            }
            $stmt->close();

            if (empty($listGroup)) {
                throw new Exception("Data Group tidak ditemukan");
            }

            // ====================================
            // 2️⃣ Ambil data user_group_akses + akses
            // ====================================
            $listUserGroupAkses = [];
            $sqlAkses = "
        SELECT uga.*, a.AksesName, a.Kategori, a.Deskripsi 
        FROM user_group_akses uga
        INNER JOIN akses a ON a.IDAkses = uga.IDAkses
        WHERE uga.IDUserGroup = ? AND uga.IsAllow = 1
    ";
            $stmt = $conn->prepare($sqlAkses);
            if (!$stmt) {
                throw new Exception("Prepare gagal (UserGroupAkses): " . $conn->error);
            }
            $stmt->bind_param("i", $IDGroup);
            $stmt->execute();
            $result = $stmt->get_result();
            while ($row = $result->fetch_assoc()) {
                $listUserGroupAkses[] = $row;
            }
            $stmt->close();

            // ============================
            // 3️⃣ Ambil daftar User
            // ============================
            $listUser = [];
            $sqlUser = "
        SELECT u.IDUser, u.Username, u.UserStatusAktif, g.NamaGroup
        FROM user u
        LEFT JOIN user_group g ON g.IDUserGroup = u.IDGroup
        WHERE u.IDGroup = ?
    ";
            $stmt = $conn->prepare($sqlUser);
            if (!$stmt) {
                throw new Exception("Prepare gagal (UserList): " . $conn->error);
            }
            $stmt->bind_param("i", $IDGroup);
            $stmt->execute();
            $result = $stmt->get_result();
            while ($row = $result->fetch_assoc()) {
                $listUser[] = $row;
            }
            $stmt->close();

            // ============================
            // 4️⃣ Return final
            // ============================
            return [
                "Status" => 1,
                "Keterangan" => "Data group berhasil diambil",
                "listGroup" => $listGroup,
                "listUserGroupAkses" => $listUserGroupAkses,
                "listUser" => $listUser
            ];
        } catch (Exception $e) {
            return [
                "Status" => 0,
                "Keterangan" => $e->getMessage(),
                "listGroup" => [],
                "listUserGroupAkses" => [],
                "listUser" => []
            ];
        }

    }

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

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

                // --------------------------------------
                // USER AKSES VALIDASI
                // --------------------------------------
                $UserLogin = "";
                $AksesNeeded = $this->sv . ".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 user_group
                // ======================================
                $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.");
                }

                $placeholders = implode(',', array_fill(0, count($idArray), '?'));
                $sqlSelect = "SELECT g.IDUserGroup, g.NamaGroup, g.Deskripsi,
                                (SELECT COUNT(*) FROM user u WHERE u.IDGroup = g.IDUserGroup) AS TotalUser
                          FROM user_group g
                          WHERE g.IDUserGroup IN ($placeholders)";
                $stmt = $conn->prepare($sqlSelect);
                $types = str_repeat('i', count($idArray));
                $stmt->bind_param($types, ...$idArray);
                $stmt->execute();
                $oldData = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
                $stmt->close();

                if (empty($oldData)) {
                    throw new Exception("Data user group tidak ditemukan.");
                }

                // ======================================
                // Filter data yang masih dipakai
                // ======================================
                $errorList = [];
                $deleteID = [];

                foreach ($oldData as $row) {
                    if ($row['TotalUser'] > 0) {
                        $errorList[] = [
                            "IDGroup" => $row['IDUserGroup'],
                            "NamaGroup" => $row['NamaGroup'],
                            "Keterangan" => "Group ini masih digunakan oleh {$row['TotalUser']} user. Mohon kosongkan terlebih dahulu."
                        ];
                    } else {
                        $deleteID[] = $row['IDUserGroup'];
                    }
                }


                // ======================================
                // Lakukan DELETE
                // ======================================
                $statusDelete = 2;

                if (!empty($deleteID)) {
                    $statusDelete = 1;
                    try {
                        // Mulai transaksi biar aman
                        $conn->begin_transaction();

                        // Buat placeholder untuk prepared statement
                        $placeholders = implode(',', array_fill(0, count($deleteID), '?'));
                        $types = str_repeat('i', count($deleteID));

                        // Hapus dari user_group_akses dulu (karena foreign key atau dependensi)
                        $sqlDelAkses = "DELETE FROM user_group_akses WHERE IDUserGroup IN ($placeholders)";
                        $stmtAkses = $conn->prepare($sqlDelAkses);
                        if (!$stmtAkses) {
                            throw new Exception("Gagal prepare delete user_group_akses: " . $conn->error);
                        }
                        $stmtAkses->bind_param($types, ...$deleteID);
                        $stmtAkses->execute();
                        $stmtAkses->close();

                        // Hapus dari user_group
                        $sqlDelGroup = "DELETE FROM user_group WHERE IDUserGroup IN ($placeholders)";
                        $stmtGroup = $conn->prepare($sqlDelGroup);
                        if (!$stmtGroup) {
                            throw new Exception("Gagal prepare delete user_group: " . $conn->error);
                        }
                        $stmtGroup->bind_param($types, ...$deleteID);
                        $stmtGroup->execute();

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

                        $stmtGroup->close();

                        // Commit transaksi kalau semua berhasil
                        $conn->commit();

                    } catch (Exception $e) {
                        // Rollback jika error
                        $conn->rollback();
                        $statusDelete = 2;
                        $errorList[] = [
                            "IDGroup" => implode(',', $deleteID),
                            "NamaGroup" => "-",
                            "Keterangan" => "Terjadi kesalahan saat menghapus data: " . $e->getMessage()
                        ];
                    }
                }



                // ======================================
                // Handle Activity Log
                // ======================================
                $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 = "user_group";

                if (!empty($deleteID)) {
                    foreach ($oldData as $row) {
                        if (in_array($row['IDUserGroup'], $deleteID)) {
                            $KodeUnik = $row['IDUserGroup'];
                            $blacklist = [];
                            $whitelist = ["NamaGroup", "Deskripsi", "StatusAktif"];
                            $queryAcitivy = g_generateActivityQuery("user_group", "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" => []
            ];
        }
    }



}
?>