PRAGMA foreign_keys = ON;

CREATE TABLE IF NOT EXISTS users (
    userID             TEXT    NOT NULL PRIMARY KEY,
    username           TEXT    NOT NULL UNIQUE,
    passwordHash       TEXT    NOT NULL,
    role               TEXT    NOT NULL CHECK(role IN ('admin','supervisor','coach')),
    entityID           TEXT    NOT NULL,
    mustChangePassword INTEGER NOT NULL DEFAULT 1,
    createdAt          INTEGER NOT NULL
);

CREATE TABLE IF NOT EXISTS admin (
    adminID  TEXT NOT NULL PRIMARY KEY,
    username TEXT NOT NULL,
    location TEXT NOT NULL DEFAULT ''
);

CREATE TABLE IF NOT EXISTS supervisor (
    supervisorID TEXT NOT NULL PRIMARY KEY,
    username     TEXT NOT NULL,
    location     TEXT NOT NULL DEFAULT ''
);

CREATE TABLE IF NOT EXISTS coach (
    coachID      TEXT NOT NULL PRIMARY KEY,
    supervisorID TEXT NOT NULL,
    username     TEXT NOT NULL,
    FOREIGN KEY(supervisorID) REFERENCES supervisor(supervisorID)
);

CREATE TABLE IF NOT EXISTS client (
    clientCode TEXT NOT NULL PRIMARY KEY,
    coachID    TEXT NOT NULL,
    archived   INTEGER NOT NULL DEFAULT 0,
    archivedAt INTEGER NOT NULL DEFAULT 0,
    FOREIGN KEY(coachID) REFERENCES coach(coachID)
);

CREATE TABLE IF NOT EXISTS questionnaire_category (
    categoryKey TEXT    NOT NULL PRIMARY KEY,
    label       TEXT    NOT NULL DEFAULT '',
    color       TEXT    NOT NULL DEFAULT '#64748b',
    orderIndex  INTEGER NOT NULL DEFAULT 0
);

CREATE TABLE IF NOT EXISTS questionnaire (
    questionnaireID    TEXT    NOT NULL PRIMARY KEY,
    name               TEXT    NOT NULL DEFAULT '',
    version            TEXT    NOT NULL DEFAULT '',
    state              TEXT    NOT NULL DEFAULT '',
    orderIndex         INTEGER NOT NULL DEFAULT 0,
    showPoints         INTEGER NOT NULL DEFAULT 0,
    conditionJson      TEXT    NOT NULL DEFAULT '{}',
    categoryKey        TEXT    NOT NULL DEFAULT '',
    structureRevision  INTEGER NOT NULL DEFAULT 1,
    structureChangedAt INTEGER NOT NULL DEFAULT 0
);

