--liquibase formatted sql

--changeset reya:users_table runInTransaction:false
CREATE TABLE IF NOT EXISTS users
(
    id         UUID        NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(),
    is_admin   BOOLEAN     NOT NULL             DEFAULT FALSE,
    created_at TIMESTAMPTZ NOT NULL             DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL             DEFAULT now(),
    active_at  TIMESTAMPTZ NULL                 DEFAULT NULL,
    FAMILY essentials (id, is_admin),
    FAMILY timestamps (created_at, updated_at, active_at)
);
--rollback DROP TABLE IF EXISTS users;

--changeset reya:battle_types_table runInTransaction:false
CREATE TABLE IF NOT EXISTS battle_types
(
    id            INT    NOT NULL PRIMARY KEY,
    name          STRING NOT NULL UNIQUE,
    emoji         STRING NOT NULL UNIQUE,
    color         STRING NOT NULL,
    display_order INT    NOT NULL,
    immunities    INT[]  NOT NULL DEFAULT '{}',
    resistances   INT[]  NOT NULL DEFAULT '{}',
    weaknesses    INT[]  NOT NULL DEFAULT '{}'
);
--rollback DROP TABLE IF EXISTS battle_types;

--changeset reya:battle_types_values runInTransaction:true
INSERT INTO battle_types (id, name, emoji, color, display_order)
VALUES (0, 'Basic', '🔲', '', 0),
       (1, 'Sassy', '🔥', '', 1),
       (2, 'Gentle', '💙', '', 2),
       (3, 'Sexy', '💋', '', 3),
       (4, 'Muscle', '💪', '', 4),
       (5, 'Glam', '✨', '', 5),
       (6, 'Punk', '🎸', '', 6),
       (7, 'Glutton', '🍗', '', 7),
       (8, 'Dumb', '🪨', '', 8),
       (9, 'Drone', '🤖', '', 9),
       (10, 'Spooky', '👻', '', 10),
       (11, 'Lively', '🎉', '', 11),
       (12, 'Smart', '🧠', '', 12),
       (13, 'Cool', '🧊', '', 13),
       (14, 'Bully', '😈', '', 14),
       (15, 'Mythic', '🔱', '', 15),
       (16, 'Toy', '🧸', '', 16),
       (17, 'Cute', '🌺', '', 17)
ON CONFLICT DO NOTHING;
--rollback DELETE FROM battle_types WHERE id in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)

--changeset reya:difficulties_table runInTransaction:false
CREATE TABLE IF NOT EXISTS difficulties
(
    id                          INT     NOT NULL PRIMARY KEY,
    name                        STRING  NOT NULL UNIQUE,
    emoji                       STRING  NOT NULL UNIQUE,
    short_description           STRING  NOT NULL,
    long_description            STRING  NOT NULL,
    display_order               INT     NOT NULL,
    allow_digestion             BOOLEAN NOT NULL DEFAULT true,
    regenerate_talent           BOOLEAN NOT NULL DEFAULT false,
    reformation_health_percent  FLOAT   NOT NULL DEFAULT 100,
    reformation_stamina_percent FLOAT   NOT NULL DEFAULT 100,
    lose_proficiency_percent    FLOAT   NOT NULL DEFAULT 0,
    lose_exp_percent            FLOAT   NOT NULL DEFAULT 0,
    lose_money_percent          FLOAT   NOT NULL DEFAULT 0
);
--rollback DROP TABLE IF EXISTS difficulties;

--changeset reya:difficulties_values runInTransaction:true
INSERT INTO difficulties
(id, name, emoji, short_description, long_description, display_order, allow_digestion, regenerate_talent,
 reformation_health_percent, reformation_stamina_percent, lose_proficiency_percent, lose_exp_percent,
 lose_money_percent)
