<?php
/**
 * Scoring profiles CRUD (weighted multi-questionnaire Green/Yellow/Red bands).
 */

require_once __DIR__ . '/../lib/scoring.php';

$tokenRec = require_valid_token_web();

switch ($method) {
case 'GET':
    try {
        [$pdo, $tmpDb, $lockFp] = qdb_open_read_or_fail();
        $profileID = trim($_GET['id'] ?? '');
        if ($profileID !== '') {
            $profile = qdb_get_scoring_profile($pdo, $profileID);
            qdb_discard($tmpDb, $lockFp);
            if (!$profile) {
                json_error('NOT_FOUND', 'Scoring profile not found', 404);
            }
            json_success(['profile' => $profile]);
        }
        json_success(['profiles' => qdb_list_scoring_profiles($pdo)]);
        qdb_discard($tmpDb, $lockFp);
    } catch (Throwable $e) {
        qdb_handler_fail($e, 'List scoring profiles', null, $tmpDb ?? null, $lockFp ?? null);
    }
    break;

case 'POST':
    require_role(['admin', 'supervisor'], $tokenRec);
    $body = read_json_body();
    $name = trim($body['name'] ?? '');
    if ($name === '') {
        json_error('BAD_REQUEST', 'name is required', 400);
    }
    $bands = qdb_parse_scoring_bands_body($body);
    $bandErr = qdb_validate_scoring_bands($bands);
    if ($bandErr !== null) {
        json_error('INVALID_FIELD', $bandErr, 400);
    }
    $members = qdb_parse_profile_questionnaires($body['questionnaires'] ?? []);
    if ($members === []) {
        json_error('INVALID_FIELD', 'At least one questionnaire is required', 400);
    }
    $processCompleteBands = qdb_parse_process_complete_bands($body['processCompleteBands'] ?? []);
    try {
        [$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
        $profileID = bin2hex(random_bytes(16));
        $now = time();
        $pdo->prepare(
            'INSERT INTO scoring_profile (profileID, name, description, isActive,
             greenMin, greenMax, yellowMin, yellowMax, redMin, processCompleteBands, createdAt, updatedAt)
             VALUES (:id, :name, :desc, :act, :gmin, :gmax, :ymin, :ymax, :rmin, :pcb, :ca, :ua)'
        )->execute([
            ':id'   => $profileID,
            ':name' => $name,
            ':desc' => trim($body['description'] ?? ''),
            ':act'  => !empty($body['isActive']) ? 1 : 0,
            ':gmin' => $bands['greenMin'],
            ':gmax' => $bands['greenMax'],
            ':ymin' => $bands['yellowMin'],
            ':ymax' => $bands['yellowMax'],
            ':rmin' => $bands['redMin'],
            ':pcb'  => qdb_encode_process_complete_bands($processCompleteBands),
            ':ca'   => $now,
            ':ua'   => $now,
        ]);
        qdb_sync_profile_questionnaires($pdo, $profileID, $members);
        qdb_recompute_all_profiles_after_change($pdo);
        qdb_save($tmpDb, $lockFp);
        json_success(['profile' => qdb_get_scoring_profile($pdo, $profileID)]);
    } catch (Throwable $e) {
        qdb_handler_fail($e, 'Create scoring profile', $pdo ?? null, $tmpDb ?? null, $lockFp ?? null);
    }
    break;

case 'PUT':
    require_role(['admin', 'supervisor'], $tokenRec);
    $body = read_json_body();
    $profileID = trim($body['profileID'] ?? '');
    if ($profileID === '') {
        json_error('BAD_REQUEST', 'profileID is required', 400);
    }
    try {
        [$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
        $existing = qdb_get_scoring_profile($pdo, $profileID);
        if (!$existing) {
            qdb_discard($tmpDb, $lockFp);
            json_error('NOT_FOUND', 'Scoring profile not found', 404);
        }
        $name = trim($body['name'] ?? $existing['name']);
        $bands = qdb_normalize_scoring_bands(array_merge($existing, $body));
        $bandErr = qdb_validate_scoring_bands($bands);
        if ($bandErr !== null) {
            qdb_discard($tmpDb, $lockFp);
            json_error('INVALID_FIELD', $bandErr, 400);
        }
        $members = isset($body['questionnaires'])
            ? qdb_parse_profile_questionnaires($body['questionnaires'])
            : null;
        if ($members !== null && $members === []) {
            qdb_discard($tmpDb, $lockFp);
            json_error('INVALID_FIELD', 'At least one questionnaire is required', 400);
        }
        $processCompleteBands = array_key_exists('processCompleteBands', $body)
            ? qdb_parse_process_complete_bands($body['processCompleteBands'])
            : qdb_row_process_complete_bands($existing);
        $pdo->prepare(
            'UPDATE scoring_profile SET name = :name, description = :desc, isActive = :act,
             greenMin = :gmin, greenMax = :gmax, yellowMin = :ymin, yellowMax = :ymax, redMin = :rmin,
             processCompleteBands = :pcb, updatedAt = :ua WHERE profileID = :id'
        )->execute([
            ':name' => $name,
            ':desc' => trim($body['description'] ?? $existing['description']),
            ':act'  => isset($body['isActive']) ? (!empty($body['isActive']) ? 1 : 0) : $existing['isActive'],
            ':gmin' => $bands['greenMin'],
            ':gmax' => $bands['greenMax'],
            ':ymin' => $bands['yellowMin'],
            ':ymax' => $bands['yellowMax'],
            ':rmin' => $bands['redMin'],
            ':pcb'  => qdb_encode_process_complete_bands($processCompleteBands),
            ':ua'   => time(),
            ':id'   => $profileID,
        ]);
        if ($members !== null) {
            qdb_sync_profile_questionnaires($pdo, $profileID, $members);
        }
        qdb_recompute_all_profiles_after_change($pdo, $profileID);
        qdb_save($tmpDb, $lockFp);
        json_success(['profile' => qdb_get_scoring_profile($pdo, $profileID)]);
    } catch (Throwable $e) {
        qdb_handler_fail($e, 'Update scoring profile', $pdo ?? null, $tmpDb ?? null, $lockFp ?? null);
    }
    break;

case 'DELETE':
    require_role(['admin', 'supervisor'], $tokenRec);
    $body = read_json_body();
    $profileID = trim($body['profileID'] ?? '');
    if ($profileID === '') {
        json_error('BAD_REQUEST', 'profileID is required', 400);
    }
    try {
        [$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
        $pdo->prepare('DELETE FROM scoring_profile WHERE profileID = :id')->execute([':id' => $profileID]);
        qdb_save($tmpDb, $lockFp);
        json_success(['deleted' => true]);
    } catch (Throwable $e) {
        qdb_handler_fail($e, 'Delete scoring profile', $pdo ?? null, $tmpDb ?? null, $lockFp ?? null);
    }
    break;

default:
    json_error('METHOD_NOT_ALLOWED', 'Method not allowed', 405);
}

/**
 * @return list<array{questionnaireID: string, weight: float, orderIndex: int}>
 */
function qdb_parse_profile_questionnaires(array $rows): array {
    $out = [];
    $idx = 0;
    foreach ($rows as $row) {
        if (!is_array($row)) {
            continue;
        }
        $qnID = trim((string)($row['questionnaireID'] ?? ''));
        if ($qnID === '') {
            continue;
        }
        $weight = (float)($row['weight'] ?? 1.0);
        if ($weight <= 0) {
            $weight = 1.0;
        }
        $out[] = [
            'questionnaireID' => $qnID,
            'weight'          => $weight,
            'orderIndex'      => (int)($row['orderIndex'] ?? $idx),
        ];
        $idx++;
    }
    return $out;
}

function qdb_sync_profile_questionnaires(PDO $pdo, string $profileID, array $members): void {
    $pdo->prepare('DELETE FROM scoring_profile_questionnaire WHERE profileID = :pid')
        ->execute([':pid' => $profileID]);
    $ins = $pdo->prepare(
        'INSERT INTO scoring_profile_questionnaire (profileID, questionnaireID, weight, orderIndex)
         VALUES (:pid, :qn, :w, :o)'
    );
    foreach ($members as $m) {
        $ins->execute([
            ':pid' => $profileID,
            ':qn'  => $m['questionnaireID'],
            ':w'   => $m['weight'],
            ':o'   => $m['orderIndex'],
        ]);
    }
}

function qdb_recompute_all_profiles_after_change(PDO $pdo, ?string $profileID = null): void {
    $clients = $pdo->query('SELECT DISTINCT clientCode FROM completed_questionnaire WHERE status = \'completed\'')
        ->fetchAll(PDO::FETCH_COLUMN);
    foreach ($clients as $clientCode) {
        qdb_recompute_profile_scores_for_client($pdo, (string)$clientCode);
    }
}
