<?php 
header('Content-Type: application/json');

$tenant = $_REQUEST['tenant'] ?? '';
if ($tenant !== '' && file_exists('../../..' . $tenant . '/config.php')) {
    require_once('../../..' . $tenant . '/config.php');
}
if (file_exists('/config.php')) {
    require_once('/config.php');
}

$GLOBALS['con']->set_charset('utf8mb4');

function pmrResponse(string $status, string $message, array $extra = []): void
{
    echo json_encode(array_merge([
        'status' => $status,
        'message' => $message
    ], $extra));
    exit;
}

function pmrNextSort(mysqli $db, string $table, string $where = '', array $params = [], string $types = ''): int
{
    $sql = "SELECT COALESCE(MAX(sort_order), 0) + 1 AS next_sort FROM `$table`" . ($where !== '' ? " WHERE $where" : '');
    $stmt = $db->prepare($sql);
    if (!$stmt) {
        return 1;
    }
    if ($params) {
        $stmt->bind_param($types, ...$params);
    }
    $stmt->execute();
    $res = $stmt->get_result();
    $row = $res ? $res->fetch_assoc() : null;
    $stmt->close();
    return (int)($row['next_sort'] ?? 1);
}

function pmrSwapSort(mysqli $db, string $table, int $id, string $direction, string $scopeColumn = ''): bool
{
    $stmt = $db->prepare("SELECT * FROM `$table` WHERE `id` = ? LIMIT 1");
    $stmt->bind_param('i', $id);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();

    if (!$res || $res->num_rows < 1) {
        return false;
    }

    $current = $res->fetch_assoc();
    $currentSort = (int)$current['sort_order'];
    $scopeSql = '';
    $scopeParams = [];
    $scopeTypes = '';

    if ($scopeColumn !== '') {
        $scopeSql = " AND `$scopeColumn` = ?";
        $scopeParams[] = (int)$current[$scopeColumn];
        $scopeTypes .= 'i';
    }

    $operator = $direction === 'up' ? '<' : '>';
    $order = $direction === 'up' ? 'DESC' : 'ASC';
    $stmt = $db->prepare("SELECT `id`, `sort_order` FROM `$table` WHERE `sort_order` $operator ?$scopeSql ORDER BY `sort_order` $order LIMIT 1");
    $params = array_merge([$currentSort], $scopeParams);
    $stmt->bind_param('i' . $scopeTypes, ...$params);
    $stmt->execute();
    $swapRes = $stmt->get_result();
    $stmt->close();

    if (!$swapRes || $swapRes->num_rows < 1) {
        return false;
    }

    $swap = $swapRes->fetch_assoc();
    $swapId = (int)$swap['id'];
    $swapSort = (int)$swap['sort_order'];

    $db->begin_transaction();
    try {
        $stmt = $db->prepare("UPDATE `$table` SET `sort_order` = ? WHERE `id` = ?");
        $stmt->bind_param('ii', $swapSort, $id);
        $stmt->execute();
        $stmt->close();

        $stmt = $db->prepare("UPDATE `$table` SET `sort_order` = ? WHERE `id` = ?");
        $stmt->bind_param('ii', $currentSort, $swapId);
        $stmt->execute();
        $stmt->close();

        $db->commit();
        return true;
    } catch (\Throwable $e) {
        $db->rollback();
        return false;
    }
}