VALUES (0, 'Indigestible', '🔰',
        'You can''t be digested. Stomachs just make you sleepy, and you always come out none the worse for wear.',
        'Stomachs have no effect on you. When your health is reduced to 0, you simply become tired and drift off to '
            ||
        'sleep. You don''t need to be reformed after battles when this happens, and you won''t lose anything for '
            || 'falling asleep this way. You''ll be ready to go right away as soon as you''re released!'
            || e'\n\n'
            || 'Suitable for players who play with the Pred Only or Spectator preferences, or who don''t want their '
            || 'character to die even temporarily.',
        0, false, false, 100, 100, 0, 0, 0),
       (1, 'Very Safe', '☀',
        'You''ll be completely safe. The only downsides to being digested? Inconvenience. And smug predators.',
        'Reformation is a cakewalk for you. You can be digested, but you can reform after battle with no penalties '
            || 'of any kind. Your body and mind are completely unaffected by the visit to someone else''s gut.'
            || e'\n\n'
            || 'Reformation leaves you a little bit weary, but in good health.'
            || e'\n\n'
            || 'Suitable for players who prefer a digestive end, but don''t want to lose any progress.',
        1, true, false, 100, 90, 0, 0, 0),
       (2, 'Safe', '🌤',
        'There''s a small price to being digested, but you didn''t think cheating death would be free, right?',
        'Digestion takes a little bit of a toll on your body and mind. And while you do come back, you don''t come '
            || 'back _quite_ the way you left.'
            || 'Your proficiencies will drop by 10% as a little of what you''ve taken from your past exploits fades '
            || 'from you. You''ll also lose 10% of your money as a cost for the reformation process.'
            || e'\n\n'
            || 'Reformation leaves you a bit weakened and fairly drowsy. You should rest a bit before continuing.'
            || e'\n\n'
            || 'Suitable for players who want to add a little risk to being digested, but don''t want to lose levels.',
        2, true, false, 90, 75, 10, 0, 10),
       (3, 'Risky', '🌥',
        'Reformation is a painful experience. It''s no laughing matter to be digested, so watch your back.',
        'Digestion is no walk in the park for you. When you come back, you leave some of yourself in the predator who '
            || 'turned you from a person to a snack. Your proficiencies drop by 25% as some of what you''ve taken from '
            || 'your past conquests fades from you, and your talents will be re-randomized, as the process of '
            || 'reformation is more art than science and your body and mind will not be quite the same. You''ll also '
            || 'lose 25% of your money as the cost of returning from being belly paunch. Worst of all, you''ll lose '
            || '10% of your experience points as your memories are clouded by your brush with fatality.'
            || e'\n\n'
            || ''
            || e'\n\n'
            || 'Suitable for players who want a balance between risk and maintaining their progress.',
        3, true, true, 25, 10, 25),
       (4, 'Dangerous', '🌦',
        'Digestion pushes your',
        'Digestion is something to be avoided at all costs. You''ll lose half your money, your stats will have atrophied, and you''ll lose some of your memories.',
        4, true, true, 50, 25, 50),
       (5, 'Very Dangerous', '🌧', '',
        'Being a meal is not just humiliating - it''s a nightmare. You''re lucky you get to hold on to anything.',
        5, true, true, 90, 50, 90),
       (6, 'Extremely Dangerous', '⛈', '',
        'If you get devoured and you don''t get out, you''ll lose just about everything. Be very, very careful...',
        6, true, true, 100, 100, 100)
ON CONFLICT DO NOTHING;
--rollback DELETE FROM difficulties WHERE id IN (0, 1, 2, 3, 4, 5, 6, 7);

--changeset reya:preferences_table runInTransaction:false
CREATE TABLE IF NOT EXISTS preferences
(
    id                INT     NOT NULL PRIMARY KEY,
    name              STRING  NOT NULL UNIQUE,
    emoji             STRING  NOT NULL UNIQUE,
    short_description STRING  NOT NULL,
    long_description  STRING  NOT NULL,
    display_order     INT     NOT NULL,
    can_use_vore      BOOLEAN NOT NULL,
    can_receive_vore  BOOLEAN NOT NULL
);
--rollback DROP TABLE IF EXISTS preferences;

