-- Domains
CREATE DOMAIN WL_HEX_COLOR AS TEXT CHECK (value ~* '^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$');
CREATE DOMAIN WL_EMAIL AS TEXT CHECK (value ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$');

-- Enumerated Types
-- Add new values using "ALTER TYPE WL_TASK_LIST_COL_KEY ADD VALUE 'NEW_VALUE_NAME' AFTER 'REPORTER';"
CREATE TYPE WL_TASK_LIST_COL_KEY AS ENUM ('ASSIGNEES', 'COMPLETED_DATE', 'CREATED_DATE', 'DESCRIPTION', 'DUE_DATE', 'ESTIMATION', 'KEY', 'LABELS', 'LAST_UPDATED', 'NAME', 'PRIORITY', 'PROGRESS', 'START_DATE', 'STATUS', 'TIME_TRACKING', 'REPORTER', 'PHASE');

CREATE TYPE REACTION_TYPES AS ENUM ('like');

CREATE TYPE DEPENDENCY_TYPE AS ENUM ('blocked_by');

CREATE TYPE SCHEDULE_TYPE AS ENUM ('daily', 'weekly', 'yearly', 'monthly', 'every_x_days', 'every_x_weeks', 'every_x_months');

CREATE TYPE LANGUAGE_TYPE AS ENUM ('en', 'es', 'pt');

-- START: Users
CREATE SEQUENCE IF NOT EXISTS users_user_no_seq START 1;

-- Utility and referenced tables
-- Create sessions table for connect-pg-simple session store
CREATE TABLE IF NOT EXISTS pg_sessions (
    sid    VARCHAR      NOT NULL        PRIMARY KEY,
    sess   JSON         NOT NULL,
    expire TIMESTAMP(6) NOT NULL
);

CREATE TABLE IF NOT EXISTS project_access_levels (
    id   UUID DEFAULT uuid_generate_v4() NOT NULL,
    name TEXT                            NOT NULL,
    key  TEXT                            NOT NULL
);

ALTER TABLE project_access_levels
    ADD CONSTRAINT project_access_levels_pk
        PRIMARY KEY (id);
        
CREATE TABLE IF NOT EXISTS countries (
    id       UUID       DEFAULT uuid_generate_v4() NOT NULL,
    code     CHAR(2)                               NOT NULL,
    name     VARCHAR(150)                          NOT NULL,
    phone    INTEGER                               NOT NULL,
    currency VARCHAR(3) DEFAULT NULL::CHARACTER VARYING
);

ALTER TABLE countries
    ADD PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS permissions (
    id          TEXT NOT NULL,
    name        TEXT NOT NULL,
    description TEXT NOT NULL
);

ALTER TABLE permissions
    ADD CONSTRAINT permissions_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS archived_projects (
    user_id    UUID NOT NULL,
    project_id UUID NOT NULL
);

ALTER TABLE archived_projects
    ADD CONSTRAINT archived_projects_pk
        PRIMARY KEY (user_id, project_id);

CREATE TABLE IF NOT EXISTS bounced_emails (
    id         UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    email      TEXT                                                NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE bounced_emails
    ADD CONSTRAINT bounced_emails_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS clients (
    id         UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name       TEXT                                                NOT NULL,
    team_id    UUID                                                NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE clients
    ADD CONSTRAINT clients_pk
        PRIMARY KEY (id);

ALTER TABLE clients
    ADD CONSTRAINT clients_name_check
        CHECK (CHAR_LENGTH(name) <= 60);

CREATE TABLE IF NOT EXISTS cpt_phases (
    id          UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name        TEXT                                                NOT NULL,
    color_code  WL_HEX_COLOR                                        NOT NULL,
    template_id UUID                                                NOT NULL,
    created_at  TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE cpt_phases
    ADD CONSTRAINT cpt_phases_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS cpt_task_labels (
    task_id  UUID NOT NULL,
    label_id UUID NOT NULL
);

ALTER TABLE cpt_task_labels
    ADD CONSTRAINT cpt_task_labels_pk
        PRIMARY KEY (task_id, label_id);

CREATE TABLE IF NOT EXISTS cpt_task_phases (
    task_id  UUID NOT NULL,
    phase_id UUID NOT NULL
);

ALTER TABLE cpt_task_phases
    ADD CONSTRAINT cpt_task_phase_phase_id_fk
        FOREIGN KEY (phase_id) REFERENCES cpt_phases
            ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS cpt_task_statuses (
    id          UUID    DEFAULT uuid_generate_v4() NOT NULL,
    name        TEXT                               NOT NULL,
    template_id UUID                               NOT NULL,
    team_id     UUID                               NOT NULL,
    category_id UUID                               NOT NULL,
    sort_order  INTEGER DEFAULT 0                  NOT NULL
);

ALTER TABLE cpt_task_statuses
    ADD CONSTRAINT cpt_task_statuses_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS cpt_tasks (
    id               UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name             TEXT                                                NOT NULL,
    description      TEXT,
    total_minutes    NUMERIC                  DEFAULT 0                  NOT NULL,
    sort_order       INTEGER                  DEFAULT 0                  NOT NULL,
    task_no          BIGINT,
    original_task_id UUID,
    priority_id      UUID                                                NOT NULL,
    template_id      UUID                                                NOT NULL,
    parent_task_id   UUID,
    status_id        UUID                                                NOT NULL,
    created_at       TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at       TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

COMMENT ON COLUMN cpt_tasks.original_task_id IS 'original_task_id from the project the template is created from';

ALTER TABLE cpt_tasks
    ADD CONSTRAINT cpt_tasks_pk
        PRIMARY KEY (id);

ALTER TABLE cpt_task_labels
    ADD CONSTRAINT cpt_task_labels_task_id_fk
        FOREIGN KEY (task_id) REFERENCES cpt_tasks
            ON DELETE CASCADE;

ALTER TABLE cpt_task_phases
    ADD CONSTRAINT cpt_task_phase_task_id_fk
        FOREIGN KEY (task_id) REFERENCES cpt_tasks
            ON DELETE CASCADE;

ALTER TABLE cpt_tasks
    ADD CONSTRAINT cpt_tasks_sort_order_unique
        UNIQUE (template_id, sort_order)
            DEFERRABLE INITIALLY DEFERRED;

ALTER TABLE cpt_tasks
    ADD CONSTRAINT cpt_tasks_status_id_fk
        FOREIGN KEY (status_id) REFERENCES cpt_task_statuses
            ON DELETE RESTRICT;

ALTER TABLE cpt_tasks
    ADD CONSTRAINT cpt_tasks_task_order_check
        CHECK (sort_order >= 0);

ALTER TABLE cpt_tasks
    ADD CONSTRAINT cpt_tasks_total_minutes_check
        CHECK ((total_minutes >= (0)::NUMERIC) AND (total_minutes <= (999999)::NUMERIC));

CREATE TABLE IF NOT EXISTS custom_project_templates (
    id          UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name        TEXT                                                NOT NULL,
    phase_label TEXT                     DEFAULT 'Phase'::TEXT      NOT NULL,
    team_id     UUID                                                NOT NULL,
    created_at  TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at  TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    color_code  TEXT                                                NOT NULL,
    notes       TEXT
);

ALTER TABLE custom_project_templates
    ADD CONSTRAINT custom_project_templates_pk
        PRIMARY KEY (id);

ALTER TABLE cpt_phases
    ADD CONSTRAINT cpt_phases_template_id_fk
        FOREIGN KEY (template_id) REFERENCES custom_project_templates
            ON DELETE CASCADE;

ALTER TABLE cpt_task_statuses
    ADD CONSTRAINT cpt_task_statuses_template_id_fk
        FOREIGN KEY (template_id) REFERENCES custom_project_templates
            ON DELETE CASCADE;

ALTER TABLE cpt_tasks
    ADD CONSTRAINT cpt_tasks_template_fk
        FOREIGN KEY (template_id) REFERENCES custom_project_templates
            ON DELETE CASCADE;

CREATE OR REPLACE FUNCTION lower_email() RETURNS trigger
    LANGUAGE plpgsql
AS
$$
DECLARE
BEGIN

    IF (is_null_or_empty(NEW.email) IS FALSE)
    THEN
        NEW.email = LOWER(TRIM(NEW.email));
    END IF;

    RETURN NEW;
END
$$;

CREATE TABLE IF NOT EXISTS email_invitations (
    id             UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name           TEXT                                                NOT NULL,
    email          WL_EMAIL                                            NOT NULL,
    team_id        UUID,
    team_member_id UUID,
    created_at     TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at     TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE email_invitations
    ADD CONSTRAINT email_invitations_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS favorite_projects (
    user_id    UUID NOT NULL,
    project_id UUID NOT NULL
);

ALTER TABLE favorite_projects
    ADD CONSTRAINT favorite_projects_pk
        PRIMARY KEY (user_id, project_id);

CREATE TABLE IF NOT EXISTS job_titles (
    id      UUID DEFAULT uuid_generate_v4() NOT NULL,
    name    TEXT                            NOT NULL,
    team_id UUID                            NOT NULL
);

ALTER TABLE job_titles
    ADD CONSTRAINT job_titles_pk
        PRIMARY KEY (id);

ALTER TABLE job_titles
    ADD CONSTRAINT job_titles_name_check
        CHECK (CHAR_LENGTH(name) <= 55);

CREATE TABLE IF NOT EXISTS licensing_admin_users (
    id         UUID    DEFAULT uuid_generate_v4() NOT NULL,
    name       TEXT                               NOT NULL,
    username   TEXT                               NOT NULL,
    phone_no   TEXT                               NOT NULL,
    otp        TEXT,
    otp_expiry TIMESTAMP WITH TIME ZONE,
    active     BOOLEAN DEFAULT TRUE               NOT NULL
);

ALTER TABLE licensing_admin_users
    ADD CONSTRAINT licensing_admin_users_id_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS licensing_app_sumo_batches (
    id         UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name       TEXT                                                NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    created_by UUID                                                NOT NULL
);

ALTER TABLE licensing_app_sumo_batches
    ADD CONSTRAINT licensing_app_sumo_batches_pk
        PRIMARY KEY (id);

ALTER TABLE licensing_app_sumo_batches
    ADD CONSTRAINT licensing_app_sumo_batches_created_by_fk
        FOREIGN KEY (created_by) REFERENCES licensing_admin_users;

CREATE TABLE IF NOT EXISTS licensing_coupon_codes (
    id                 UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    coupon_code        TEXT                                                NOT NULL,
    is_redeemed        BOOLEAN                  DEFAULT FALSE,
    is_app_sumo        BOOLEAN                  DEFAULT FALSE,
    projects_limit     INTEGER,
    team_members_limit INTEGER                  DEFAULT 3,
    storage_limit      INTEGER                  DEFAULT 5,
    redeemed_by        UUID,
    batch_id           UUID,
    created_by         UUID                                                NOT NULL,
    created_at         TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    redeemed_at        TIMESTAMP WITH TIME ZONE,
    is_refunded        BOOLEAN                  DEFAULT FALSE,
    reason             TEXT,
    feedback           TEXT,
    refunded_at        TIMESTAMP WITH TIME ZONE
);

ALTER TABLE licensing_coupon_codes
    ADD CONSTRAINT licensing_coupon_codes_pk
        PRIMARY KEY (id);

ALTER TABLE licensing_coupon_codes
    ADD CONSTRAINT licensing_coupon_codes_created_by_fk
        FOREIGN KEY (created_by) REFERENCES licensing_admin_users;

CREATE TABLE IF NOT EXISTS licensing_credit_subs (
    id             UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    next_plan_id   UUID                                                NOT NULL,
    user_id        UUID                                                NOT NULL,
    credit_given   NUMERIC                                             NOT NULL,
    created_at     TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    created_by     UUID                                                NOT NULL,
    checkout_url   TEXT,
    credit_balance NUMERIC                  DEFAULT 0
);

ALTER TABLE licensing_credit_subs
    ADD CONSTRAINT licensing_credit_subs_pk
        PRIMARY KEY (id);

ALTER TABLE licensing_credit_subs
    ADD CONSTRAINT licensing_credit_subs_created_by_fk
        FOREIGN KEY (created_by) REFERENCES licensing_admin_users;

CREATE TABLE IF NOT EXISTS licensing_custom_subs (
    id           UUID                     DEFAULT uuid_generate_v4()        NOT NULL,
    user_id      UUID                                                       NOT NULL,
    billing_type TEXT                     DEFAULT 'year'::CHARACTER VARYING NOT NULL,
    currency     TEXT                     DEFAULT 'LKR'::CHARACTER VARYING  NOT NULL,
    rate         NUMERIC                  DEFAULT 0                         NOT NULL,
    created_at   TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP         NOT NULL,
    end_date     DATE                                                       NOT NULL,
    user_limit   INTEGER
);

ALTER TABLE licensing_custom_subs
    ADD PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS licensing_custom_subs_logs (
    id              UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    subscription_id UUID                                                NOT NULL,
    log_text        TEXT                                                NOT NULL,
    description     TEXT,
    admin_user_id   UUID                                                NOT NULL,
    created_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE licensing_custom_subs_logs
    ADD PRIMARY KEY (id);

ALTER TABLE licensing_custom_subs_logs
    ADD CONSTRAINT licensing_custom_subs_logs_licensing_admin_users_id_fk
        FOREIGN KEY (admin_user_id) REFERENCES licensing_admin_users;

CREATE TABLE IF NOT EXISTS licensing_payment_details (
    id                      UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    user_id                 UUID,
    alert_id                TEXT                                                NOT NULL,
    alert_name              TEXT                                                NOT NULL,
    balance_currency        TEXT                     DEFAULT 'USD'::TEXT,
    balance_earnings        NUMERIC                  DEFAULT 0                  NOT NULL,
    balance_fee             NUMERIC                  DEFAULT 0                  NOT NULL,
    balance_gross           NUMERIC                  DEFAULT 0                  NOT NULL,
    balance_tax             NUMERIC                  DEFAULT 0                  NOT NULL,
    checkout_id             TEXT                                                NOT NULL,
    country                 TEXT                                                NOT NULL,
    coupon                  TEXT                                                NOT NULL,
    currency                TEXT                     DEFAULT 'USD'::TEXT        NOT NULL,
    custom_data             TEXT,
    customer_name           TEXT                                                NOT NULL,
    earnings                NUMERIC                  DEFAULT 0                  NOT NULL,
    email                   TEXT                                                NOT NULL,
    event_time              TEXT                                                NOT NULL,
    fee                     NUMERIC                  DEFAULT 0                  NOT NULL,
    initial_payment         NUMERIC                  DEFAULT 1                  NOT NULL,
    instalments             NUMERIC                  DEFAULT 1                  NOT NULL,
    marketing_consent       INTEGER                  DEFAULT 0,
    next_bill_date          DATE                                                NOT NULL,
    next_payment_amount     NUMERIC                  DEFAULT 0                  NOT NULL,
    order_id                TEXT                                                NOT NULL,
    p_signature             TEXT                                                NOT NULL,
    passthrough             TEXT,
    payment_method          TEXT                     DEFAULT 'card'::TEXT       NOT NULL,
    payment_tax             NUMERIC                  DEFAULT 0,
    plan_name               TEXT                                                NOT NULL,
    quantity                NUMERIC                  DEFAULT 0                  NOT NULL,
    receipt_url             TEXT                                                NOT NULL,
    sale_gross              TEXT                     DEFAULT 0                  NOT NULL,
    status                  TEXT                                                NOT NULL,
    subscription_id         TEXT                                                NOT NULL,
    subscription_payment_id TEXT                                                NOT NULL,
    subscription_plan_id    INTEGER,
    unit_price              NUMERIC                  DEFAULT 0                  NOT NULL,
    paddle_user_id          TEXT                                                NOT NULL,
    created_at              TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    payment_status          TEXT                     DEFAULT 'success'::TEXT    NOT NULL
);

ALTER TABLE licensing_payment_details
    ADD PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS licensing_pricing_plans (
    id               UUID    DEFAULT uuid_generate_v4() NOT NULL,
    name             TEXT    DEFAULT ''::TEXT           NOT NULL,
    billing_type     TEXT    DEFAULT 'month'::TEXT      NOT NULL,
    billing_period   INTEGER DEFAULT 1                  NOT NULL,
    default_currency TEXT    DEFAULT 'USD'::TEXT        NOT NULL,
    initial_price    TEXT    DEFAULT '0'::TEXT          NOT NULL,
    recurring_price  TEXT    DEFAULT '0'::TEXT          NOT NULL,
    trial_days       INTEGER DEFAULT 0                  NOT NULL,
    paddle_id        INTEGER DEFAULT 0,
    active           BOOLEAN DEFAULT FALSE              NOT NULL,
    is_startup_plan  BOOLEAN DEFAULT FALSE              NOT NULL
);

ALTER TABLE licensing_pricing_plans
    ADD CONSTRAINT licensing_pricing_plans_pk
        PRIMARY KEY (id);

ALTER TABLE licensing_credit_subs
    ADD CONSTRAINT licensing_credit_subs_next_plan_id_fk
        FOREIGN KEY (next_plan_id) REFERENCES licensing_pricing_plans;

ALTER TABLE licensing_pricing_plans
    ADD UNIQUE (paddle_id);

ALTER TABLE licensing_payment_details
    ADD CONSTRAINT licensing_payment_details_licensing_pricing_plans_paddle_id_fk
        FOREIGN KEY (subscription_plan_id) REFERENCES licensing_pricing_plans (paddle_id);

ALTER TABLE licensing_pricing_plans
    ADD CONSTRAINT billing_type_allowed
        CHECK (billing_type = ANY (ARRAY ['month'::TEXT, 'year'::TEXT]));

CREATE TABLE IF NOT EXISTS licensing_settings (
    default_trial_storage NUMERIC DEFAULT 1  NOT NULL,
    default_storage       NUMERIC DEFAULT 25 NOT NULL,
    storage_addon_price   NUMERIC DEFAULT 0  NOT NULL,
    storage_addon_size    NUMERIC DEFAULT 0,
    default_monthly_plan  UUID,
    default_annual_plan   UUID,
    default_startup_plan  UUID,
    projects_limit        INTEGER DEFAULT 5  NOT NULL,
    team_member_limit     INTEGER DEFAULT 0  NOT NULL,
    free_tier_storage     INTEGER DEFAULT 5  NOT NULL,
    trial_duration        INTEGER DEFAULT 14 NOT NULL
);

COMMENT ON COLUMN licensing_settings.default_trial_storage IS 'default storage amount for a trial in Gigabytes(GB)';

COMMENT ON COLUMN licensing_settings.default_storage IS 'default storage amount for a paid account in Gigabytes(GB)';

ALTER TABLE licensing_settings
    ADD CONSTRAINT licensing_settings_licensing_pricing_plans_id_fk
        FOREIGN KEY (default_startup_plan) REFERENCES licensing_pricing_plans;

ALTER TABLE licensing_settings
    ADD CONSTRAINT licensing_settings_licensing_user_plans_id_fk
        FOREIGN KEY (default_monthly_plan) REFERENCES licensing_pricing_plans;

ALTER TABLE licensing_settings
    ADD CONSTRAINT licensing_settings_licensing_user_plans_id_fk_2
        FOREIGN KEY (default_annual_plan) REFERENCES licensing_pricing_plans;

CREATE TABLE IF NOT EXISTS licensing_user_subscription_modifiers (
    subscription_id INTEGER                                            NOT NULL,
    modifier_id     INTEGER                                            NOT NULL,
    created_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL
);

CREATE TABLE IF NOT EXISTS licensing_user_subscriptions (
    id                          UUID    DEFAULT uuid_generate_v4() NOT NULL,
    user_id                     UUID                               NOT NULL,
    paddle_user_id              INTEGER,
    cancel_url                  TEXT,
    update_url                  TEXT,
    checkout_id                 TEXT,
    next_bill_date              TEXT,
    quantity                    INTEGER DEFAULT 1                  NOT NULL,
    subscription_id             INTEGER,
    subscription_plan_id        INTEGER,
    unit_price                  NUMERIC,
    plan_id                     UUID                               NOT NULL,
    status                      TEXT,
    custom_value_month          NUMERIC DEFAULT 0                  NOT NULL,
    custom_value_year           NUMERIC DEFAULT 0                  NOT NULL,
    custom_storage_amount       NUMERIC DEFAULT 0                  NOT NULL,
    custom_storage_unit         TEXT    DEFAULT 'MB'::TEXT         NOT NULL,
    cancellation_effective_date DATE,
    currency                    TEXT    DEFAULT 'USD'::TEXT        NOT NULL,
    event_time                  TEXT,
    paused_at                   TEXT,
    paused_from                 TEXT,
    paused_reason               TEXT,
    active                      BOOLEAN DEFAULT TRUE
);

ALTER TABLE licensing_user_subscriptions
    ADD CONSTRAINT licensing_user_plans_pk
        PRIMARY KEY (id);

ALTER TABLE licensing_user_subscriptions
    ADD UNIQUE (subscription_id);

ALTER TABLE licensing_user_subscriptions
    ADD CONSTRAINT licensing_user_subscriptions_licensing_pricing_plans_id_fk
        FOREIGN KEY (plan_id) REFERENCES licensing_pricing_plans;

ALTER TABLE licensing_user_subscriptions
    ADD CONSTRAINT licensing_user_subscriptions_statuses_allowed
        CHECK (status = ANY
               (ARRAY ['active'::TEXT, 'past_due'::TEXT, 'trialing'::TEXT, 'paused'::TEXT, 'deleted'::TEXT]));

CREATE TABLE IF NOT EXISTS notification_settings (
    email_notifications_enabled BOOLEAN DEFAULT TRUE  NOT NULL,
    popup_notifications_enabled BOOLEAN DEFAULT TRUE  NOT NULL,
    show_unread_items_count     BOOLEAN DEFAULT TRUE  NOT NULL,
    daily_digest_enabled        BOOLEAN DEFAULT FALSE NOT NULL,
    user_id                     UUID                  NOT NULL,
    team_id                     UUID                  NOT NULL
);

ALTER TABLE notification_settings
    ADD CONSTRAINT notification_settings_pk
        PRIMARY KEY (user_id, team_id);

CREATE TABLE IF NOT EXISTS organizations (
    id                       UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    organization_name        TEXT                                                NOT NULL,
    contact_number           TEXT,
    contact_number_secondary TEXT,
    address_line_1           TEXT,
    address_line_2           TEXT,
    country                  UUID,
    city                     TEXT,
    state                    TEXT,
    postal_code              TEXT,
    trial_in_progress        BOOLEAN                  DEFAULT FALSE              NOT NULL,
    trial_expire_date        DATE,
    subscription_status      TEXT                     DEFAULT 'active'::TEXT     NOT NULL,
    storage                  INTEGER                  DEFAULT 1                  NOT NULL,
    updating_plan            BOOLEAN                  DEFAULT FALSE,
    user_id                  UUID                                                NOT NULL,
    created_at               TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at               TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    license_type_id          UUID,
    is_lkr_billing           BOOLEAN                  DEFAULT FALSE,
    working_hours            DOUBLE PRECISION         DEFAULT 8                  NOT NULL
);

ALTER TABLE organizations
    ADD CONSTRAINT organizations_pk
        PRIMARY KEY (id);

ALTER TABLE organizations
    ADD CONSTRAINT organizations_pk_2
        UNIQUE (user_id);

ALTER TABLE organizations
    ADD CONSTRAINT subscription_statuses_allowed
        CHECK (subscription_status = ANY
               (ARRAY ['active'::TEXT, 'past_due'::TEXT, 'trialing'::TEXT, 'paused'::TEXT, 'deleted'::TEXT, 'life_time_deal'::TEXT, 'free'::TEXT, 'custom'::TEXT, 'credit'::TEXT]));

CREATE TABLE IF NOT EXISTS personal_todo_list (
    id          UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name        TEXT                                                NOT NULL,
    description TEXT,
    color_code  WL_HEX_COLOR                                        NOT NULL,
    done        BOOLEAN                  DEFAULT FALSE              NOT NULL,
    index       INTEGER                  DEFAULT 0,
    user_id     UUID                                                NOT NULL,
    created_at  TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at  TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE personal_todo_list
    ADD CONSTRAINT personal_todo_list_pk
        PRIMARY KEY (id);

ALTER TABLE personal_todo_list
    ADD CONSTRAINT personal_todo_list_description_check
        CHECK (CHAR_LENGTH(description) <= 200);

ALTER TABLE personal_todo_list
    ADD CONSTRAINT personal_todo_list_name_check
        CHECK (CHAR_LENGTH(name) <= 100);

CREATE TABLE IF NOT EXISTS project_categories (
    id         UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name       TEXT                                                NOT NULL,
    color_code WL_HEX_COLOR             DEFAULT '#70a6f3'::TEXT    NOT NULL,
    team_id    UUID                                                NOT NULL,
    created_by UUID                                                NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE project_categories
    ADD CONSTRAINT project_categories_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS project_comment_mentions (
    comment_id      UUID                                               NOT NULL,
    mentioned_index INTEGER                                            NOT NULL,
    mentioned_by    UUID                                               NOT NULL,
    informed_by     UUID                                               NOT NULL,
    created_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL
);

CREATE TABLE IF NOT EXISTS project_comments (
    id         UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    content    TEXT                                                NOT NULL,
    created_by UUID                                                NOT NULL,
    project_id UUID                                                NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE project_comments
    ADD CONSTRAINT project_comments_pk
        PRIMARY KEY (id);

ALTER TABLE project_comment_mentions
    ADD CONSTRAINT project_comment_mentions_comment_id_fk
        FOREIGN KEY (comment_id) REFERENCES project_comments
            ON DELETE CASCADE;

ALTER TABLE project_comments
    ADD CONSTRAINT project_comments_content_length_check
        CHECK (CHAR_LENGTH(content) <= 2000);

CREATE TABLE IF NOT EXISTS project_folders (
    id               UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name             TEXT                                                NOT NULL,
    key              TEXT                                                NOT NULL,
    color_code       WL_HEX_COLOR             DEFAULT '#70a6f3'::TEXT    NOT NULL,
    created_by       UUID                                                NOT NULL,
    parent_folder_id UUID,
    team_id          UUID                                                NOT NULL,
    created_at       TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at       TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE project_folders
    ADD CONSTRAINT project_folders_pk
        PRIMARY KEY (id);

ALTER TABLE project_folders
    ADD CONSTRAINT project_folders_parent_folder_fk
        FOREIGN KEY (parent_folder_id) REFERENCES project_folders;

CREATE TABLE IF NOT EXISTS project_logs (
    id          UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    team_id     UUID                                                NOT NULL,
    project_id  UUID                                                NOT NULL,
    description TEXT                                                NOT NULL,
    created_at  TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE project_logs
    ADD CONSTRAINT project_logs_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS project_member_allocations (
    id              UUID DEFAULT uuid_generate_v4() NOT NULL,
    project_id      UUID                            NOT NULL,
    team_member_id  UUID                            NOT NULL,
    allocated_from  TIMESTAMP WITH TIME ZONE        NOT NULL,
    allocated_to    TIMESTAMP WITH TIME ZONE        NOT NULL,
    seconds_per_day INTEGER
);

ALTER TABLE project_member_allocations
    ADD CONSTRAINT project_member_allocations_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS project_members (
    id                      UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    team_member_id          UUID                                                NOT NULL,
    project_access_level_id UUID                                                NOT NULL,
    project_id              UUID                                                NOT NULL,
    role_id                 UUID                                                NOT NULL,
    created_at              TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    default_view            TEXT                     DEFAULT 'TASK_LIST'::TEXT  NOT NULL
);

ALTER TABLE project_members
    ADD CONSTRAINT project_members_pk
        PRIMARY KEY (id);

ALTER TABLE project_members
    ADD CONSTRAINT project_members_access_level_fk
        FOREIGN KEY (project_access_level_id) REFERENCES project_access_levels;

CREATE TABLE IF NOT EXISTS project_phases (
    id         UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name       TEXT                                                NOT NULL,
    color_code WL_HEX_COLOR                                        NOT NULL,
    project_id UUID                                                NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    start_date TIMESTAMP WITH TIME ZONE,
    end_date   TIMESTAMP WITH TIME ZONE,
    sort_index INTEGER                  DEFAULT 0
);

ALTER TABLE project_phases
    ADD CONSTRAINT project_phases_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS project_subscribers (
    id             UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    user_id        UUID                                                NOT NULL,
    project_id     UUID                                                NOT NULL,
    team_member_id UUID                                                NOT NULL,
    created_at     TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE project_subscribers
    ADD CONSTRAINT project_subscribers_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS project_task_list_cols (
    id                UUID    DEFAULT uuid_generate_v4() NOT NULL,
    name              TEXT                               NOT NULL,
    key               WL_TASK_LIST_COL_KEY               NOT NULL,
    index             INTEGER DEFAULT 0                  NOT NULL,
    pinned            BOOLEAN DEFAULT TRUE               NOT NULL,
    project_id        UUID                               NOT NULL,
    custom_column     BOOLEAN DEFAULT FALSE,
    custom_column_obj JSONB
);

ALTER TABLE project_task_list_cols
    ADD CONSTRAINT project_task_list_cols_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS projects (
    id                     UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name                   TEXT                                                NOT NULL,
    key                    TEXT                                                NOT NULL,
    color_code             WL_HEX_COLOR             DEFAULT '#70a6f3'::TEXT    NOT NULL,
    notes                  TEXT,
    tasks_counter          BIGINT                   DEFAULT 0                  NOT NULL,
    start_date             TIMESTAMP WITH TIME ZONE,
    end_date               TIMESTAMP WITH TIME ZONE,
    team_id                UUID                                                NOT NULL,
    client_id              UUID,
    owner_id               UUID                                                NOT NULL,
    status_id              UUID                                                NOT NULL,
    created_at             TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at             TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    category_id            UUID,
    folder_id              UUID,
    phase_label            TEXT                     DEFAULT 'Phase'::TEXT      NOT NULL,
    estimated_man_days     INTEGER                  DEFAULT 0,
    hours_per_day          INTEGER                  DEFAULT 8,
    health_id              UUID,
    estimated_working_days INTEGER                  DEFAULT 0
);

ALTER TABLE projects
    ADD CONSTRAINT projects_pk
        PRIMARY KEY (id);

ALTER TABLE archived_projects
    ADD CONSTRAINT archived_projects_project_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE favorite_projects
    ADD CONSTRAINT favorite_projects_project_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE project_comments
    ADD CONSTRAINT project_comments_project_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE project_logs
    ADD CONSTRAINT project_logs_projects_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE project_member_allocations
    ADD CONSTRAINT project_members_allocations_project_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE project_members
    ADD CONSTRAINT project_members_project_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE project_phases
    ADD CONSTRAINT project_phases_project_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE project_subscribers
    ADD CONSTRAINT project_subscribers_project_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE project_task_list_cols
    ADD CONSTRAINT project_task_list_cols_project_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE projects
    ADD CONSTRAINT projects_category_id_fk
        FOREIGN KEY (category_id) REFERENCES project_categories
            ON DELETE CASCADE;

ALTER TABLE projects
    ADD CONSTRAINT projects_client_id_fk
        FOREIGN KEY (client_id) REFERENCES clients
            ON DELETE SET NULL;

ALTER TABLE projects
    ADD CONSTRAINT projects_folder_id_fk
        FOREIGN KEY (folder_id) REFERENCES project_folders
            ON DELETE SET DEFAULT;

ALTER TABLE projects
    ADD CONSTRAINT projects_name_check
        CHECK (CHAR_LENGTH(name) <= 100);

ALTER TABLE projects
    ADD CONSTRAINT projects_notes_check
        CHECK (CHAR_LENGTH(notes) <= 500);

CREATE TABLE IF NOT EXISTS pt_labels (
    id          UUID DEFAULT uuid_generate_v4() NOT NULL,
    name        TEXT                            NOT NULL,
    color_code  TEXT                            NOT NULL,
    template_id UUID
);

ALTER TABLE pt_labels
    ADD CONSTRAINT pt_project_templates_labels_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS pt_phases (
    id          UUID DEFAULT uuid_generate_v4() NOT NULL,
    name        TEXT                            NOT NULL,
    color_code  TEXT,
    template_id UUID                            NOT NULL
);

ALTER TABLE pt_phases
    ADD CONSTRAINT pt_project_template_phases_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS pt_project_templates (
    id          UUID DEFAULT uuid_generate_v4() NOT NULL,
    name        TEXT                            NOT NULL,
    key         TEXT                            NOT NULL,
    description TEXT,
    phase_label TEXT,
    image_url   TEXT,
    color_code  TEXT DEFAULT '#3b7ad4'::TEXT    NOT NULL
);

ALTER TABLE pt_project_templates
    ADD CONSTRAINT pt_project_templates_pk
        PRIMARY KEY (id);

ALTER TABLE pt_labels
    ADD CONSTRAINT pt_labels_pt_project_templates_id_fk
        FOREIGN KEY (template_id) REFERENCES pt_project_templates;

ALTER TABLE pt_phases
    ADD CONSTRAINT pt_project_template_phases_template_id_fk
        FOREIGN KEY (template_id) REFERENCES pt_project_templates
            ON DELETE CASCADE;

ALTER TABLE pt_project_templates
    ADD CONSTRAINT pt_project_templates_key_unique
        UNIQUE (key);

CREATE TABLE IF NOT EXISTS pt_statuses (
    id          UUID DEFAULT uuid_generate_v4() NOT NULL,
    name        TEXT                            NOT NULL,
    template_id UUID                            NOT NULL,
    category_id UUID                            NOT NULL
);

ALTER TABLE pt_statuses
    ADD CONSTRAINT pt_project_template_statuses_pk
        PRIMARY KEY (id);

ALTER TABLE pt_statuses
    ADD CONSTRAINT pt_project_template_statuses_template_id_fk
        FOREIGN KEY (template_id) REFERENCES pt_project_templates
            ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS pt_task_labels (
    task_id  UUID NOT NULL,
    label_id UUID NOT NULL
);

ALTER TABLE pt_task_labels
    ADD CONSTRAINT pt_task_labels_pk
        PRIMARY KEY (task_id, label_id);

ALTER TABLE pt_task_labels
    ADD CONSTRAINT pt_task_labels_label_id_fk
        FOREIGN KEY (label_id) REFERENCES pt_labels;

CREATE TABLE IF NOT EXISTS pt_task_phases (
    task_id  UUID NOT NULL,
    phase_id UUID NOT NULL
);

ALTER TABLE pt_task_phases
    ADD CONSTRAINT pt_task_phase_phase_id_fk
        FOREIGN KEY (phase_id) REFERENCES pt_phases
            ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS pt_task_statuses (
    id          UUID    DEFAULT uuid_generate_v4() NOT NULL,
    name        TEXT                               NOT NULL,
    template_id UUID                               NOT NULL,
    team_id     UUID                               NOT NULL,
    category_id UUID                               NOT NULL,
    sort_order  INTEGER DEFAULT 0                  NOT NULL
);

ALTER TABLE pt_task_statuses
    ADD CONSTRAINT pt_task_statuses_pk
        PRIMARY KEY (id);

ALTER TABLE pt_task_statuses
    ADD CONSTRAINT pt_task_statuses_template_id_fk
        FOREIGN KEY (template_id) REFERENCES pt_project_templates
            ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS pt_tasks (
    id             UUID    DEFAULT uuid_generate_v4() NOT NULL,
    name           TEXT                               NOT NULL,
    description    TEXT,
    total_minutes  NUMERIC DEFAULT 0                  NOT NULL,
    sort_order     INTEGER DEFAULT 0                  NOT NULL,
    priority_id    UUID                               NOT NULL,
    template_id    UUID                               NOT NULL,
    parent_task_id UUID,
    status_id      UUID                               NOT NULL
);

ALTER TABLE pt_tasks
    ADD CONSTRAINT pt_tasks_pk
        PRIMARY KEY (id);

ALTER TABLE pt_task_labels
    ADD CONSTRAINT pt_task_labels_task_id_fk
        FOREIGN KEY (task_id) REFERENCES pt_tasks
            ON DELETE CASCADE;

ALTER TABLE pt_task_phases
    ADD CONSTRAINT pt_task_phase_task_id_fk
        FOREIGN KEY (task_id) REFERENCES pt_tasks
            ON DELETE CASCADE;

ALTER TABLE pt_tasks
    ADD CONSTRAINT pt_tasks_sort_order_unique
        UNIQUE (template_id, sort_order)
            DEFERRABLE INITIALLY DEFERRED;

ALTER TABLE pt_tasks
    ADD CONSTRAINT pt_tasks_parent_task_id_fk
        FOREIGN KEY (parent_task_id) REFERENCES pt_tasks
            ON DELETE CASCADE;

ALTER TABLE pt_tasks
    ADD CONSTRAINT pt_tasks_status_id_fk
        FOREIGN KEY (status_id) REFERENCES pt_statuses
            ON DELETE RESTRICT;

ALTER TABLE pt_tasks
    ADD CONSTRAINT pt_tasks_template_fk
        FOREIGN KEY (template_id) REFERENCES pt_project_templates
            ON DELETE CASCADE;

ALTER TABLE pt_tasks
    ADD CONSTRAINT pt_tasks_task_order_check
        CHECK (sort_order >= 0);

ALTER TABLE pt_tasks
    ADD CONSTRAINT pt_tasks_total_minutes_check
        CHECK ((total_minutes >= (0)::NUMERIC) AND (total_minutes <= (999999)::NUMERIC));

CREATE TABLE IF NOT EXISTS role_permissions (
    role_id       UUID NOT NULL,
    permission_id TEXT NOT NULL
);

ALTER TABLE role_permissions
    ADD CONSTRAINT role_permissions_pk
        PRIMARY KEY (role_id, permission_id);

ALTER TABLE role_permissions
    ADD CONSTRAINT role_permissions_permission_id_fk
        FOREIGN KEY (permission_id) REFERENCES permissions;

CREATE TABLE IF NOT EXISTS roles (
    id           UUID    DEFAULT uuid_generate_v4() NOT NULL,
    name         TEXT                               NOT NULL,
    team_id      UUID                               NOT NULL,
    default_role BOOLEAN DEFAULT FALSE              NOT NULL,
    admin_role   BOOLEAN DEFAULT FALSE              NOT NULL,
    owner        BOOLEAN DEFAULT FALSE              NOT NULL
);

ALTER TABLE roles
    ADD CONSTRAINT roles_pk
        PRIMARY KEY (id);

ALTER TABLE project_members
    ADD CONSTRAINT project_members_role_id_fk
        FOREIGN KEY (role_id) REFERENCES roles;

ALTER TABLE role_permissions
    ADD CONSTRAINT role_permissions_role_id_fk
        FOREIGN KEY (role_id) REFERENCES roles;

CREATE TABLE IF NOT EXISTS spam_emails (
    id         UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    email      TEXT                                                NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE spam_emails
    ADD CONSTRAINT spam_emails_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS sys_project_healths (
    id         UUID    DEFAULT uuid_generate_v4() NOT NULL,
    name       TEXT                               NOT NULL,
    color_code WL_HEX_COLOR                       NOT NULL,
    sort_order INTEGER DEFAULT 0                  NOT NULL,
    is_default BOOLEAN DEFAULT FALSE              NOT NULL
);

ALTER TABLE sys_project_healths
    ADD CONSTRAINT sys_project_healths_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS sys_project_statuses (
    id         UUID    DEFAULT uuid_generate_v4() NOT NULL,
    name       TEXT                               NOT NULL,
    color_code WL_HEX_COLOR                       NOT NULL,
    icon       TEXT                               NOT NULL,
    sort_order INTEGER DEFAULT 0                  NOT NULL,
    is_default BOOLEAN DEFAULT FALSE              NOT NULL
);

ALTER TABLE sys_project_statuses
    ADD CONSTRAINT sys_project_statuses_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS sys_task_status_categories (
    id              UUID    DEFAULT uuid_generate_v4() NOT NULL,
    name            TEXT                               NOT NULL,
    color_code      WL_HEX_COLOR                       NOT NULL,
    index           INTEGER DEFAULT 0                  NOT NULL,
    is_todo         BOOLEAN DEFAULT FALSE              NOT NULL,
    is_doing        BOOLEAN DEFAULT FALSE              NOT NULL,
    is_done         BOOLEAN DEFAULT FALSE              NOT NULL,
    description     TEXT,
    color_code_dark WL_HEX_COLOR
);

ALTER TABLE sys_task_status_categories
    ADD CONSTRAINT sys_task_status_categories_pk
        PRIMARY KEY (id);

ALTER TABLE cpt_task_statuses
    ADD CONSTRAINT cpt_task_statuses_category_id_fk
        FOREIGN KEY (category_id) REFERENCES sys_task_status_categories;

ALTER TABLE pt_statuses
    ADD CONSTRAINT pt_project_template_statuses_category_id_fk
        FOREIGN KEY (category_id) REFERENCES sys_task_status_categories;

ALTER TABLE pt_task_statuses
    ADD CONSTRAINT pt_task_statuses_category_id_fk
        FOREIGN KEY (category_id) REFERENCES sys_task_status_categories;

CREATE TABLE IF NOT EXISTS task_activity_logs (
    id             UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    task_id        UUID                                                NOT NULL,
    team_id        UUID                                                NOT NULL,
    attribute_type TEXT                                                NOT NULL,
    user_id        UUID                                                NOT NULL,
    log_type       TEXT,
    old_value      TEXT,
    new_value      TEXT,
    prev_string    TEXT,
    next_string    TEXT,
    created_at     TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    project_id     UUID                                                NOT NULL
);

COMMENT ON COLUMN task_activity_logs.user_id IS 'id of the user who initiated the activity';

COMMENT ON COLUMN task_activity_logs.log_type IS 'whether the log belongs to create, update, delete, assign or unassign category';

ALTER TABLE task_activity_logs
    ADD CONSTRAINT task_activity_logs_pk
        PRIMARY KEY (id);

ALTER TABLE task_activity_logs
    ADD CONSTRAINT task_activity_logs_projects_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE task_activity_logs
    ADD CONSTRAINT task_activity_logs_log_type_check
        CHECK (log_type = ANY (ARRAY ['create'::TEXT, 'update'::TEXT, 'delete'::TEXT, 'assign'::TEXT, 'unassign'::TEXT]));

CREATE TABLE IF NOT EXISTS task_attachments (
    id          UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name        TEXT                                                NOT NULL,
    size        BIGINT                   DEFAULT 0                  NOT NULL,
    type        TEXT                                                NOT NULL,
    task_id     UUID,
    team_id     UUID                                                NOT NULL,
    project_id  UUID                                                NOT NULL,
    uploaded_by UUID                                                NOT NULL,
    created_at  TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE task_attachments
    ADD CONSTRAINT task_attachments_pk
        PRIMARY KEY (id);

ALTER TABLE task_attachments
    ADD CONSTRAINT task_attachments_project_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE task_attachments
    ADD CONSTRAINT task_attachments_name_check
        CHECK (CHAR_LENGTH(name) <= 110);

CREATE TABLE IF NOT EXISTS task_comment_contents (
    index          INTEGER NOT NULL,
    comment_id     UUID    NOT NULL,
    team_member_id UUID,
    text_content   TEXT
);

ALTER TABLE task_comment_contents
    ADD CONSTRAINT task_comment_contents_content_check
        CHECK (((team_member_id IS NULL) AND (text_content IS NULL)) IS FALSE);

ALTER TABLE task_comment_contents
    ADD CONSTRAINT task_comment_contents_name_check
        CHECK (CHAR_LENGTH(text_content) <= 5000);

CREATE TABLE IF NOT EXISTS task_comments (
    id             UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    user_id        UUID                                                NOT NULL,
    team_member_id UUID                                                NOT NULL,
    task_id        UUID                                                NOT NULL,
    created_at     TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at     TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    ses_message_id TEXT
);

ALTER TABLE task_comments
    ADD CONSTRAINT task_comments_pk
        PRIMARY KEY (id);

ALTER TABLE task_comment_contents
    ADD CONSTRAINT task_comment_contents_comment_id_fk
        FOREIGN KEY (comment_id) REFERENCES task_comments
            ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS task_labels (
    task_id  UUID NOT NULL,
    label_id UUID NOT NULL
);

ALTER TABLE task_labels
    ADD CONSTRAINT task_labels_pk
        PRIMARY KEY (task_id, label_id);

CREATE TABLE IF NOT EXISTS team_labels (
    id         UUID DEFAULT uuid_generate_v4() NOT NULL,
    name       TEXT                            NOT NULL,
    color_code WL_HEX_COLOR                    NOT NULL,
    team_id    UUID                            NOT NULL
);

ALTER TABLE team_labels
    ADD CONSTRAINT team_labels_pk
        PRIMARY KEY (id);

ALTER TABLE cpt_task_labels
    ADD CONSTRAINT cpt_task_labels_label_id_fk
        FOREIGN KEY (label_id) REFERENCES team_labels
            ON DELETE CASCADE;

ALTER TABLE task_labels
    ADD CONSTRAINT task_labels_label_id_fk
        FOREIGN KEY (label_id) REFERENCES team_labels
            ON DELETE CASCADE;

ALTER TABLE team_labels
    ADD CONSTRAINT team_labels_name_check
        CHECK (CHAR_LENGTH(name) <= 40);

CREATE TABLE IF NOT EXISTS task_phase (
    task_id  UUID NOT NULL,
    phase_id UUID NOT NULL
);

ALTER TABLE task_phase
    ADD CONSTRAINT task_phase_phase_id_fk
        FOREIGN KEY (phase_id) REFERENCES project_phases
            ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS task_priorities (
    id              UUID    DEFAULT uuid_generate_v4() NOT NULL,
    name            TEXT                               NOT NULL,
    value           INTEGER DEFAULT 0                  NOT NULL,
    color_code      WL_HEX_COLOR                       NOT NULL,
    color_code_dark WL_HEX_COLOR
);

ALTER TABLE task_priorities
    ADD CONSTRAINT task_priorities_pk
        PRIMARY KEY (id);

ALTER TABLE cpt_tasks
    ADD CONSTRAINT cpt_tasks_priority_fk
        FOREIGN KEY (priority_id) REFERENCES task_priorities;

ALTER TABLE pt_tasks
    ADD CONSTRAINT pt_tasks_priority_fk
        FOREIGN KEY (priority_id) REFERENCES task_priorities;

CREATE TABLE IF NOT EXISTS task_statuses (
    id          UUID    DEFAULT uuid_generate_v4() NOT NULL,
    name        TEXT                               NOT NULL,
    project_id  UUID                               NOT NULL,
    team_id     UUID                               NOT NULL,
    category_id UUID                               NOT NULL,
    sort_order  INTEGER DEFAULT 0                  NOT NULL
);

ALTER TABLE task_statuses
    ADD CONSTRAINT task_statuses_pk
        PRIMARY KEY (id);

ALTER TABLE task_statuses
    ADD CONSTRAINT task_statuses_category_id_fk
        FOREIGN KEY (category_id) REFERENCES sys_task_status_categories;

ALTER TABLE task_statuses
    ADD CONSTRAINT task_statuses_project_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE task_statuses
    ADD CONSTRAINT task_statuses_name_check
        CHECK (CHAR_LENGTH(name) <= 50);

CREATE TABLE IF NOT EXISTS task_subscribers (
    id             UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    user_id        UUID                                                NOT NULL,
    task_id        UUID                                                NOT NULL,
    team_member_id UUID                                                NOT NULL,
    action         TEXT                                                NOT NULL,
    created_at     TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE task_subscribers
    ADD CONSTRAINT task_subscribers_pk
        PRIMARY KEY (id);

ALTER TABLE task_subscribers
    ADD CONSTRAINT task_subscribers_action_check
        CHECK (action = 'WHEN_DONE'::TEXT);

CREATE TABLE IF NOT EXISTS task_templates (
    id         UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name       TEXT                                                NOT NULL,
    team_id    UUID                                                NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE task_templates
    ADD CONSTRAINT task_templates_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS task_templates_tasks (
    name          TEXT              NOT NULL,
    template_id   UUID              NOT NULL,
    total_minutes NUMERIC DEFAULT 0 NOT NULL
);

ALTER TABLE task_templates_tasks
    ADD CONSTRAINT task_templates_tasks_template_id_fk
        FOREIGN KEY (template_id) REFERENCES task_templates
            ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS task_timers (
    task_id    UUID NOT NULL,
    user_id    UUID NOT NULL,
    start_time TIMESTAMP WITH TIME ZONE
);

ALTER TABLE task_timers
    ADD CONSTRAINT task_timers_pk
        PRIMARY KEY (task_id, user_id);

CREATE TABLE IF NOT EXISTS task_updates (
    id          UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    type        TEXT                                                NOT NULL,
    reporter_id UUID                                                NOT NULL,
    task_id     UUID                                                NOT NULL,
    user_id     UUID                                                NOT NULL,
    team_id     UUID                                                NOT NULL,
    project_id  UUID                                                NOT NULL,
    is_sent     BOOLEAN                  DEFAULT FALSE              NOT NULL,
    created_at  TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    retry_count INTEGER                  DEFAULT 0
);

ALTER TABLE task_updates
    ADD CONSTRAINT task_updates_pk
        PRIMARY KEY (id);

ALTER TABLE task_updates
    ADD CONSTRAINT task_updates_project_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE task_updates
    ADD CONSTRAINT task_updates_type_check
        CHECK (type = ANY (ARRAY ['ASSIGN'::TEXT, 'UNASSIGN'::TEXT]));

CREATE TABLE IF NOT EXISTS task_work_log (
    id              UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    time_spent      NUMERIC                  DEFAULT 0                  NOT NULL,
    description     TEXT,
    logged_by_timer BOOLEAN                  DEFAULT FALSE              NOT NULL,
    task_id         UUID                                                NOT NULL,
    user_id         UUID                                                NOT NULL,
    created_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE task_work_log
    ADD CONSTRAINT task_work_log_pk
        PRIMARY KEY (id);

ALTER TABLE task_work_log
    ADD CONSTRAINT task_work_log_description_check
        CHECK (CHAR_LENGTH(description) <= 500);

ALTER TABLE task_work_log
    ADD CONSTRAINT task_work_log_time_spent_check
        CHECK (time_spent >= (0)::NUMERIC);

CREATE TABLE IF NOT EXISTS tasks (
    id                 UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name               TEXT                                                NOT NULL,
    description        TEXT,
    done               BOOLEAN                  DEFAULT FALSE              NOT NULL,
    total_minutes      NUMERIC                  DEFAULT 0                  NOT NULL,
    archived           BOOLEAN                  DEFAULT FALSE              NOT NULL,
    task_no            BIGINT                                              NOT NULL,
    start_date         TIMESTAMP WITH TIME ZONE,
    end_date           TIMESTAMP WITH TIME ZONE,
    priority_id        UUID                                                NOT NULL,
    project_id         UUID                                                NOT NULL,
    reporter_id        UUID                                                NOT NULL,
    parent_task_id     UUID,
    status_id          UUID                                                NOT NULL,
    completed_at       TIMESTAMP WITH TIME ZONE,
    created_at         TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at         TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    sort_order         INTEGER                  DEFAULT 0                  NOT NULL,
    roadmap_sort_order INTEGER                  DEFAULT 0                  NOT NULL,
    billable           BOOLEAN                  DEFAULT TRUE,
    schedule_id        UUID
);

ALTER TABLE tasks
    ADD CONSTRAINT tasks_pk
        PRIMARY KEY (id);

ALTER TABLE task_activity_logs
    ADD CONSTRAINT task_activity_logs_tasks_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

ALTER TABLE task_attachments
    ADD CONSTRAINT task_attachments_task_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE SET NULL;

ALTER TABLE task_comments
    ADD CONSTRAINT task_comments_task_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

ALTER TABLE task_labels
    ADD CONSTRAINT task_labels_task_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

ALTER TABLE task_phase
    ADD CONSTRAINT task_phase_task_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

ALTER TABLE task_subscribers
    ADD CONSTRAINT task_subscribers_task_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

ALTER TABLE task_timers
    ADD CONSTRAINT task_timers_task_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

ALTER TABLE task_updates
    ADD CONSTRAINT task_updates_task_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

ALTER TABLE task_work_log
    ADD CONSTRAINT task_work_log_task_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

ALTER TABLE tasks
    ADD CONSTRAINT tasks_sort_order_unique
        UNIQUE (project_id, sort_order)
            DEFERRABLE INITIALLY DEFERRED;

ALTER TABLE tasks
    ADD CONSTRAINT tasks_parent_task_id_fk
        FOREIGN KEY (parent_task_id) REFERENCES tasks
            ON DELETE CASCADE;

ALTER TABLE tasks
    ADD CONSTRAINT tasks_priority_fk
        FOREIGN KEY (priority_id) REFERENCES task_priorities;

ALTER TABLE tasks
    ADD CONSTRAINT tasks_status_id_fk
        FOREIGN KEY (status_id) REFERENCES task_statuses
            ON DELETE RESTRICT;

ALTER TABLE tasks
    ADD CONSTRAINT tasks_project_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE tasks
    ADD CONSTRAINT tasks_description_check
        CHECK (CHAR_LENGTH(description) <= 500000);

ALTER TABLE tasks
    ADD CONSTRAINT tasks_name_check
        CHECK (CHAR_LENGTH(name) <= 500);

ALTER TABLE tasks
    ADD CONSTRAINT tasks_total_minutes_check
        CHECK ((total_minutes >= (0)::NUMERIC) AND (total_minutes <= (999999)::NUMERIC));

CREATE TABLE IF NOT EXISTS tasks_assignees (
    task_id           UUID                                               NOT NULL,
    project_member_id UUID                                               NOT NULL,
    team_member_id    UUID                                               NOT NULL,
    created_at        TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
    updated_at        TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
    assigned_by       UUID                                               NOT NULL
);

ALTER TABLE tasks_assignees
    ADD CONSTRAINT tasks_assignees_pk
        PRIMARY KEY (task_id, project_member_id);

ALTER TABLE tasks_assignees
    ADD CONSTRAINT tasks_assignees_project_member_id_fk
        FOREIGN KEY (project_member_id) REFERENCES project_members
            ON UPDATE CASCADE ON DELETE CASCADE;

ALTER TABLE tasks_assignees
    ADD CONSTRAINT tasks_assignees_task_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS team_members (
    id           UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    user_id      UUID,
    team_id      UUID                                                NOT NULL,
    role_id      UUID                                                NOT NULL,
    job_title_id UUID,
    created_at   TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at   TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    active       BOOLEAN                  DEFAULT TRUE
);

ALTER TABLE team_members
    ADD CONSTRAINT team_members_pk
        PRIMARY KEY (id);

ALTER TABLE email_invitations
    ADD CONSTRAINT email_invitations_team_member_id_fk
        FOREIGN KEY (team_member_id) REFERENCES team_members
            ON DELETE CASCADE;

ALTER TABLE project_member_allocations
    ADD CONSTRAINT project_members_allocations_team_member_id_fk
        FOREIGN KEY (team_member_id) REFERENCES team_members
            ON DELETE CASCADE;

ALTER TABLE project_members
    ADD CONSTRAINT project_members_team_member_id_fk
        FOREIGN KEY (team_member_id) REFERENCES team_members
            ON DELETE CASCADE;

ALTER TABLE project_subscribers
    ADD CONSTRAINT project_subscribers_team_member_id_fk
        FOREIGN KEY (team_member_id) REFERENCES team_members
            ON DELETE CASCADE;

ALTER TABLE task_comment_contents
    ADD CONSTRAINT task_comment_contents_team_member_fk
        FOREIGN KEY (team_member_id) REFERENCES team_members;

ALTER TABLE task_comments
    ADD CONSTRAINT task_comments_team_member_id_fk
        FOREIGN KEY (team_member_id) REFERENCES team_members
            ON DELETE CASCADE;

ALTER TABLE task_subscribers
    ADD CONSTRAINT task_subscribers_team_member_id_fk
        FOREIGN KEY (team_member_id) REFERENCES team_members
            ON DELETE CASCADE;

ALTER TABLE tasks_assignees
    ADD CONSTRAINT tasks_assignees_team_member_fk
        FOREIGN KEY (team_member_id) REFERENCES team_members
            ON DELETE CASCADE;

ALTER TABLE team_members
    ADD CONSTRAINT team_members_job_title_id_fk
        FOREIGN KEY (job_title_id) REFERENCES job_titles
            ON DELETE SET NULL;

ALTER TABLE team_members
    ADD CONSTRAINT team_members_role_id_fk
        FOREIGN KEY (role_id) REFERENCES roles;

CREATE TABLE IF NOT EXISTS users (
    id              UUID                     DEFAULT uuid_generate_v4()                     NOT NULL,
    name            TEXT                                                                    NOT NULL,
    email           WL_EMAIL                                                                NOT NULL,
    password        TEXT,
    active_team     UUID,
    avatar_url      TEXT,
    setup_completed BOOLEAN                  DEFAULT FALSE                                  NOT NULL,
    user_no         BIGINT                   DEFAULT NEXTVAL('users_user_no_seq'::REGCLASS) NOT NULL,
    timezone_id     UUID                                                                    NOT NULL,
    google_id       TEXT,
    socket_id       TEXT,
    created_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP                      NOT NULL,
    updated_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP                      NOT NULL,
    last_active     TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP                      NOT NULL,
    temp_email      BOOLEAN                  DEFAULT FALSE,
    is_deleted      BOOLEAN                  DEFAULT FALSE,
    deleted_at      TIMESTAMP WITH TIME ZONE,
    language        LANGUAGE_TYPE            DEFAULT 'en'::LANGUAGE_TYPE
);

ALTER TABLE users
    ADD CONSTRAINT users_pk
        PRIMARY KEY (id);

ALTER TABLE archived_projects
    ADD CONSTRAINT archived_projects_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE favorite_projects
    ADD CONSTRAINT favorite_projects_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE licensing_coupon_codes
    ADD CONSTRAINT licensing_coupon_codes_users_id_fk
        FOREIGN KEY (redeemed_by) REFERENCES users;

ALTER TABLE licensing_credit_subs
    ADD CONSTRAINT licensing_credit_subs_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE licensing_custom_subs
    ADD CONSTRAINT licensing_custom_subs_users_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE licensing_payment_details
    ADD CONSTRAINT licensing_payment_details_users_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE licensing_user_subscriptions
    ADD CONSTRAINT licensing_user_subscriptions_users_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE notification_settings
    ADD CONSTRAINT notification_settings_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users
            ON DELETE CASCADE;

ALTER TABLE organizations
    ADD CONSTRAINT organization_user_id_pk
        FOREIGN KEY (user_id) REFERENCES users
            ON DELETE CASCADE;

ALTER TABLE personal_todo_list
    ADD CONSTRAINT personal_todo_list_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE project_categories
    ADD CONSTRAINT project_categories_created_by_fk
        FOREIGN KEY (created_by) REFERENCES users;

ALTER TABLE project_comment_mentions
    ADD CONSTRAINT project_comment_mentions_informed_by_fk
        FOREIGN KEY (informed_by) REFERENCES users;

ALTER TABLE project_comment_mentions
    ADD CONSTRAINT project_comment_mentions_mentioned_by_fk
        FOREIGN KEY (mentioned_by) REFERENCES users;

ALTER TABLE project_comments
    ADD CONSTRAINT project_comments_created_by_fk
        FOREIGN KEY (created_by) REFERENCES users;

ALTER TABLE project_folders
    ADD CONSTRAINT project_folders_created_by_fk
        FOREIGN KEY (created_by) REFERENCES users;

ALTER TABLE project_subscribers
    ADD CONSTRAINT project_subscribers_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE projects
    ADD CONSTRAINT projects_owner_id_fk
        FOREIGN KEY (owner_id) REFERENCES users;

ALTER TABLE task_activity_logs
    ADD CONSTRAINT task_activity_logs_users_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE task_attachments
    ADD CONSTRAINT task_attachments_uploaded_by_fk
        FOREIGN KEY (uploaded_by) REFERENCES users;

ALTER TABLE task_comments
    ADD CONSTRAINT task_comments_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users
            ON DELETE CASCADE;

ALTER TABLE task_subscribers
    ADD CONSTRAINT task_subscribers_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE task_timers
    ADD CONSTRAINT task_timers_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users
            ON DELETE CASCADE;

ALTER TABLE task_updates
    ADD CONSTRAINT task_updates_reporter_id_fk
        FOREIGN KEY (reporter_id) REFERENCES users
            ON DELETE CASCADE;

ALTER TABLE task_updates
    ADD CONSTRAINT task_updates_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users
            ON DELETE CASCADE;

ALTER TABLE task_work_log
    ADD CONSTRAINT task_work_log_users_id_fk
        FOREIGN KEY (user_id) REFERENCES users
            ON DELETE CASCADE;

ALTER TABLE tasks
    ADD CONSTRAINT tasks_reporter_id_fk
        FOREIGN KEY (reporter_id) REFERENCES users;

ALTER TABLE tasks_assignees
    ADD CONSTRAINT tasks_assignees_assigned_by_fk
        FOREIGN KEY (assigned_by) REFERENCES users;

ALTER TABLE team_members
    ADD CONSTRAINT team_members_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE users
    ADD CONSTRAINT users_email_check
        CHECK (CHAR_LENGTH((email)::TEXT) <= 255);

ALTER TABLE users
    ADD CONSTRAINT users_name_check
        CHECK (CHAR_LENGTH(name) <= 55);

CREATE TABLE IF NOT EXISTS teams (
    id              UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name            TEXT                                                NOT NULL,
    user_id         UUID                                                NOT NULL,
    created_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    organization_id UUID
);

ALTER TABLE teams
    ADD CONSTRAINT teams_pk
        PRIMARY KEY (id);

ALTER TABLE clients
    ADD CONSTRAINT clients_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE cpt_task_statuses
    ADD CONSTRAINT cpt_task_statuses_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE custom_project_templates
    ADD CONSTRAINT custom_project_templates_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE email_invitations
    ADD CONSTRAINT email_invitations_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE job_titles
    ADD CONSTRAINT job_titles_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE notification_settings
    ADD CONSTRAINT notification_settings_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE project_categories
    ADD CONSTRAINT project_categories_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE project_folders
    ADD CONSTRAINT project_folders_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams;

ALTER TABLE project_logs
    ADD CONSTRAINT project_logs_teams_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE projects
    ADD CONSTRAINT projects_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE pt_task_statuses
    ADD CONSTRAINT pt_task_statuses_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE task_activity_logs
    ADD CONSTRAINT task_activity_logs_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE task_attachments
    ADD CONSTRAINT task_attachments_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE team_labels
    ADD CONSTRAINT team_labels_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE task_statuses
    ADD CONSTRAINT task_statuses_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE task_templates
    ADD CONSTRAINT task_templates_teams_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE task_updates
    ADD CONSTRAINT task_updates_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE team_members
    ADD CONSTRAINT team_members_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE users
    ADD CONSTRAINT users_active_team_fk
        FOREIGN KEY (active_team) REFERENCES teams;

ALTER TABLE teams
    ADD CONSTRAINT team_organization_id_pk
        FOREIGN KEY (organization_id) REFERENCES organizations;

ALTER TABLE teams
    ADD CONSTRAINT teams_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE teams
    ADD CONSTRAINT teams_name_check
        CHECK (CHAR_LENGTH(name) <= 55);

CREATE TABLE IF NOT EXISTS timezones (
    id         UUID DEFAULT uuid_generate_v4() NOT NULL,
    name       TEXT                            NOT NULL,
    abbrev     TEXT                            NOT NULL,
    utc_offset INTERVAL                        NOT NULL
);

ALTER TABLE timezones
    ADD CONSTRAINT timezones_pk
        PRIMARY KEY (id);

ALTER TABLE users
    ADD CONSTRAINT users_timezone_id_fk
        FOREIGN KEY (timezone_id) REFERENCES timezones;

CREATE TABLE IF NOT EXISTS user_notifications (
    id         UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    message    TEXT                                                NOT NULL,
    user_id    UUID                                                NOT NULL,
    team_id    UUID                                                NOT NULL,
    read       BOOLEAN                  DEFAULT FALSE              NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    task_id    UUID,
    project_id UUID
);

ALTER TABLE user_notifications
    ADD CONSTRAINT user_notifications_pk
        PRIMARY KEY (id);

ALTER TABLE user_notifications
    ADD CONSTRAINT user_notifications_project_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE user_notifications
    ADD CONSTRAINT user_notifications_task_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

ALTER TABLE user_notifications
    ADD CONSTRAINT user_notifications_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE user_notifications
    ADD CONSTRAINT user_notifications_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

CREATE TABLE IF NOT EXISTS users_data (
    user_id                  UUID                           NOT NULL,
    organization_name        TEXT                           NOT NULL,
    contact_number           TEXT,
    contact_number_secondary TEXT,
    address_line_1           TEXT,
    address_line_2           TEXT,
    country                  UUID,
    city                     TEXT,
    state                    TEXT,
    postal_code              TEXT,
    trial_in_progress        BOOLEAN DEFAULT FALSE          NOT NULL,
    trial_expire_date        DATE,
    subscription_status      TEXT    DEFAULT 'active'::TEXT NOT NULL,
    storage                  INTEGER DEFAULT 1              NOT NULL,
    updating_plan            BOOLEAN DEFAULT FALSE
);

ALTER TABLE users_data
    ADD UNIQUE (user_id);

ALTER TABLE users_data
    ADD CONSTRAINT users_data_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users
            ON DELETE CASCADE;

ALTER TABLE users_data
    ADD CONSTRAINT users_data_users_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

CREATE TABLE IF NOT EXISTS worklenz_alerts (
    description TEXT NOT NULL,
    type        TEXT NOT NULL,
    active      BOOLEAN DEFAULT FALSE
);

ALTER TABLE worklenz_alerts
    ADD CONSTRAINT worklenz_alerts_type_check
        CHECK (type = ANY (ARRAY ['success'::TEXT, 'info'::TEXT, 'warning'::TEXT, 'error'::TEXT]));

CREATE TABLE IF NOT EXISTS licensing_coupon_logs (
    id          UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    coupon_code TEXT                                                NOT NULL,
    redeemed_by UUID                                                NOT NULL,
    redeemed_at TIMESTAMP WITH TIME ZONE                            NOT NULL,
    is_refunded BOOLEAN                  DEFAULT TRUE               NOT NULL,
    reason      TEXT,
    reverted_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    feedback    TEXT
);

ALTER TABLE licensing_coupon_logs
    ADD CONSTRAINT licensing_coupon_logs_pk
        PRIMARY KEY (id);

ALTER TABLE licensing_coupon_logs
    ADD CONSTRAINT licensing_coupon_logs_users_id_fk
        FOREIGN KEY (redeemed_by) REFERENCES users;

CREATE TABLE IF NOT EXISTS sys_license_types (
    id          UUID DEFAULT uuid_generate_v4() NOT NULL,
    name        TEXT                            NOT NULL,
    key         TEXT                            NOT NULL,
    description TEXT
);

ALTER TABLE sys_license_types
    ADD PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS task_comment_mentions (
    comment_id      UUID                                               NOT NULL,
    mentioned_index INTEGER                  DEFAULT 0                 NOT NULL,
    mentioned_by    UUID                                               NOT NULL,
    informed_by     UUID                                               NOT NULL,
    created_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL
);

ALTER TABLE task_comment_mentions
    ADD CONSTRAINT task_comment_mentions_comment_id_fk
        FOREIGN KEY (comment_id) REFERENCES task_comments
            ON DELETE CASCADE;

ALTER TABLE task_comment_mentions
    ADD CONSTRAINT task_comment_mentions_mentioned_by_fk
        FOREIGN KEY (mentioned_by) REFERENCES users;

ALTER TABLE task_comment_mentions
    ADD CONSTRAINT task_comment_mentions_informed_by_fk
        FOREIGN KEY (informed_by) REFERENCES team_members
            ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS email_logs (
    id         UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    email      TEXT                                                NOT NULL,
    subject    TEXT                                                NOT NULL,
    html       TEXT                                                NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS task_comment_reactions (
    id             UUID                     DEFAULT uuid_generate_v4()     NOT NULL,
    comment_id     UUID                                                    NOT NULL,
    user_id        UUID                                                    NOT NULL,
    team_member_id UUID                                                    NOT NULL,
    reaction_type  REACTION_TYPES           DEFAULT 'like'::REACTION_TYPES NOT NULL,
    created_at     TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

ALTER TABLE task_comment_reactions
    ADD CONSTRAINT task_comment_reactions_pk
        PRIMARY KEY (id);

ALTER TABLE task_comment_reactions
    ADD CONSTRAINT task_comment_reactions_user_id_fk
        FOREIGN KEY (user_id) REFERENCES users;

ALTER TABLE task_comment_reactions
    ADD CONSTRAINT task_comment_reactions_comment_id_fk
        FOREIGN KEY (comment_id) REFERENCES task_comments
            ON DELETE CASCADE;

ALTER TABLE task_comment_reactions
    ADD CONSTRAINT task_comment_reactions_team_member_id_fk
        FOREIGN KEY (team_member_id) REFERENCES team_members
            ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS task_dependencies (
    id              UUID                     DEFAULT uuid_generate_v4()            NOT NULL,
    task_id         UUID                                                           NOT NULL,
    related_task_id UUID                                                           NOT NULL,
    dependency_type DEPENDENCY_TYPE          DEFAULT 'blocked_by'::DEPENDENCY_TYPE NOT NULL,
    created_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

ALTER TABLE task_dependencies
    ADD CONSTRAINT task_dependencies_pk
        PRIMARY KEY (id);

ALTER TABLE task_dependencies
    ADD CONSTRAINT task_dependencies_unique_key
        UNIQUE (task_id, related_task_id, dependency_type);

ALTER TABLE task_dependencies
    ADD CONSTRAINT task_dependencies_tasks_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

ALTER TABLE task_dependencies
    ADD CONSTRAINT task_dependencies_tasks_id_fk_2
        FOREIGN KEY (related_task_id) REFERENCES tasks
            ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS task_recurring_schedules (
    id              UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    schedule_type   SCHEDULE_TYPE            DEFAULT 'daily'::SCHEDULE_TYPE,
    days_of_week    INTEGER[],
    day_of_month    INTEGER,
    week_of_month   INTEGER,
    interval_days   INTEGER,
    interval_weeks  INTEGER,
    interval_months INTEGER,
    start_date      DATE,
    end_date        DATE,
    created_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

ALTER TABLE task_recurring_schedules
    ADD CONSTRAINT task_recurring_schedules_pk
        PRIMARY KEY (id);

CREATE TABLE IF NOT EXISTS task_recurring_templates (
    id          UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    task_id     UUID                                                NOT NULL,
    schedule_id UUID                                                NOT NULL,
    name        TEXT                                                NOT NULL,
    description TEXT,
    end_date    TIMESTAMP WITH TIME ZONE,
    priority_id UUID                                                NOT NULL,
    project_id  UUID                                                NOT NULL,
    assignees   JSONB,
    labels      JSONB,
    created_at  TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

ALTER TABLE task_recurring_templates
    ADD CONSTRAINT task_recurring_templates_projects_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE task_recurring_templates
    ADD CONSTRAINT task_recurring_templates_task_priorities_id_fk
        FOREIGN KEY (priority_id) REFERENCES task_priorities;

ALTER TABLE task_recurring_templates
    ADD CONSTRAINT task_recurring_templates_task_recurring_schedules_id_fk
        FOREIGN KEY (schedule_id) REFERENCES task_recurring_schedules
            ON DELETE CASCADE;

ALTER TABLE task_recurring_templates
    ADD CONSTRAINT task_recurring_templates_tasks_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS task_comment_attachments (
    id         UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    name       TEXT                                                NOT NULL,
    size       BIGINT                   DEFAULT 0                  NOT NULL,
    type       TEXT                                                NOT NULL,
    task_id    UUID                                                NOT NULL,
    comment_id UUID                                                NOT NULL,
    team_id    UUID                                                NOT NULL,
    project_id UUID                                                NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE task_comment_attachments
    ADD CONSTRAINT task_comment_attachments_pk
        PRIMARY KEY (id);

ALTER TABLE task_comment_attachments
    ADD CONSTRAINT task_comment_attachments_comment_id_fk
        FOREIGN KEY (comment_id) REFERENCES task_comments
            ON DELETE CASCADE;

ALTER TABLE task_comment_attachments
    ADD CONSTRAINT task_comment_attachments_project_id_fk
        FOREIGN KEY (project_id) REFERENCES projects
            ON DELETE CASCADE;

ALTER TABLE task_comment_attachments
    ADD CONSTRAINT task_comment_attachments_task_id_fk
        FOREIGN KEY (task_id) REFERENCES tasks
            ON DELETE CASCADE;

ALTER TABLE task_comment_attachments
    ADD CONSTRAINT task_comment_attachments_team_id_fk
        FOREIGN KEY (team_id) REFERENCES teams
            ON DELETE CASCADE;

ALTER TABLE task_comment_attachments
    ADD CONSTRAINT task_comment_attachments_name_check
        CHECK (CHAR_LENGTH(name) <= 100);

CREATE TABLE IF NOT EXISTS cc_custom_columns (
    id               UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    project_id       UUID                                                NOT NULL,
    name             TEXT                                                NOT NULL,
    key              TEXT                                                NOT NULL,
    field_type       TEXT                                                NOT NULL,
    width            INTEGER                  DEFAULT 150,
    is_visible       BOOLEAN                  DEFAULT TRUE,
    is_custom_column BOOLEAN                  DEFAULT TRUE,
    created_at       TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at       TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

ALTER TABLE cc_custom_columns
    ADD PRIMARY KEY (id);

ALTER TABLE cc_custom_columns
    ADD UNIQUE (project_id, key);

ALTER TABLE cc_custom_columns
    ADD FOREIGN KEY (project_id) REFERENCES projects
        ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS cc_column_configurations (
    id                        UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    column_id                 UUID                                                NOT NULL,
    field_title               TEXT,
    field_type                TEXT,
    number_type               TEXT,
    decimals                  INTEGER,
    label                     TEXT,
    label_position            TEXT,
    preview_value             TEXT,
    expression                TEXT,
    first_numeric_column_key  TEXT,
    second_numeric_column_key TEXT,
    created_at                TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at                TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

ALTER TABLE cc_column_configurations
    ADD PRIMARY KEY (id);

ALTER TABLE cc_column_configurations
    ADD FOREIGN KEY (column_id) REFERENCES cc_custom_columns
        ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS cc_selection_options (
    id              UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    column_id       UUID                                                NOT NULL,
    selection_id    TEXT                                                NOT NULL,
    selection_name  TEXT                                                NOT NULL,
    selection_color TEXT,
    selection_order INTEGER                                             NOT NULL,
    created_at      TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at      TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

ALTER TABLE cc_selection_options
    ADD PRIMARY KEY (id);

ALTER TABLE cc_selection_options
    ADD FOREIGN KEY (column_id) REFERENCES cc_custom_columns
        ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS cc_label_options (
    id          UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    column_id   UUID                                                NOT NULL,
    label_id    TEXT                                                NOT NULL,
    label_name  TEXT                                                NOT NULL,
    label_color TEXT,
    label_order INTEGER                                             NOT NULL,
    created_at  TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at  TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

ALTER TABLE cc_label_options
    ADD PRIMARY KEY (id);

ALTER TABLE cc_label_options
    ADD FOREIGN KEY (column_id) REFERENCES cc_custom_columns
        ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS cc_column_values (
    id            UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    task_id       UUID                                                NOT NULL,
    column_id     UUID                                                NOT NULL,
    text_value    TEXT,
    number_value  NUMERIC(18, 6),
    date_value    TIMESTAMP WITH TIME ZONE,
    boolean_value BOOLEAN,
    json_value    JSONB,
    created_at    TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at    TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

ALTER TABLE cc_column_values
    ADD PRIMARY KEY (id);

ALTER TABLE cc_column_values
    ADD UNIQUE (task_id, column_id);

ALTER TABLE cc_column_values
    ADD FOREIGN KEY (task_id) REFERENCES tasks
        ON DELETE CASCADE;

ALTER TABLE cc_column_values
    ADD FOREIGN KEY (column_id) REFERENCES cc_custom_columns
        ON DELETE CASCADE;

CREATE TABLE IF NOT EXISTS organization_working_days (
    id              UUID                     DEFAULT uuid_generate_v4() NOT NULL,
    monday          BOOLEAN                  DEFAULT TRUE               NOT NULL,
    tuesday         BOOLEAN                  DEFAULT TRUE               NOT NULL,
    wednesday       BOOLEAN                  DEFAULT TRUE               NOT NULL,
    thursday        BOOLEAN                  DEFAULT TRUE               NOT NULL,
    friday          BOOLEAN                  DEFAULT TRUE               NOT NULL,
    saturday        BOOLEAN                  DEFAULT FALSE              NOT NULL,
    sunday          BOOLEAN                  DEFAULT FALSE              NOT NULL,
    organization_id UUID                                                NOT NULL,
    created_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL,
    updated_at      TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP  NOT NULL
);

ALTER TABLE organization_working_days
    ADD CONSTRAINT organization_working_days_pk
        PRIMARY KEY (id);

ALTER TABLE organization_working_days
    ADD CONSTRAINT org_organization_id_fk
        FOREIGN KEY (organization_id) REFERENCES organizations;
