--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            UUID     NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(),
    name          STRING   NOT NULL UNIQUE,
    emoji         STRING   NOT NULL UNIQUE,
    display_order SMALLINT NOT NULL
);
--rollback DROP TABLE IF EXISTS battle_types;

--changeset reya:battle_types_relationships runInTransaction:false
CREATE TABLE IF NOT EXISTS battle_types_relationships
(
    defender          UUID     NOT NULL REFERENCES battle_types (id) ON DELETE CASCADE,
    attacker          UUID     NOT NULL REFERENCES battle_types (id) ON DELETE CASCADE,
    damage_percentage SMALLINT NOT NULL DEFAULT 100,
    PRIMARY KEY (defender, attacker)
);
--rollback DROP TABLE IF EXISTS battle_types_relationships

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

--changeset reya:difficulties_table runInTransaction:false
CREATE TABLE IF NOT EXISTS difficulties
(
    id                          UUID     NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(),
    name                        STRING   NOT NULL UNIQUE,
    emoji                       STRING   NOT NULL UNIQUE,
    short_description           STRING   NOT NULL,
    long_description            STRING   NOT NULL,
    display_order               SMALLINT 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
(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 ('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),
       ('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, 95, 90, 0, 0, 0),
       ('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),
       ('Risky', '🌥',
        'Reformation is an unpleasant experience, but you can handle it if you have to.',
        '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'
            || 'After reforming, you''ll need some time to rest before you''re back at your peak.'
            || e'\n\n'
            || 'Suitable for players who want a balance between risk and maintaining their progress.',
        3, true, true, 75, 60, 25, 10, 25),
       ('Dangerous', '🌦',
        'You need to be careful around predators, as you''ll be in real trouble if you melt away.',
        'Digestion is something to be avoided at all costs. The process of being revived is expensive, costing a full '
            || '50% of your available money. You''ll also lose 50% of your proficiencies and 25% of your experience '
            || 'points as your mind and body are imperfectly restored. Your talents will be regenerated, as well.'
            || e'\n\n'
            || 'After reforming, you will be tired and still vulnerable to other predators. Take some time to rest '
            || 'after a defeat, or you''ll find yourself back in another stomach before you know it.'
            || e'\n\n'
            || 'Suitable for players who want digestion to be particularly painful, but not devastating.',
        4, true, true, 50, 30, 50, 25, 50),
       ('Very Dangerous', '🌧',
        'The world is cruel. Once you start getting digested, it''s hard to stop.',
        'Being a meal is not just humiliating - it''s a nightmare. You''re lucky you still remember who you are when '
            || 'you stumble out of the reformation chamber. You''ll lose 90% of your money to the reformation fee, '
            || 'and 90% of your proficiency points will be drained away as the reformation process leaves you '
            || 'seriously addled and barely feeling like yourself. Your experience point total will also drop by 50%.'
            || e'\n\n'
            || 'After reforming, you will be very weak and exhausted. Make sure to rest and recover before you get '
            || 'into another fight, or you''ll lose another large chunk of progress.'
            || e'\n\n'
            || 'Suitable for players who want digestion to be a devastating loss.',
        5, true, true, 25, 15, 90, 50, 90),
       ('Extremely Dangerous', '⛈',
        'Be very, very careful. There''s no coming back from digestion. Not really. You''ll lose everything...',
        'After being digested, your experience points, proficiencies, and money will all be set to 0, as if you '
            || 'had just stumbled blinking into this world for the first time. You''ll be able to keep your items, '
            || 'but that''s little comfort as your body and mind are returned to life as a blank slate...'
            || e'\n\n'
            || 'After reforming, you will have 1 Health and Energy. You definitely need to spend some time resting - '
            || 'or you won''t be able to break out of the cycle of digestion.'
            || e'\n\n'
            || 'Suitable for players who want a soft-perma type of experience.',
        6, true, true, 0, 0, 100, 100, 100)
ON CONFLICT DO NOTHING;
--rollback TRUNCATE difficulties;

--changeset reya:preferences_table runInTransaction:false
CREATE TABLE IF NOT EXISTS preferences
(
    id                UUID     NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(),
    name              STRING   NOT NULL UNIQUE,
    emoji             STRING   NOT NULL UNIQUE,
    short_description STRING   NOT NULL,
    display_order     SMALLINT 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 (name, emoji, short_description, display_order, can_use_vore,
                         can_receive_vore)
VALUES ('Switch', '😃', 'You can both eat and be eaten.', 0, true, true),
       ('Pred Only', '🤤', 'You can only eat, not be eaten.', 1, true, false),
       ('Prey Only', '🥩', 'You can only be eaten, not eat.', 2, false, true),
       ('Observer', '👀', 'You can neither eat nor be eaten.', 3, false, false)
ON CONFLICT DO NOTHING;
--rollback TRUNCATE preferences;

--changeset reya:gender_markers_table runInTransaction:false
CREATE TABLE IF NOT EXISTS gender_markers
(
    emoji         STRING   NOT NULL PRIMARY KEY,
    default_name  STRING   NOT NULL UNIQUE,
    display_order SMALLINT NOT NULL
);
--rollback DROP TABLE IF EXISTS gender_markers;

--changeset reya:gender_markers runInTransaction:true
INSERT INTO gender_markers (default_name, emoji, display_order)
VALUES ('Non-binary', '⚧', 0),
       ('Female', '♀️', 1),
       ('Male', '♂️', 2),
       ('Non*binary', '✳️', 3),
       ('Genderless', '⬜', 4)
ON CONFLICT DO NOTHING;
--rollback TRUNCATE gender_markers;

--changeset reya:pronouns_table runInTransaction:false
CREATE TABLE IF NOT EXISTS pronouns
(
    id             UUID     NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(),
    default_marker STRING   NOT NULL REFERENCES gender_markers (emoji) ON DELETE RESTRICT,
    name           STRING   NOT NULL UNIQUE,
    display_order  SMALLINT 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,
    UNIQUE (subjective, adjective, possessive, reflexive, objective)
);
--rollback DROP TABLE IF EXISTS pronouns;

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

--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,
    archived               BOOLEAN  NOT NULL DEFAULT FALSE,
    name                   STRING   NOT NULL,
    title                  STRING   NOT NULL,
    profile                STRING   NOT NULL,
    pronouns_id            SMALLINT NOT NULL REFERENCES pronouns (id) ON DELETE RESTRICT,
    gender_marker          STRING   NOT NULL REFERENCES gender_markers (emoji) ON DELETE RESTRICT,
    gender_name            STRING   NOT NULL,
    difficulty_id          SMALLINT NOT NULL REFERENCES difficulties (id) ON DELETE RESTRICT,
    preference_id          SMALLINT NOT NULL REFERENCES preferences (id) ON DELETE RESTRICT,
    battle_type1_id        SMALLINT NOT NULL REFERENCES battle_types (id) ON DELETE RESTRICT,
    battle_type2_id        SMALLINT NOT NULL REFERENCES battle_types (id) ON DELETE RESTRICT,
    experience             SMALLINT NOT NULL             DEFAULT 0,
    money                  SMALLINT NOT NULL             DEFAULT 0,

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

    FAMILY character_base (id, user_id, name, title, profile, pronouns_id, gender_marker, gender_name,
                           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 PRIMARY KEY,
    character_id    UUID     NULL REFERENCES characters (id) ON DELETE CASCADE,
    name            STRING   NULL,
    title           STRING   NULL,
    profile         STRING   NULL,
    pronouns_id     UUID     NULL REFERENCES pronouns (id) ON DELETE SET NULL,
    gender_marker   STRING   NULL REFERENCES gender_markers (emoji) ON DELETE SET NULL,
    gender_name     STRING   NULL,
    difficulty_id   UUID     NULL REFERENCES difficulties (id) ON DELETE SET NULL,
    preference_id   UUID     NULL REFERENCES preferences (id) ON DELETE SET NULL,
    battle_type1_id UUID     NULL REFERENCES battle_types (id) ON DELETE SET NULL,
    battle_type2_id UUID     NULL REFERENCES battle_types (id) ON DELETE SET NULL,
    base_confidence SMALLINT NULL DEFAULT 70,
    base_health     SMALLINT NULL DEFAULT 70,
    base_stamina    SMALLINT NULL DEFAULT 70,
    base_brawn      SMALLINT NULL DEFAULT 70,
    base_durability SMALLINT NULL DEFAULT 70,
    base_intensity  SMALLINT NULL DEFAULT 70,
    base_resilience SMALLINT NULL DEFAULT 70,
    base_speed      SMALLINT NULL DEFAULT 70
);
--rollback DROP TABLE IF EXISTS character_creation;

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