function pmrSwapQuestionSort(mysqli $db, int $id, string $direction): bool
{
    $stmt = $db->prepare("SELECT `id`, `section_id`, `group_id`, `sort_order` FROM `pmr_questions` WHERE `id` = ? LIMIT 1");
    $stmt->bind_param('i', $id);
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();

    if (!$res || $res->num_rows < 1) {
        return false;
    }

    $current = $res->fetch_assoc();
    $currentSort = (int)$current['sort_order'];
    $sectionId = (int)$current['section_id'];
    $groupId = $current['group_id'] === null ? null : (int)$current['group_id'];
    $operator = $direction === 'up' ? '<' : '>';
    $order = $direction === 'up' ? 'DESC' : 'ASC';

    if ($groupId === null) {
        $stmt = $db->prepare("
            SELECT `id`, `sort_order`
            FROM `pmr_questions`
            WHERE `section_id` = ? AND `group_id` IS NULL AND `sort_order` $operator ?
            ORDER BY `sort_order` $order
            LIMIT 1
        ");
        $stmt->bind_param('ii', $sectionId, $currentSort);
    } else {
        $stmt = $db->prepare("
            SELECT `id`, `sort_order`
            FROM `pmr_questions`
            WHERE `section_id` = ? AND `group_id` = ? AND `sort_order` $operator ?
            ORDER BY `sort_order` $order
            LIMIT 1
        ");
        $stmt->bind_param('iii', $sectionId, $groupId, $currentSort);
    }

    $stmt->execute();
    $swapRes = $stmt->get_result();
    $stmt->close();

    if (!$swapRes || $swapRes->num_rows < 1) {
        return false;
    }

    $swap = $swapRes->fetch_assoc();
    $swapId = (int)$swap['id'];
    $swapSort = (int)$swap['sort_order'];

    $db->begin_transaction();
    try {
        $stmt = $db->prepare("UPDATE `pmr_questions` SET `sort_order` = ? WHERE `id` = ?");
        $stmt->bind_param('ii', $swapSort, $id);
        $stmt->execute();
        $stmt->close();

        $stmt = $db->prepare("UPDATE `pmr_questions` SET `sort_order` = ? WHERE `id` = ?");
        $stmt->bind_param('ii', $currentSort, $swapId);
        $stmt->execute();
        $stmt->close();

        $db->commit();
        return true;
    } catch (\Throwable $e) {
        $db->rollback();
        return false;
    }
}

function pmrCleanInputTypes(string $json): array
{
    $allowed = ['yes', 'no', 'na', 'notes', 'textarea', 'text', 'numeric'];
    $decoded = json_decode($json, true);
    if (!is_array($decoded)) {
        return [];
    }

    $clean = [];
    foreach ($decoded as $type) {
        $type = strtolower(trim((string)$type));
        if (in_array($type, $allowed, true) && !in_array($type, $clean, true)) {
            $clean[] = $type;
        }
    }
    return $clean;
}

function pmrExecute(mysqli $db, string $sql, string $types = '', array $params = []): void
{
    $stmt = $db->prepare($sql);
    if (!$stmt) {
        throw new RuntimeException($db->error);
    }
    if ($types !== '') {
        $stmt->bind_param($types, ...$params);
    }
    if (!$stmt->execute()) {
        $error = $stmt->error;
        $stmt->close();
        throw new RuntimeException($error);
    }
    $stmt->close();
}

$FUNCTION = $_REQUEST['FUNCTION'] ?? '';

switch ($FUNCTION) {
    case 'saveSystemType':
        $id = (int)($_REQUEST['id'] ?? 0);
        $title = trim((string)($_REQUEST['title'] ?? ''));
        $status = !empty($_REQUEST['status']) ? 1 : 0;

        if ($title === '') {
            pmrResponse('error', 'System type title is required');
        }

        if ($id > 0) {
            $stmt = $GLOBALS['con']->prepare("UPDATE `pmr_system_types` SET `title` = ?, `status` = ? WHERE `id` = ?");
            $stmt->bind_param('sii', $title, $status, $id);
            $stmt->execute();
            $stmt->close();
            pmrResponse('success', 'System type updated');
        }

        $sortOrder = pmrNextSort($GLOBALS['con'], 'pmr_system_types');
        $stmt = $GLOBALS['con']->prepare("INSERT INTO `pmr_system_types` (`title`, `sort_order`, `status`) VALUES (?, ?, ?)");
        $stmt->bind_param('sii', $title, $sortOrder, $status);
        $stmt->execute();
        $stmt->close();
        pmrResponse('success', 'System type created');
        break;

    case 'deleteSystemType':
        $id = (int)($_REQUEST['id'] ?? 0);
        if ($id <= 0) {
            pmrResponse('error', 'Invalid system type');
        }
        $GLOBALS['con']->begin_transaction();
        try {
            pmrExecute($GLOBALS['con'], "
                DELETE q
                FROM `pmr_questions` q
                INNER JOIN `pmr_sections` s ON s.`id` = q.`section_id`
                WHERE s.`system_type_id` = ?
            ", 'i', [$id]);
            pmrExecute($GLOBALS['con'], "
                DELETE g
                FROM `pmr_groups` g
                INNER JOIN `pmr_sections` s ON s.`id` = g.`section_id`
                WHERE s.`system_type_id` = ?
            ", 'i', [$id]);
            pmrExecute($GLOBALS['con'], "DELETE FROM `pmr_sections` WHERE `system_type_id` = ?", 'i', [$id]);
            pmrExecute($GLOBALS['con'], "DELETE FROM `pmr_system_types` WHERE `id` = ?", 'i', [$id]);
            $GLOBALS['con']->commit();
        } catch (\Throwable $e) {
            $GLOBALS['con']->rollback();
            pmrResponse('error', 'System type could not be removed');
        }
        pmrResponse('success', 'System type removed');
        break;

    case 'moveSystemType':
        $id = (int)($_REQUEST['id'] ?? 0);
        $direction = ($_REQUEST['direction'] ?? '') === 'up' ? 'up' : 'down';
        if ($id <= 0 || !pmrSwapSort($GLOBALS['con'], 'pmr_system_types', $id, $direction)) {
            pmrResponse('warning', 'No further movement possible');
        }
        pmrResponse('success', 'System type order updated');
        break;

    case 'saveSection':
        $id = (int)($_REQUEST['id'] ?? 0);
        $systemTypeId = (int)($_REQUEST['system_type_id'] ?? 0);
        $title = trim((string)($_REQUEST['title'] ?? ''));
        $status = !empty($_REQUEST['status']) ? 1 : 0;

        if ($systemTypeId <= 0 || $title === '') {
            pmrResponse('error', 'System type and section title are required');
        }

        if ($id > 0) {
            $stmt = $GLOBALS['con']->prepare("UPDATE `pmr_sections` SET `system_type_id` = ?, `title` = ?, `status` = ? WHERE `id` = ?");
            $stmt->bind_param('isii', $systemTypeId, $title, $status, $id);
            $stmt->execute();
            $stmt->close();
            pmrResponse('success', 'Section updated');
        }

        $sortOrder = pmrNextSort($GLOBALS['con'], 'pmr_sections', '`system_type_id` = ?', [$systemTypeId], 'i');
        $stmt = $GLOBALS['con']->prepare("INSERT INTO `pmr_sections` (`system_type_id`, `title`, `sort_order`, `status`) VALUES (?, ?, ?, ?)");
        $stmt->bind_param('isii', $systemTypeId, $title, $sortOrder, $status);
        $stmt->execute();
        $stmt->close();
        pmrResponse('success', 'Section created');
        break;

    case 'deleteSection':
        $id = (int)($_REQUEST['id'] ?? 0);
        if ($id <= 0) {
            pmrResponse('error', 'Invalid section');
        }
        $GLOBALS['con']->begin_transaction();
        try {
            pmrExecute($GLOBALS['con'], "DELETE FROM `pmr_questions` WHERE `section_id` = ?", 'i', [$id]);
            pmrExecute($GLOBALS['con'], "DELETE FROM `pmr_groups` WHERE `section_id` = ?", 'i', [$id]);
            pmrExecute($GLOBALS['con'], "DELETE FROM `pmr_sections` WHERE `id` = ?", 'i', [$id]);
            $GLOBALS['con']->commit();
        } catch (\Throwable $e) {
            $GLOBALS['con']->rollback();
            pmrResponse('error', 'Section could not be removed');
        }
        pmrResponse('success', 'Section removed');
        break;

    case 'moveSection':
        $id = (int)($_REQUEST['id'] ?? 0);
        $direction = ($_REQUEST['direction'] ?? '') === 'up' ? 'up' : 'down';
        if ($id <= 0 || !pmrSwapSort($GLOBALS['con'], 'pmr_sections', $id, $direction, 'system_type_id')) {
            pmrResponse('warning', 'No further movement possible');
        }
        pmrResponse('success', 'Section order updated');
        break;

    case 'saveGroup':
        $id = (int)($_REQUEST['id'] ?? 0);
        $sectionId = (int)($_REQUEST['section_id'] ?? 0);
        $title = trim((string)($_REQUEST['title'] ?? ''));
        $status = !empty($_REQUEST['status']) ? 1 : 0;

        if ($sectionId <= 0 || $title === '') {
            pmrResponse('error', 'Section and group title are required');
        }

        if ($id > 0) {
            $stmt = $GLOBALS['con']->prepare("UPDATE `pmr_groups` SET `section_id` = ?, `title` = ?, `status` = ? WHERE `id` = ?");
            $stmt->bind_param('isii', $sectionId, $title, $status, $id);
            $stmt->execute();
            $stmt->close();
            pmrResponse('success', 'Group updated');
        }

        $sortOrder = pmrNextSort($GLOBALS['con'], 'pmr_groups', '`section_id` = ?', [$sectionId], 'i');
        $stmt = $GLOBALS['con']->prepare("INSERT INTO `pmr_groups` (`section_id`, `title`, `sort_order`, `status`) VALUES (?, ?, ?, ?)");
        $stmt->bind_param('isii', $sectionId, $title, $sortOrder, $status);
        $stmt->execute();
        $stmt->close();
        pmrResponse('success', 'Group created');
        break;

    case 'deleteGroup':
        $id = (int)($_REQUEST['id'] ?? 0);
        if ($id <= 0) {
            pmrResponse('error', 'Invalid group');
        }
        $GLOBALS['con']->begin_transaction();
        try {
            pmrExecute($GLOBALS['con'], "DELETE FROM `pmr_questions` WHERE `group_id` = ?", 'i', [$id]);
            pmrExecute($GLOBALS['con'], "DELETE FROM `pmr_groups` WHERE `id` = ?", 'i', [$id]);
            $GLOBALS['con']->commit();
        } catch (\Throwable $e) {
            $GLOBALS['con']->rollback();
            pmrResponse('error', 'Group could not be removed');
        }
        pmrResponse('success', 'Group removed');
        break;

    case 'moveGroup':
        $id = (int)($_REQUEST['id'] ?? 0);
        $direction = ($_REQUEST['direction'] ?? '') === 'up' ? 'up' : 'down';
        if ($id <= 0 || !pmrSwapSort($GLOBALS['con'], 'pmr_groups', $id, $direction, 'section_id')) {
            pmrResponse('warning', 'No further movement possible');
        }
        pmrResponse('success', 'Group order updated');
        break;

    case 'saveQuestion':
        $id = (int)($_REQUEST['id'] ?? 0);
        $sectionId = (int)($_REQUEST['section_id'] ?? 0);
        $groupId = (int)($_REQUEST['group_id'] ?? 0);
        $questionText = trim((string)($_REQUEST['question_text'] ?? ''));
        $inputTypes = pmrCleanInputTypes((string)($_REQUEST['input_types_json'] ?? '[]'));
        $status = !empty($_REQUEST['status']) ? 1 : 0;
        $groupParam = $groupId > 0 ? $groupId : null;

        if ($sectionId <= 0 || $questionText === '') {
            pmrResponse('error', 'Section and question text are required');
        }
        if (empty($inputTypes)) {
            pmrResponse('error', 'Select at least one input type');
        }

        $inputTypesJson = json_encode($inputTypes);

        if ($id > 0) {
            $stmt = $GLOBALS['con']->prepare("UPDATE `pmr_questions` SET `section_id` = ?, `group_id` = ?, `question_text` = ?, `input_types_json` = ?, `status` = ? WHERE `id` = ?");
            $stmt->bind_param('iissii', $sectionId, $groupParam, $questionText, $inputTypesJson, $status, $id);
            $stmt->execute();
            $stmt->close();
            pmrResponse('success', 'Question updated');
        }

        if ($groupId > 0) {
            $sortOrder = pmrNextSort($GLOBALS['con'], 'pmr_questions', '`section_id` = ? AND `group_id` = ?', [$sectionId, $groupId], 'ii');
        } else {
            $sortOrder = pmrNextSort($GLOBALS['con'], 'pmr_questions', '`section_id` = ? AND `group_id` IS NULL', [$sectionId], 'i');
        }

        $stmt = $GLOBALS['con']->prepare("INSERT INTO `pmr_questions` (`section_id`, `group_id`, `question_text`, `input_types_json`, `sort_order`, `status`) VALUES (?, ?, ?, ?, ?, ?)");
        $stmt->bind_param('iissii', $sectionId, $groupParam, $questionText, $inputTypesJson, $sortOrder, $status);
        $stmt->execute();
        $stmt->close();
        pmrResponse('success', 'Question created');
        break;

    case 'deleteQuestion':
        $id = (int)($_REQUEST['id'] ?? 0);
        if ($id <= 0) {
            pmrResponse('error', 'Invalid question');
        }
        $stmt = $GLOBALS['con']->prepare("DELETE FROM `pmr_questions` WHERE `id` = ?");
        $stmt->bind_param('i', $id);
        $stmt->execute();
        $stmt->close();
        pmrResponse('success', 'Question removed');
        break;

    case 'moveQuestion':
        $id = (int)($_REQUEST['id'] ?? 0);
        $direction = ($_REQUEST['direction'] ?? '') === 'up' ? 'up' : 'down';
        if ($id <= 0 || !pmrSwapQuestionSort($GLOBALS['con'], $id, $direction)) {
            pmrResponse('warning', 'No further movement possible');
        }
        pmrResponse('success', 'Question order updated');
        break;

    default:
        pmrResponse('error', 'Invalid function');
        break;
}