--changeset reya:preferences_values runInTransaction:true
INSERT INTO preferences (id, name, emoji, short_description, long_description, display_order, can_use_vore,
                         can_receive_vore)
VALUES (0, 'Observer', '', 'You can neither eat nor be eaten.', '', 0, false, false),
       (1, 'Prey Only', '', 'You can only be eaten, not eat.', '', 1, false, true),
       (2, 'Pred Only', '', 'You can only eat, not be eaten.', '', 2, true, false),
       (3, 'Switch', '', 'You can both eat and be eaten.', '', 3, true, true)
ON CONFLICT DO NOTHING;
--rollback DELETE FROM preferences WHERE id IN (0, 1, 2, 3);

--changeset reya:pronouns_table runInTransaction:false
CREATE TABLE IF NOT EXISTS pronouns
(
    id             INT     NOT NULL PRIMARY KEY,
    default_gender STRING  NOT NULL,
    pronouns       STRING  NOT NULL UNIQUE,
    display_order  INT     NOT NULL,
    use_plural     BOOLEAN NOT NULL,
    subjective     STRING  NOT NULL,
    adjective      STRING  NOT NULL,
    possessive     STRING  NOT NULL,
    reflexive      STRING  NOT NULL,
    objective      STRING  NOT NULL
);
--rollback DROP TABLE IF EXISTS pronouns;

--changeset reya:pronouns_values runInTransaction:true
INSERT INTO pronouns (id, default_gender, pronouns, display_order, use_plural, subjective, adjective, possessive,
                      reflexive, objective)
VALUES (0, 'Genderless', 'none', 0, false, '@@', '@@''s', '@@''s', '@@''s self', '@@'),
       (1, 'Female', 'she/her', 1, false, 'she', 'her', 'hers', 'herself', 'her'),
       (2, 'Non-binary', 'they/them', 2, true, 'they', 'their', 'theirs', 'themself', 'them'),
       (3, 'Male', 'he/him', 3, false, 'he', 'his', 'his', 'himself', 'him'),
       (4, 'Genderless', 'it/its', 4, false, 'it', 'its', 'its', 'itself', 'it'),
       (5, 'Herm', 'shi/hir', 5, false, 'shi', 'hir', 'hirs', 'hirself', 'hir'),
       (6, 'Non-binary', 'ae/aer', 6, false, 'ae', 'aer', 'aers', 'aerself', 'aer'),
       (7, 'Non-binary', 'fae/faer', 7, false, 'fae', 'faer', 'faers', 'faerself', 'faer'),
       (8, 'Non-binary', 'e/em', 8, false, 'e', 'eir', 'eirs', 'emself', 'em'),
       (9, 'Non-binary', 'ey/em', 9, false, 'ey', 'eir', 'eirs', 'emself', 'em'),
       (10, 'Non-binary', 'per/per', 10, false, 'per', 'pers', 'pers', 'perself', 'per'),
       (11, 'Non-binary', 've/ver', 11, false, 've', 'vis', 'vis', 'verself', 'ver'),
       (12, 'Non-binary', 'xe/xem', 12, false, 'xe', 'xyr', 'xyrs', 'xemself', 'xem'),
       (13, 'Non-binary', 'ze/hir', 13, false, 'ze', 'hir', 'hirs', 'hirself', 'hir'),
       (14, 'Non-binary', 'zie/hir', 14, false, 'zie', 'hir', 'hirs', 'hirself', 'hir'),
       (15, 'Non-binary', 'zie/zim', 15, false, 'zie', 'zir', 'zis', 'zieself', 'zim'),
       (16, 'Non-binary', 'sie/sie', 16, false, 'sie', 'hir', 'hirs', 'hirself', 'sie'),
       (17, 'Non-binary', 'te/ter', 17, false, 'te', 'tem', 'ters', 'terself', 'ter')
