CREATE TABLE IF NOT EXISTS schema_migrations (
    version BIGINT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    applied_at TIMESTAMPTZ NOT NULL
);

CREATE TABLE authorization_subjects (
    id UUID PRIMARY KEY,
    platform_name VARCHAR(128) NOT NULL,
    workspace VARCHAR(128) NOT NULL,
    created_at TIMESTAMPTZ NOT NULL,
    updated_at TIMESTAMPTZ NOT NULL,
    CONSTRAINT authorization_subjects_platform_workspace_key
        UNIQUE (platform_name, workspace),
    CONSTRAINT authorization_subjects_platform_name_not_blank
        CHECK (btrim(platform_name) <> '' AND platform_name = btrim(platform_name)),
    CONSTRAINT authorization_subjects_workspace_not_blank
        CHECK (btrim(workspace) <> '' AND workspace = btrim(workspace)),
    CONSTRAINT authorization_subjects_platform_name_no_control
        CHECK (platform_name !~ '[[:cntrl:]]'),
    CONSTRAINT authorization_subjects_workspace_no_control
        CHECK (workspace !~ '[[:cntrl:]]')
);

CREATE TABLE signing_keys (
    id UUID PRIMARY KEY,
    public_key BYTEA NOT NULL,
    certificate_json JSONB NOT NULL,
    fingerprint_sha256 CHAR(64) NOT NULL,
    status VARCHAR(16) NOT NULL,
    activated_at TIMESTAMPTZ NOT NULL,
    retired_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ NOT NULL,
    CONSTRAINT signing_keys_fingerprint_sha256_key
        UNIQUE (fingerprint_sha256),
    CONSTRAINT signing_keys_status_check
        CHECK (status IN ('active', 'retired')),
    CONSTRAINT signing_keys_public_key_length_check
        CHECK (octet_length(public_key) = 32),
    CONSTRAINT signing_keys_fingerprint_length_check
        CHECK (fingerprint_sha256::text ~ '^[0-9A-F]{64}$')
);

CREATE TABLE licence_issuances (
    id UUID PRIMARY KEY,
    subject_id UUID NOT NULL,
    issuance_type VARCHAR(16) NOT NULL,
    previous_licence_id UUID,
    valid_from DATE NOT NULL,
    expires_on DATE NOT NULL,
    max_database BIGINT NOT NULL,
    max_middleware BIGINT NOT NULL,
    max_network_device BIGINT NOT NULL,
    max_security BIGINT NOT NULL,
    max_storage BIGINT NOT NULL,
    max_pc BIGINT NOT NULL,
    max_server BIGINT NOT NULL,
    max_user BIGINT NOT NULL,
    max_role BIGINT NOT NULL,
    max_permission BIGINT NOT NULL,
    max_menu BIGINT NOT NULL,
    signing_key_id UUID NOT NULL,
    payload_json JSONB NOT NULL,
    file_content BYTEA NOT NULL,
    issued_at TIMESTAMPTZ NOT NULL,
    operator_name VARCHAR(128) NOT NULL,
    CONSTRAINT licence_issuances_id_subject_key
        UNIQUE (id, subject_id),
    CONSTRAINT licence_issuances_subject_id_fkey
        FOREIGN KEY (subject_id)
        REFERENCES authorization_subjects (id)
        ON DELETE RESTRICT,
    CONSTRAINT licence_issuances_signing_key_id_fkey
        FOREIGN KEY (signing_key_id)
        REFERENCES signing_keys (id)
        ON DELETE RESTRICT,
    CONSTRAINT licence_issuances_previous_subject_fkey
        FOREIGN KEY (previous_licence_id, subject_id)
        REFERENCES licence_issuances (id, subject_id)
        ON DELETE RESTRICT,
    CONSTRAINT licence_issuances_type_check
        CHECK (issuance_type IN ('issue', 'renewal')),
    CONSTRAINT licence_issuances_dates_check
        CHECK (valid_from <= expires_on),
    CONSTRAINT licence_issuances_previous_check
        CHECK (
            (issuance_type = 'issue' AND previous_licence_id IS NULL) OR
            (issuance_type = 'renewal' AND previous_licence_id IS NOT NULL)
        ),
    CONSTRAINT licence_issuances_max_database_non_negative_check
        CHECK (max_database >= 0),
    CONSTRAINT licence_issuances_max_middleware_non_negative_check
        CHECK (max_middleware >= 0),
    CONSTRAINT licence_issuances_max_network_device_non_negative_check
        CHECK (max_network_device >= 0),
    CONSTRAINT licence_issuances_max_security_non_negative_check
        CHECK (max_security >= 0),
    CONSTRAINT licence_issuances_max_storage_non_negative_check
        CHECK (max_storage >= 0),
    CONSTRAINT licence_issuances_max_pc_non_negative_check
        CHECK (max_pc >= 0),
    CONSTRAINT licence_issuances_max_server_non_negative_check
        CHECK (max_server >= 0),
    CONSTRAINT licence_issuances_max_user_non_negative_check
        CHECK (max_user >= 0),
    CONSTRAINT licence_issuances_max_role_non_negative_check
        CHECK (max_role >= 0),
    CONSTRAINT licence_issuances_max_permission_non_negative_check
        CHECK (max_permission >= 0),
    CONSTRAINT licence_issuances_max_menu_non_negative_check
        CHECK (max_menu >= 0)
);

CREATE UNIQUE INDEX signing_keys_one_active_idx
ON signing_keys ((status))
WHERE status = 'active';

CREATE INDEX authorization_subjects_created_at_idx
ON authorization_subjects (created_at DESC, id DESC);

CREATE INDEX licence_issuances_issued_at_idx
ON licence_issuances (issued_at DESC, id DESC);

CREATE INDEX licence_issuances_subject_issued_at_idx
ON licence_issuances (subject_id, issued_at DESC, id DESC);

CREATE INDEX licence_issuances_expires_on_idx
ON licence_issuances (expires_on, id);

CREATE INDEX licence_issuances_previous_licence_id_idx
ON licence_issuances (previous_licence_id)
WHERE previous_licence_id IS NOT NULL;

CREATE INDEX licence_issuances_signing_key_id_idx
ON licence_issuances (signing_key_id);
