<?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';
require_once PROJECT_ROOT . '/backend/controllers/AttachmentController.php';

class RankingCategoryController
{
    private $conn;
    private $table = "ranking_category T
    LEFT JOIN (
            SELECT C.IDRankCategory, COUNT(*) AS TotalPlayer
            FROM player_ranking C
            GROUP BY C.IDRankCategory
        ) AS SK ON SK.IDRankCategory = T.IDRankCategory";
    private $pk = "IDRankCategory";
    private $sv = "RankingCategory";

    protected $displayedColumn = [
        'T.IDRankCategory',
        'T.CategoryName',
        'T.CategoryCode',
        'T.MinPoints',
        'T.MaxPoints',
        'T.Description',
        'T.IsActive',
        'T.IsDefaultRank',
        'T.CreateBy',
        'T.CreateAt',
        'T.LastUpdateBy',
        'T.LastUpdateAt',
        'IFNULL(SK.TotalPlayer, 0) AS TotalPlayer',
    ];

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

    public function select($post)
    {
        $listExclude = [];

        $listSearch = [
            'IDRankCategory',
            'CategoryName',
            'CategoryCode',
            'Description'
        ];

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

    public function update($post, $files)
    {
        try {
            // Validasi required fields
            if (empty($post['CategoryName'])) {
                throw new Exception("Nama Kategori tidak boleh kosong");
            }

            if (!isset($post['MinPoints']) || !is_numeric($post['MinPoints'])) {
                throw new Exception("Min Points harus diisi dengan angka");
            }

          

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

                $CategoryName = trim($post['CategoryName']);
                $CategoryCode = trim($post['CategoryCode'] ?? '');
                $MinPoints = intval($post['MinPoints'] ?? null);
                $MaxPoints = intval($post['MaxPoints'] ?? null);
                $Description = trim($post['Description'] ?? '');
                $IsExclusive = isset($post['IsExclusive']) ? intval($post['IsExclusive']) : 0;
                $IsActive = isset($post['IsActive']) ? intval($post['IsActive']) : 1;
                $IsDefaultRank = isset($post['IsDefaultRank']) ? intval($post['IsDefaultRank']) : 0;
                $SortOrder = isset($post['SortOrder']) ? intval($post['SortOrder']) : 0;
                
                $isUpdate = !empty($post['IDRankCategory']) && intval($post['IDRankCategory']) > 0;

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

                $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)) {
                        $msg = "User tidak memiliki otoritas akses - [" . $AksesNeeded . "]";
                        throw new Exception($msg);
                    }

                    $UserLogin = $userAksesresult['Username'];
                } else {
                    $msg = $userAksesresult['Keterangan'] ?? "Akses pengguna tidak valid";
                    throw new Exception($msg);
                }
                // --------------------------------------
                // END USER AKSES
                // --------------------------------------

                // =========================
                // START - cek duplikat
                // ========================= 
                $duplikatDataFilter = [];
                $duplikatDataFilter[] = ["CategoryName", $post['CategoryName'], 1];

                if (!empty($CategoryCode)) {
                    $duplikatDataFilter[] = ["CategoryCode", $CategoryCode, 1];
                }

                if ($isUpdate) {
                    $duplikatDataFilter[] = ["IDRankCategory", $post['IDRankCategory'], 6];
                }

                $duplikatDataSelectParam = [
                    "filters" => $duplikatDataFilter,
                    "rows_per_page" => 1,
                    "page_number" => 1,
                    "no_count" => true
                ];
                $duplikatDataResult = $this->select($duplikatDataSelectParam);

                if ($duplikatDataResult['Status'] == 1 && count($duplikatDataResult['list_data']) > 0) {
                    $msg = "Kategori dengan nama atau kode yang sama sudah terpakai, mohon diganti";
                    throw new Exception($msg);
                }
                // =========================
                // END - cek duplikat
                // =========================

                // =========================
                // START - ambil data lama
                // =========================
                $oldData = [];
                if ($isUpdate && !empty($post['IDRankCategory'])) {

                    $oldDataFilter = [
                        ["IDRankCategory", $post['IDRankCategory'], 1]
                    ];

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

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

                    if ($oldDataResult['Status'] == 1 && !empty($oldDataResult['list_data'])) {
                        $oldData = $oldDataResult['list_data'][0];
                    } else {
                        $msg = $oldDataResult['Keterangan'] ?? "Data tidak ditemukan";
                        throw new Exception($msg);
                    }

                    // Jika ada default rank lain dan ini diubah jadi default, cek yang lain
                    if ($IsDefaultRank == 1) {
                        $checkDefaultFilter = [
                            ["IsDefaultRank", 1, 1],
                            ["IDRankCategory", $post['IDRankCategory'], 6]
                        ];
                        $checkDefaultParam = [
                            "filters" => $checkDefaultFilter,
                            "rows_per_page" => 1,
                            "page_number" => 1,
                            "no_count" => true
                        ];
                        $checkDefaultResult = $this->select($checkDefaultParam);
                        if ($checkDefaultResult['Status'] == 1 && count($checkDefaultResult['list_data']) > 0) {
                            // Update default rank yang lama menjadi 0
                            $sqlUpdateDefault = "UPDATE ranking_category SET IsDefaultRank = 0 WHERE IDRankCategory != ?";
                            $stmtUpdateDefault = $conn->prepare($sqlUpdateDefault);
                            $stmtUpdateDefault->bind_param("i", $post['IDRankCategory']);
                            $stmtUpdateDefault->execute();
                            $stmtUpdateDefault->close();
                        }
                    }
                }
                // =========================
                // END - ambil data lama
                // =========================