ON CONFLICT DO NOTHING;
--rollback DELETE FROM pronouns WHERE id IN (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);

--changeset reya:characters_table runInTransaction:false
CREATE TABLE IF NOT EXISTS characters
(
    id                     UUID   NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id                UUID   NOT NULL REFERENCES users (id) ON DELETE CASCADE,
    name                   STRING NOT NULL,
    discriminator          INT    NULL                 DEFAULT NULL,
    title                  STRING NOT NULL,
    profile                STRING NOT NULL,
    pronouns_id            INT    NOT NULL REFERENCES pronouns (id) ON DELETE RESTRICT,
    gender_name            STRING NOT NULL,
    difficulty_id          INT    NOT NULL REFERENCES difficulties (id) ON DELETE RESTRICT,
    preference_id          INT    NOT NULL REFERENCES preferences (id) ON DELETE RESTRICT,
    battle_type1_id        INT    NOT NULL REFERENCES battle_types (id) ON DELETE RESTRICT,
    battle_type2_id        INT    NOT NULL REFERENCES battle_types (id) ON DELETE RESTRICT,
    experience             INT    NOT NULL             DEFAULT 0,
    money                  INT    NOT NULL             DEFAULT 0,

    -- stats: base
    base_confidence        INT    NOT NULL             DEFAULT 70,
    base_health            INT    NOT NULL             DEFAULT 70,
    base_stamina           INT    NOT NULL             DEFAULT 70,
    base_brawn             INT    NOT NULL             DEFAULT 70,
    base_durability        INT    NOT NULL             DEFAULT 70,
    base_intensity         INT    NOT NULL             DEFAULT 70,
    base_resilience        INT    NOT NULL             DEFAULT 70,
    base_speed             INT    NOT NULL             DEFAULT 70,
    -- stats: banked talent points
    min_confidence_talent  INT    NOT NULL             DEFAULT 0,
    min_health_talent      INT    NOT NULL             DEFAULT 0,
    min_stamina_talent     INT    NOT NULL             DEFAULT 0,
    min_brawn_talent       INT    NOT NULL             DEFAULT 0,
    min_durability_talent  INT    NOT NULL             DEFAULT 0,
    min_intensity_talent   INT    NOT NULL             DEFAULT 0,
    min_resilience_talent  INT    NOT NULL             DEFAULT 0,
    min_speed_talent       INT    NOT NULL             DEFAULT 0,
    -- stats: current talent points
    confidence_talent      INT    NOT NULL             DEFAULT floor(random() * 32)::INT, --min_confidence_talent + floor(random() * (32 - min_confidence_talent)),
    health_talent          INT    NOT NULL             DEFAULT floor(random() * 32)::INT, --min_health_talent + floor(random() * (32 - min_health_talent)),
    stamina_talent         INT    NOT NULL             DEFAULT floor(random() * 32)::INT, --min_stamina_talent + floor(random() * (32 - min_stamina_talent)),
    brawn_talent           INT    NOT NULL             DEFAULT floor(random() * 32)::INT, --min_brawn_talent + floor(random() * (32 - min_brawn_talent)),
    durability_talent      INT    NOT NULL             DEFAULT floor(random() * 32)::INT, --min_durability_talent + floor(random() * (32 - min_durability_talent)),
    intensity_talent       INT    NOT NULL             DEFAULT floor(random() * 32)::INT, --min_intensity_talent + floor(random() * (32 - min_intensity_talent)),
    resilience_talent      INT    NOT NULL             DEFAULT floor(random() * 32)::INT, --min_resilience_talent + floor(random() * (32 - min_resilience_talent)),
    speed_talent           INT    NOT NULL             DEFAULT floor(random() * 32)::INT, --min_speed_talent + floor(random() * (32 - min_speed_talent)),
    -- stats: current proficiency points
    confidence_proficiency INT    NOT NULL             DEFAULT 0,
    health_proficiency     INT    NOT NULL             DEFAULT 0,
    stamina_proficiency    INT    NOT NULL             DEFAULT 0,
    brawn_proficiency      INT    NOT NULL             DEFAULT 0,
    durability_proficiency INT    NOT NULL             DEFAULT 0,
    intensity_proficiency  INT    NOT NULL             DEFAULT 0,
    resilience_proficiency INT    NOT NULL             DEFAULT 0,
    speed_proficiency      INT    NOT NULL             DEFAULT 0,

    UNIQUE (user_id, name, discriminator),
    FAMILY character_base (id, user_id, name, title, profile, pronouns_id, battle_type1_id, battle_type2_id,
                           base_confidence,
                           base_health,
                           base_stamina, base_brawn, base_durability, base_intensity, base_resilience, base_speed),
    FAMILY character_reformation_stats (min_confidence_talent, min_health_talent, min_stamina_talent, min_brawn_talent,
                                        min_durability_talent, min_intensity_talent, min_resilience_talent,
                                        min_speed_talent,
                                        confidence_talent, health_talent, stamina_talent, brawn_talent,
                                        durability_talent, intensity_talent, resilience_talent, speed_talent),
    FAMILY character_live_stats (difficulty_id, preference_id, experience, money, confidence_proficiency,
                                 health_proficiency, stamina_proficiency, brawn_proficiency, durability_proficiency,
                                 intensity_proficiency, resilience_proficiency, speed_proficiency)
);
--rollback DROP TABLE IF EXISTS characters;

