<?php

define('BASE_PATH', realpath(__DIR__ . '/../..'));

require_once BASE_PATH . '/config/autoload.php';
require_once BASE_PATH . '/config/bootstrap.php';

$db = \App\Core\Database::getInstance();

echo "SIDEBAR PERMISSIONS SYNC\n";

$files = [
    BASE_PATH . '/app/views/partials/unified_role_layout_links.php',
    BASE_PATH . '/app/views/layouts/admin_layout.php',
    BASE_PATH . '/app/views/layouts/author_layout.php',
    BASE_PATH . '/app/views/layouts/reviewer_layout.php',
];

function table_columns(PDO $db, string $table): array
{
    $stmt = $db->prepare("
        SELECT COLUMN_NAME
        FROM information_schema.COLUMNS
        WHERE TABLE_SCHEMA = DATABASE()
        AND TABLE_NAME = ?
    ");
    $stmt->execute([$table]);
    return array_column($stmt->fetchAll(PDO::FETCH_ASSOC), 'COLUMN_NAME');
}

function make_key(string $url): string
{
    $key = trim($url);
    $key = preg_replace('#^/easychair/#', '', $key);
    $key = preg_replace('#^/#', '', $key);
    $key = str_replace(['/', '-'], ['.', '_'], $key);
    $key = preg_replace('/[^a-zA-Z0-9_.]/', '_', $key);
    return $key ?: 'menu.item';
}

function guess_roles(string $block): array
{
    if (!preg_match("/'roles'\\s*=>\\s*\\[(.*?)\\]/s", $block, $m)) {
        return [];
    }

    preg_match_all("/'([^']+)'/", $m[1], $r);
    return array_values(array_unique($r[1] ?? []));
}

function extract_label(string $block, string $fallback): string
{
    if (preg_match("/'label'\\s*=>\\s*'([^']+)'/s", $block, $m)) {
        return $m[1];
    }

    if (preg_match('/"label"\\s*=>\\s*"([^"]+)"/s', $block, $m)) {
        return $m[1];
    }

    return $fallback;
}

function extract_label_key(string $block, string $fallback): string
{
    if (preg_match("/'label_key'\\s*=>\\s*'([^']+)'/s", $block, $m)) {
        return $m[1];
    }

    if (preg_match('/"label_key"\\s*=>\\s*"([^"]+)"/s', $block, $m)) {
        return $m[1];
    }

    return $fallback;
}

$menuCols = table_columns($db, 'rbac_menu_items');
$permCols = table_columns($db, 'rbac_role_menu_permissions');

$roles = $db->query("
    SELECT id, code
    FROM roles
")->fetchAll(PDO::FETCH_ASSOC);

$roleMap = [];
foreach ($roles as $r) {
    $roleMap[$r['code']] = (int)$r['id'];
}

$items = [];

foreach ($files as $file) {

    if (!is_file($file)) {
        continue;
    }

    $txt = file_get_contents($file);

    preg_match_all("/\\[(.*?)\\]/s", $txt, $blocks);

    foreach ($blocks[0] as $block) {

        if (!preg_match("/'url'\\s*=>\\s*'([^']+)'/s", $block, $m)
            && !preg_match('/"url"\\s*=>\\s*"([^"]+)"/s', $block, $m)) {
            continue;
        }

        $url = trim($m[1]);

        if ($url === '' || $url === '#') {
            continue;
        }

        if (!str_starts_with($url, '/easychair/')) {
            continue;
        }

        $key = make_key($url);
        $label = extract_label($block, ucwords(str_replace(['.', '_'], ' ', $key)));
        $labelKey = extract_label_key($block, 'menu.' . str_replace('.', '_', $key));
        $itemRoles = guess_roles($block);

        $items[$url] = [
            'url' => $url,
            'menu_key' => $key,
            'label' => $label,
            'label_key' => $labelKey,
            'roles' => $itemRoles,
            'file' => basename($file),
        ];
    }
}

ksort($items);

$inserted = 0;
$updated = 0;
$permInserted = 0;

$sort = 1000;

foreach ($items as $item) {

    $stmt = $db->prepare("
        SELECT id
        FROM rbac_menu_items
        WHERE url = ?
        LIMIT 1
    ");
    $stmt->execute([$item['url']]);
    $menuId = (int)$stmt->fetchColumn();

    if ($menuId <= 0) {

        $fields = [];
        $values = [];
        $params = [];

        $candidate = [
            'menu_key' => $item['menu_key'],
            'label' => $item['label'],
            'label_en' => $item['label'],
            'label_ar' => $item['label'],
            'url' => $item['url'],
            'parent_key' => 'sidebar',
            'sort_order' => $sort,
            'icon' => 'fa-circle',
            'is_active' => 1,
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s'),
        ];

        foreach ($candidate as $col => $val) {
            if (in_array($col, $menuCols, true)) {
                $fields[] = $col;
                $values[] = '?';
                $params[] = $val;
            }
        }

        $sql = "
            INSERT INTO rbac_menu_items
            (" . implode(',', $fields) . ")
            VALUES
            (" . implode(',', $values) . ")
        ";

        $db->prepare($sql)->execute($params);

        $menuId = (int)$db->lastInsertId();
        $inserted++;

    } else {

        $sets = [];
        $params = [];

        if (in_array('label', $menuCols, true)) {
            $sets[] = "label=?";
            $params[] = $item['label'];
        }

        if (in_array('label_en', $menuCols, true)) {
            $sets[] = "label_en=?";
            $params[] = $item['label'];
        }

        if (in_array('updated_at', $menuCols, true)) {
            $sets[] = "updated_at=?";
            $params[] = date('Y-m-d H:i:s');
        }

        if ($sets) {
            $params[] = $menuId;
            $db->prepare("
                UPDATE rbac_menu_items
                SET " . implode(',', $sets) . "
                WHERE id=?
            ")->execute($params);
            $updated++;
        }
    }

    $allowedRoles = $item['roles'];

    if (!$allowedRoles) {
        if (str_contains($item['url'], '/reviewer/')) {
            $allowedRoles = ['reviewer', 'super_admin', 'superadmin', 'admin'];
        } elseif (str_contains($item['url'], '/author/')) {
            $allowedRoles = ['author', 'super_admin', 'superadmin', 'admin'];
        } else {
            $allowedRoles = ['super_admin', 'superadmin', 'admin'];
        }
    }

    foreach ($allowedRoles as $roleCode) {

        if (!isset($roleMap[$roleCode])) {
            continue;
        }

        $roleId = $roleMap[$roleCode];

        $existsSql = "
            SELECT COUNT(*)
            FROM rbac_role_menu_permissions
            WHERE role_id=?
            AND menu_item_id=?
        ";

        $params = [$roleId, $menuId];

        if (in_array('conference_id', $permCols, true)) {
            $existsSql .= " AND conference_id=0";
        }

        $stmt = $db->prepare($existsSql);
        $stmt->execute($params);

        if ((int)$stmt->fetchColumn() > 0) {
            continue;
        }

        $fields = [];
        $values = [];
        $insertParams = [];

        $candidate = [
            'role_id' => $roleId,
            'menu_item_id' => $menuId,
            'conference_id' => 0,
            'can_view' => 1,
            'can_create' => 0,
            'can_update' => 0,
            'can_delete' => 0,
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s'),
        ];

        foreach ($candidate as $col => $val) {
            if (in_array($col, $permCols, true)) {
                $fields[] = $col;
                $values[] = '?';
                $insertParams[] = $val;
            }
        }

        $db->prepare("
            INSERT INTO rbac_role_menu_permissions
            (" . implode(',', $fields) . ")
            VALUES
            (" . implode(',', $values) . ")
        ")->execute($insertParams);

        $permInserted++;
    }

    $sort += 10;
}

echo "Links found: " . count($items) . PHP_EOL;
echo "Menu inserted: {$inserted}" . PHP_EOL;
echo "Menu updated: {$updated}" . PHP_EOL;
echo "Permissions inserted: {$permInserted}" . PHP_EOL;

echo "DONE\n";