                // =========================
                // QUERY DATABASE
                // =========================
                $NewID = 0;

                if ($isUpdate) {
                    // Update ranking_category
                    $sql = "UPDATE ranking_category 
                        SET CategoryName = ?, 
                            CategoryCode = ?, 
                            MinPoints = ?,
                            MaxPoints = ?,
                            Description = ?,
                            IsActive = ?,
                            IsDefaultRank = ?,
                            SortOrder = ?,
                            LastUpdateBy = ?, 
                            LastUpdateAt = NOW()
                        WHERE IDRankCategory = ?";

                    $stmt = $conn->prepare($sql);
                    if (!$stmt) {
                        throw new Exception("Prepare statement gagal: " . $conn->error);
                    }

                    $stmt->bind_param(
                        "ssiissiisi",
                        $CategoryName,
                        $CategoryCode,
                        $MinPoints,
                        $MaxPoints,
                        $Description,
                        $IsActive,
                        $IsDefaultRank,
                        $SortOrder,
                        $UserLogin,
                        $post['IDRankCategory']
                    );

                    $stmt->execute();

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

                    $stmt->close();
                    $NewID = $post['IDRankCategory'];
                } else {
                    // Insert ranking_category baru
                    $sql = "INSERT INTO ranking_category 
                        (CategoryName, CategoryCode, MinPoints, MaxPoints, Description, 
                         IsActive, IsDefaultRank, SortOrder, CreateBy, CreateAt) 
                        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())";

                    $stmt = $conn->prepare($sql);
                    if (!$stmt) {
                        throw new Exception("Prepare statement gagal: " . $conn->error);
                    }

                    $stmt->bind_param(
                        "ssiisiiis",
                        $CategoryName,
                        $CategoryCode,
                        $MinPoints,
                        $MaxPoints,
                        $Description,
                        $IsActive,
                        $IsDefaultRank,
                        $SortOrder,
                        $UserLogin
                    );

                    $stmt->execute();

                    if ($stmt->affected_rows <= 0) {
                        throw new Exception("Gagal insert ranking_category baru");
                    }

                    $NewID = $stmt->insert_id;
                    $stmt->close();