--changeset reya:character_creation_table runInTransaction:false
CREATE TABLE IF NOT EXISTS character_creation
(
    user_id         UUID   NOT NULL REFERENCES users (id) ON DELETE CASCADE,
    character_id    UUID   NULL REFERENCES characters (id) ON DELETE CASCADE,
    name            STRING NULL,
    title           STRING NULL,
    profile         STRING NULL,
    pronouns_id     INT    NULL REFERENCES pronouns (id) ON DELETE RESTRICT,
    gender_name     STRING NULL,
    difficulty_id   INT    NULL REFERENCES difficulties (id) ON DELETE RESTRICT,
    preference_id   INT    NULL REFERENCES preferences (id) ON DELETE RESTRICT,
    battle_type1_id INT    NULL REFERENCES battle_types (id) ON DELETE RESTRICT,
    battle_type2_id INT    NULL REFERENCES battle_types (id) ON DELETE RESTRICT,
    base_confidence INT    NULL DEFAULT 70,
    base_health     INT    NULL DEFAULT 70,
    base_stamina    INT    NULL DEFAULT 70,
    base_brawn      INT    NULL DEFAULT 70,
    base_durability INT    NULL DEFAULT 70,
    base_intensity  INT    NULL DEFAULT 70,
    base_resilience INT    NULL DEFAULT 70,
    base_speed      INT    NULL DEFAULT 70,

    PRIMARY KEY (user_id, character_id)
);
--rollback DROP TABLE IF EXISTS character_creation;

--changeset reya:userDefaultDifficultyPreferenceGender
ALTER TABLE users
    ADD COLUMN default_pronouns_id   INT    NULL REFERENCES pronouns (id) ON DELETE RESTRICT     DEFAULT NULL
        CREATE IF NOT EXISTS FAMILY character_defaults,
    ADD COLUMN default_gender_name   STRING NULL                                                 DEFAULT NULL
        FAMILY character_defaults,
    ADD COLUMN default_difficulty_id INT    NULL REFERENCES difficulties (id) ON DELETE RESTRICT DEFAULT NULL
        FAMILY character_defaults,
    ADD COLUMN default_preference_id INT    NULL REFERENCES preferences (id) ON DELETE RESTRICT  DEFAULT NULL
        FAMILY character_defaults;
--rollback ALTER