CREATE TABLE IF NOT EXISTS questionnaire_structure_snapshot (
    questionnaireID   TEXT    NOT NULL,
    structureRevision INTEGER NOT NULL,
    createdAt         INTEGER NOT NULL,
    manifestJson      TEXT    NOT NULL DEFAULT '{}',
    PRIMARY KEY (questionnaireID, structureRevision),
    FOREIGN KEY(questionnaireID) REFERENCES questionnaire(questionnaireID) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS question (
    questionID         TEXT    NOT NULL PRIMARY KEY,
    questionnaireID    TEXT    NOT NULL,
    defaultText        TEXT    NOT NULL DEFAULT '',
    type               TEXT    NOT NULL DEFAULT '',
    orderIndex         INTEGER NOT NULL DEFAULT 0,
    isRequired         INTEGER NOT NULL DEFAULT 0,
    configJson         TEXT    NOT NULL DEFAULT '{}',
    retiredAt          INTEGER NOT NULL DEFAULT 0,
    retiredInRevision  INTEGER NOT NULL DEFAULT 0,
    FOREIGN KEY(questionnaireID) REFERENCES questionnaire(questionnaireID)
);

CREATE TABLE IF NOT EXISTS answer_option (
    answerOptionID TEXT    NOT NULL PRIMARY KEY,
    questionID     TEXT    NOT NULL,
    defaultText    TEXT    NOT NULL DEFAULT '',
    points         INTEGER NOT NULL DEFAULT 0,
    orderIndex     INTEGER NOT NULL DEFAULT 0,
    nextQuestionId TEXT    NOT NULL DEFAULT '',
    retiredAt      INTEGER NOT NULL DEFAULT 0,
    FOREIGN KEY(questionID) REFERENCES question(questionID)
);

CREATE TABLE IF NOT EXISTS client_answer (
    clientCode     TEXT NOT NULL,
    questionID     TEXT NOT NULL,
    answerOptionID TEXT,
    freeTextValue  TEXT,
    numericValue   REAL,
    answeredAt     INTEGER,
    PRIMARY KEY (clientCode, questionID),
    FOREIGN KEY(clientCode)     REFERENCES client(clientCode),
    FOREIGN KEY(questionID)     REFERENCES question(questionID),
    FOREIGN KEY(answerOptionID) REFERENCES answer_option(answerOptionID)
);

CREATE TABLE IF NOT EXISTS completed_questionnaire (
    clientCode            TEXT    NOT NULL,
    questionnaireID       TEXT    NOT NULL,
    assignedByCoach       TEXT,
    status                TEXT    NOT NULL DEFAULT '',
    startedAt             INTEGER,
    completedAt           INTEGER,
    sumPoints             INTEGER,
    programCycleNumber    INTEGER,
    programSessionID      TEXT,
    programSessionNumber  INTEGER,
    PRIMARY KEY (clientCode, questionnaireID),
    FOREIGN KEY(clientCode)      REFERENCES client(clientCode),
    FOREIGN KEY(questionnaireID) REFERENCES questionnaire(questionnaireID),
    FOREIGN KEY(assignedByCoach) REFERENCES coach(coachID)
);

CREATE TABLE IF NOT EXISTS question_translation (
    questionID   TEXT NOT NULL,
    languageCode TEXT NOT NULL,
    text         TEXT NOT NULL DEFAULT '',
    PRIMARY KEY (questionID, languageCode),
    FOREIGN KEY(questionID) REFERENCES question(questionID)
);

CREATE TABLE IF NOT EXISTS answer_option_translation (
    answerOptionID TEXT NOT NULL,
    languageCode   TEXT NOT NULL,
    text           TEXT NOT NULL DEFAULT '',
    PRIMARY KEY (answerOptionID, languageCode),
    FOREIGN KEY(answerOptionID) REFERENCES answer_option(answerOptionID)
);

CREATE TABLE IF NOT EXISTS string_translation (
    stringKey    TEXT NOT NULL,
    languageCode TEXT NOT NULL,
    text         TEXT NOT NULL DEFAULT '',
    PRIMARY KEY (stringKey, languageCode)
);

CREATE TABLE IF NOT EXISTS language (
    languageCode TEXT NOT NULL PRIMARY KEY,
    name         TEXT NOT NULL DEFAULT ''
);

CREATE TABLE IF NOT EXISTS session (
    token     TEXT    NOT NULL PRIMARY KEY,
    userID    TEXT    NOT NULL,
    role      TEXT    NOT NULL,
    entityID  TEXT    NOT NULL DEFAULT '',
    createdAt INTEGER NOT NULL,
    expiresAt INTEGER NOT NULL,
    temp      INTEGER NOT NULL DEFAULT 0
);

CREATE TABLE IF NOT EXISTS questionnaire_submission (
    submissionID          TEXT    NOT NULL PRIMARY KEY,
    clientCode            TEXT    NOT NULL,
    questionnaireID       TEXT    NOT NULL,
    version               INTEGER NOT NULL,
    submittedAt           INTEGER NOT NULL,
    submittedByUserID     TEXT    NOT NULL DEFAULT '',
    submittedByRole       TEXT    NOT NULL DEFAULT '',
    assignedByCoach       TEXT,
    status                TEXT    NOT NULL DEFAULT '',
    startedAt             INTEGER,
    completedAt           INTEGER,
    sumPoints             INTEGER,
    programCycleNumber    INTEGER,
    programSessionID      TEXT,
    programSessionNumber  INTEGER,
    structureRevision     INTEGER NOT NULL DEFAULT 1,
    structureSnapshotJson TEXT    NOT NULL DEFAULT '{}',
    FOREIGN KEY(clientCode)        REFERENCES client(clientCode),
    FOREIGN KEY(questionnaireID)   REFERENCES questionnaire(questionnaireID),
    FOREIGN KEY(assignedByCoach)   REFERENCES coach(coachID),
    UNIQUE(clientCode, questionnaireID, version)
);

CREATE INDEX IF NOT EXISTS idx_submission_client_qn
    ON questionnaire_submission(clientCode, questionnaireID);
CREATE INDEX IF NOT EXISTS idx_submission_client_time
    ON questionnaire_submission(clientCode, submittedAt);

CREATE TABLE IF NOT EXISTS client_answer_submission (
    submissionID   TEXT NOT NULL,
    questionID     TEXT NOT NULL,
    answerOptionID TEXT,
    freeTextValue  TEXT,
    numericValue   REAL,
    answeredAt     INTEGER,
    PRIMARY KEY (submissionID, questionID),
    FOREIGN KEY(submissionID)      REFERENCES questionnaire_submission(submissionID) ON DELETE CASCADE,
    FOREIGN KEY(questionID)        REFERENCES question(questionID),
    FOREIGN KEY(answerOptionID)      REFERENCES answer_option(answerOptionID)
);

CREATE TABLE IF NOT EXISTS client_followup_note (
    clientCode      TEXT NOT NULL PRIMARY KEY,
    note            TEXT NOT NULL DEFAULT '',
    updatedByUserID TEXT NOT NULL DEFAULT '',
    updatedAt       INTEGER NOT NULL,
    FOREIGN KEY(clientCode) REFERENCES client(clientCode)
);

CREATE TABLE IF NOT EXISTS question_score_rule (
    ruleID     TEXT    NOT NULL PRIMARY KEY,
    questionID TEXT    NOT NULL,
    scopeKey   TEXT    NOT NULL DEFAULT '',
    levelKey   TEXT    NOT NULL,
    points     INTEGER NOT NULL DEFAULT 0,
    FOREIGN KEY(questionID) REFERENCES question(questionID) ON DELETE CASCADE,
    UNIQUE(questionID, scopeKey, levelKey)
);

CREATE INDEX IF NOT EXISTS idx_score_rule_question
    ON question_score_rule(questionID);

CREATE TABLE IF NOT EXISTS scoring_profile (
    profileID   TEXT    NOT NULL PRIMARY KEY,
    name        TEXT    NOT NULL DEFAULT '',
    description TEXT    NOT NULL DEFAULT '',
    isActive    INTEGER NOT NULL DEFAULT 1,
    greenMin    INTEGER NOT NULL DEFAULT 0,
    greenMax    INTEGER NOT NULL DEFAULT 12,
    yellowMin   INTEGER NOT NULL DEFAULT 13,
    yellowMax   INTEGER NOT NULL DEFAULT 36,
    redMin      INTEGER NOT NULL DEFAULT 37,
    createdAt   INTEGER NOT NULL DEFAULT 0,
    updatedAt   INTEGER NOT NULL DEFAULT 0
);

CREATE TABLE IF NOT EXISTS scoring_profile_questionnaire (
    profileID       TEXT    NOT NULL,
    questionnaireID TEXT    NOT NULL,
    weight          REAL    NOT NULL DEFAULT 1.0,
    orderIndex      INTEGER NOT NULL DEFAULT 0,
    PRIMARY KEY (profileID, questionnaireID),
    FOREIGN KEY(profileID)       REFERENCES scoring_profile(profileID) ON DELETE CASCADE,
    FOREIGN KEY(questionnaireID) REFERENCES questionnaire(questionnaireID) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS client_scoring_profile_result (
    clientCode            TEXT NOT NULL,
    profileID             TEXT NOT NULL,
    weightedTotal         REAL NOT NULL DEFAULT 0,
    band                  TEXT NOT NULL DEFAULT '',
    computedAt            INTEGER NOT NULL DEFAULT 0,
    questionnaireSnapshot TEXT NOT NULL DEFAULT '{}',
    coachBand             TEXT NOT NULL DEFAULT '',
    coachReviewedAt       INTEGER NOT NULL DEFAULT 0,
    coachReviewedByUserID TEXT NOT NULL DEFAULT '',
    PRIMARY KEY (clientCode, profileID),
    FOREIGN KEY(clientCode) REFERENCES client(clientCode) ON DELETE CASCADE,
    FOREIGN KEY(profileID)  REFERENCES scoring_profile(profileID) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_client_profile_result_profile
    ON client_scoring_profile_result(profileID);

CREATE TABLE IF NOT EXISTS program_session (
    sessionID     TEXT    NOT NULL PRIMARY KEY,
    name          TEXT    NOT NULL DEFAULT '',
    description   TEXT    NOT NULL DEFAULT '',
    sessionNumber INTEGER NOT NULL DEFAULT 1,
    orderIndex    INTEGER NOT NULL DEFAULT 0,
    isActive      INTEGER NOT NULL DEFAULT 1,
    createdAt     INTEGER NOT NULL DEFAULT 0,
    updatedAt     INTEGER NOT NULL DEFAULT 0
);

CREATE TABLE IF NOT EXISTS program_session_questionnaire (
    sessionID       TEXT NOT NULL,
    questionnaireID TEXT NOT NULL,
    orderIndex      INTEGER NOT NULL DEFAULT 0,
    PRIMARY KEY (sessionID, questionnaireID),
    FOREIGN KEY(sessionID) REFERENCES program_session(sessionID) ON DELETE CASCADE,
    FOREIGN KEY(questionnaireID) REFERENCES questionnaire(questionnaireID) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_program_session_order
    ON program_session(orderIndex, sessionNumber);

CREATE TABLE IF NOT EXISTS client_program_cycle (
    clientCode     TEXT NOT NULL PRIMARY KEY,
    cycleNumber    INTEGER NOT NULL DEFAULT 1,
    cycleStartedAt INTEGER NOT NULL DEFAULT 0,
    updatedAt      INTEGER NOT NULL DEFAULT 0,
    FOREIGN KEY(clientCode) REFERENCES client(clientCode) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS client_session_schedule (
    clientCode           TEXT NOT NULL PRIMARY KEY,
    scheduledDate        TEXT NOT NULL,
    programCycleNumber   INTEGER NOT NULL,
    programSessionNumber INTEGER NOT NULL,
    programSessionID     TEXT,
    updatedAt            INTEGER NOT NULL DEFAULT 0,
    FOREIGN KEY(clientCode) REFERENCES client(clientCode) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_client_session_schedule_date
    ON client_session_schedule(scheduledDate);