                    // Jika ini default rank, update yang lain
                    if ($IsDefaultRank == 1) {
                        $sqlUpdateDefault = "UPDATE ranking_category SET IsDefaultRank = 0 WHERE IDRankCategory != ?";
                        $stmtUpdateDefault = $conn->prepare($sqlUpdateDefault);
                        $stmtUpdateDefault->bind_param("i", $NewID);
                        $stmtUpdateDefault->execute();
                        $stmtUpdateDefault->close();
                    }
                }

                // =========================
                // START - ambil data baru
                // =========================
                $newData = [];
                if ($NewID > 0) {

                    $newDataFilter = [
                        ["IDRankCategory", $NewID, 1]
                    ];

                    $newDataSelectParam = [
                        "filters" => $newDataFilter,
                        "rows_per_page" => 1,
                        "page_number" => 1,
                        "no_count" => true
                    ];

                    $newDataResult = $this->select($newDataSelectParam);

                    if ($newDataResult['Status'] == 1 && !empty($newDataResult['list_data'])) {
                        $newData = $newDataResult['list_data'][0];
                    } else {
                        $msg = $newDataResult['Keterangan'] ?? "Gagal mengambil data baru";
                        throw new Exception($msg);
                    }
                }
                // =========================
                // END - ambil data baru
                // =========================

                // =========================
                // START 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 = "ranking_category";
                $KodeUnik = $NewID;
                $TipeActivity = $isUpdate ? "Modify" : "Insert";
                
                $queryAcitivy = g_generateActivityQuery(
                    $Category,
                    $TipeActivity,
                    $newData,
                    $oldData,
                    []
                );
                
                $this->activityController->generateActivity(
                    $post['IDUserLogin'],
                    $UserLogin,
                    $queryAcitivy,
                    $FullDevice,
                    $IP,
                    $Category,
                    $KodeUnik
                );
                // =========================
                // END HANDLE Activity
                // =========================

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

    public function delete($post)
    {
        try {
            $MainID = $post[$this->pk] ?? null;
            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";

                $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 
                // --------------------------------------
                $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 = [
                    ["IDRankCategory", $idArray, 7]
                ];

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

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

                if ($oldDataResult['Status'] != 1 || empty($oldDataResult['list_data'])) {
                    throw new Exception($oldDataResult['Keterangan'] ?? "Data tidak ditemukan");
                }

                $oldData = $oldDataResult['list_data'];

                // --------------------------------------
                // VALIDASI: Cek apakah ada yang masih terpakai
                // --------------------------------------
                $errorList = [];
                $deleteID = [];

                foreach ($oldData as $row) {
                    $canDelete = true;

                    // Cek apakah ada player_ranking yang menggunakan kategori ini
                    $checkUsageSql = "SELECT COUNT(*) as total FROM player_ranking WHERE IDRankCategory = ?";
                    $stmtCheck = $conn->prepare($checkUsageSql);
                    $stmtCheck->bind_param("i", $row['IDRankCategory']);
                    $stmtCheck->execute();
                    $resultCheck = $stmtCheck->get_result();
                    $usageData = $resultCheck->fetch_assoc();
                    $stmtCheck->close();

                    if ($usageData['total'] > 0) {
                        $errorList[] = [
                            "IDRankCategory" => $row['IDRankCategory'],
                            "CategoryName" => $row['CategoryName'],
                            "Keterangan" => "Kategori ini masih memiliki {$usageData['total']} player. Mohon hapus atau pindahkan player terlebih dahulu."
                        ];
                        $canDelete = false;
                    }

                    if ($canDelete) {
                        $deleteID[] = $row['IDRankCategory'];
                    }
                }

                // --------------------------------------
                // PROSES DELETE
                // --------------------------------------
                $statusDelete = 2;

                if (!empty($deleteID)) {
                    try {
                        $placeholders = implode(',', array_fill(0, count($deleteID), '?'));
                        $types = str_repeat('i', count($deleteID));

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

                        if ($stmtDel->affected_rows > 0) {
                            $statusDelete = 1;
                        } else {
                            $errorList[] = [
                                "IDRankCategory" => implode(',', $deleteID),
                                "CategoryName" => "-",
                                "Keterangan" => "Tidak ada data yang dihapus dari tabel ranking_category."
                            ];
                        }

                        $stmtDel->close();
                    } catch (Exception $e) {
                        $statusDelete = 2;
                        $errorList[] = [
                            "IDRankCategory" => implode(',', $deleteID),
                            "CategoryName" => "-",
                            "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 = "ranking_category";

                if (!empty($deleteID)) {
                    foreach ($oldData as $row) {
                        if (in_array($row['IDRankCategory'], $deleteID)) {
                            $KodeUnik = $row['IDRankCategory'];
                            $whitelist = ["CategoryName", "CategoryCode", "MinPoints", "MaxPoints"];
                            $queryAcitivy = g_generateActivityQuery(
                                "ranking_category", 
                                "Delete", 
                                $row, 
                                null, 
                                [], 
                                $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" => !empty($errorList) ? "Beberapa data gagal dihapus" : "Gagal menghapus data",
                        "listErrorMessage" => $errorList
                    ];
                }
            });
        } catch (Exception $e) {
            return [
                "Status" => 0,
                "Keterangan" => $e->getMessage(),
                "listErrorMessage" => []
            ];
        }
    }

    // Method tambahan untuk mendapatkan ranking category by points
    public function getRankByPoints($points)
    {
        try {
            $sql = "SELECT * FROM ranking_category 
                    WHERE IsActive = 1 
                    AND MinPoints <= ? 
                    AND MaxPoints >= ? 
                    ORDER BY SortOrder ASC, MinPoints ASC 
                    LIMIT 1";
            
            $stmt = $this->conn->prepare($sql);
            $stmt->bind_param("ii", $points, $points);
            $stmt->execute();
            $result = $stmt->get_result();
            $data = $result->fetch_assoc();
            $stmt->close();

            return [
                "Status" => 1,
                "Keterangan" => "Success",
                "data" => $data
            ];
        } catch (Exception $e) {
            return [
                "Status" => 0,
                "Keterangan" => $e->getMessage()
            ];
        }
    }

    // Method untuk mendapatkan default rank
    public function getDefaultRank()
    {
        try {
            $sql = "SELECT * FROM ranking_category 
                    WHERE IsActive = 1 AND IsDefaultRank = 1 
                    LIMIT 1";
            
            $result = $this->conn->query($sql);
            $data = $result->fetch_assoc();

            return [
                "Status" => 1,
                "Keterangan" => "Success",
                "data" => $data
            ];
        } catch (Exception $e) {
            return [
                "Status" => 0,
                "Keterangan" => $e->getMessage()
            ];
        }
    }

    // Method untuk toggle active status
    public function toggleActive($post)
    {
        try {
            if (empty($post['IDRankCategory'])) {
                throw new Exception("ID Rank Category tidak boleh kosong");
            }

            $IDRankCategory = intval($post['IDRankCategory']);
            $IsActive = isset($post['IsActive']) ? intval($post['IsActive']) : 0;

            $sql = "UPDATE ranking_category SET IsActive = ? WHERE IDRankCategory = ?";
            $stmt = $this->conn->prepare($sql);
            $stmt->bind_param("ii", $IsActive, $IDRankCategory);
            $stmt->execute();

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

            $stmt->close();

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