--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements.  See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership.  The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"). You may not use this file except in compliance
-- with the License.  You may obtain a copy of the License at
--
--  http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied.  See the License for the
-- specific language governing permissions and limitations
-- under the License.
--

ALTER TABLE user_meta  ADD COLUMN IF NOT EXISTS updated_at BIGINT NOT NULL DEFAULT 0;
ALTER TABLE role_meta ADD COLUMN IF NOT EXISTS updated_at BIGINT NOT NULL DEFAULT 0;
ALTER TABLE owner_meta ADD COLUMN IF NOT EXISTS updated_at BIGINT NOT NULL DEFAULT 0;
ALTER TABLE group_meta ADD COLUMN IF NOT EXISTS updated_at BIGINT NOT NULL DEFAULT 0;
COMMENT ON COLUMN user_meta.updated_at IS 'updated at';
COMMENT ON COLUMN role_meta.updated_at IS 'updated at';
COMMENT ON COLUMN owner_meta.updated_at IS 'updated at';
COMMENT ON COLUMN group_meta.updated_at IS 'updated at';

CREATE INDEX IF NOT EXISTS idx_user_meta_name_del_upd ON user_meta (metalake_id, user_name, deleted_at, updated_at);
CREATE INDEX IF NOT EXISTS idx_owner_meta_del_upd_obj ON owner_meta (deleted_at, updated_at, metadata_object_id);
CREATE INDEX IF NOT EXISTS idx_group_meta_name_del_upd ON group_meta (metalake_id, group_name, deleted_at, updated_at);

CREATE TABLE IF NOT EXISTS entity_change_log (
    id BIGSERIAL PRIMARY KEY,
    metalake_name VARCHAR(128) NOT NULL,
    entity_type VARCHAR(32) NOT NULL,
    entity_full_name VARCHAR(512) NOT NULL,
    -- Operate type code: 1=ALTER, 2=DROP, 3=INSERT. Codes are stable and never re-used.
    operate_type SMALLINT NOT NULL,
    created_at BIGINT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_ecl_created_at ON entity_change_log(created_at);
COMMENT ON TABLE entity_change_log IS 'Append-only log of entity structural changes for targeted metadataIdCache invalidation';
COMMENT ON COLUMN entity_change_log.id IS 'auto increment id';
COMMENT ON COLUMN entity_change_log.metalake_name IS 'metalake name';
COMMENT ON COLUMN entity_change_log.entity_type IS 'METALAKE | CATALOG | SCHEMA | TABLE | FILESET | TOPIC | MODEL | VIEW';
COMMENT ON COLUMN entity_change_log.entity_full_name IS 'Dot-separated full name of the affected entity. For ALTER, stores the old name. For DROP, stores the entity name.';
COMMENT ON COLUMN entity_change_log.operate_type IS 'Operate type code: 1=ALTER, 2=DROP, 3=INSERT. Codes are stable and never re-used.';
COMMENT ON COLUMN entity_change_log.created_at IS 'timestamp of the change in millis';

ALTER TABLE view_meta
    ADD COLUMN IF NOT EXISTS audit_info TEXT NOT NULL DEFAULT '{}';

ALTER TABLE view_meta
    ALTER COLUMN audit_info DROP DEFAULT;

COMMENT ON COLUMN view_meta.audit_info IS 'view audit info';

CREATE TABLE IF NOT EXISTS view_version_info (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY,
    metalake_id BIGINT NOT NULL,
    catalog_id BIGINT NOT NULL,
    schema_id BIGINT NOT NULL,
    view_id BIGINT NOT NULL,
    version INT NOT NULL,
    view_comment TEXT,
    columns TEXT NOT NULL,
    properties TEXT,
    default_catalog VARCHAR(128),
    default_schema VARCHAR(128),
    representations TEXT NOT NULL,
    audit_info TEXT NOT NULL,
    deleted_at BIGINT NOT NULL DEFAULT 0,
    PRIMARY KEY (id),
    UNIQUE (view_id, version, deleted_at)
);

CREATE INDEX IF NOT EXISTS view_version_info_idx_metalake_id ON view_version_info (metalake_id);
CREATE INDEX IF NOT EXISTS view_version_info_idx_catalog_id ON view_version_info (catalog_id);
CREATE INDEX IF NOT EXISTS view_version_info_idx_schema_id ON view_version_info (schema_id);
COMMENT ON TABLE view_version_info IS 'view version info';

COMMENT ON COLUMN view_version_info.id IS 'auto increment id';
COMMENT ON COLUMN view_version_info.metalake_id IS 'metalake id';
COMMENT ON COLUMN view_version_info.catalog_id IS 'catalog id';
COMMENT ON COLUMN view_version_info.schema_id IS 'schema id';
COMMENT ON COLUMN view_version_info.view_id IS 'view id';
COMMENT ON COLUMN view_version_info.version IS 'view version';
COMMENT ON COLUMN view_version_info.view_comment IS 'view version comment';
COMMENT ON COLUMN view_version_info.columns IS 'view columns snapshot (JSON)';
COMMENT ON COLUMN view_version_info.properties IS 'view properties (JSON)';
COMMENT ON COLUMN view_version_info.default_catalog IS 'default catalog for view SQL resolution';
COMMENT ON COLUMN view_version_info.default_schema IS 'default schema for view SQL resolution';
COMMENT ON COLUMN view_version_info.representations IS 'view representations (JSON array)';
COMMENT ON COLUMN view_version_info.audit_info IS 'view version audit info';
COMMENT ON COLUMN view_version_info.deleted_at IS 'view version deleted at';

CREATE TABLE IF NOT EXISTS idp_user_meta (
    user_id BIGINT NOT NULL,
    user_name VARCHAR(128) NOT NULL,
    password_hash VARCHAR(1024) NOT NULL,
    current_version INT NOT NULL DEFAULT 1,
    last_version INT NOT NULL DEFAULT 1,
    deleted_at BIGINT NOT NULL DEFAULT 0,
    PRIMARY KEY (user_id),
    UNIQUE (user_name, deleted_at)
);
COMMENT ON TABLE idp_user_meta IS 'local IdP user metadata';

COMMENT ON COLUMN idp_user_meta.user_id IS 'idp user id';
COMMENT ON COLUMN idp_user_meta.user_name IS 'idp username';
COMMENT ON COLUMN idp_user_meta.password_hash IS 'idp user password hash';
COMMENT ON COLUMN idp_user_meta.current_version IS 'idp user current version';
COMMENT ON COLUMN idp_user_meta.last_version IS 'idp user last version';
COMMENT ON COLUMN idp_user_meta.deleted_at IS 'idp user deleted at';

CREATE TABLE IF NOT EXISTS idp_group_meta (
    group_id BIGINT NOT NULL,
    group_name VARCHAR(128) NOT NULL,
    current_version INT NOT NULL DEFAULT 1,
    last_version INT NOT NULL DEFAULT 1,
    deleted_at BIGINT NOT NULL DEFAULT 0,
    PRIMARY KEY (group_id),
    UNIQUE (group_name, deleted_at)
);
COMMENT ON TABLE idp_group_meta IS 'local IdP group metadata';

COMMENT ON COLUMN idp_group_meta.group_id IS 'idp group id';
COMMENT ON COLUMN idp_group_meta.group_name IS 'idp group name';
COMMENT ON COLUMN idp_group_meta.current_version IS 'idp group current version';
COMMENT ON COLUMN idp_group_meta.last_version IS 'idp group last version';
COMMENT ON COLUMN idp_group_meta.deleted_at IS 'idp group deleted at';

CREATE TABLE IF NOT EXISTS idp_user_group_rel (
    id BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY,
    user_id BIGINT NOT NULL,
    group_id BIGINT NOT NULL,
    current_version INT NOT NULL DEFAULT 1,
    last_version INT NOT NULL DEFAULT 1,
    deleted_at BIGINT NOT NULL DEFAULT 0,
    PRIMARY KEY (id),
    CONSTRAINT uk_iuig_del UNIQUE (user_id, group_id, deleted_at)
);
CREATE INDEX IF NOT EXISTS idp_user_group_rel_idx_iuig_uid ON idp_user_group_rel (user_id);
CREATE INDEX IF NOT EXISTS idp_user_group_rel_idx_iuig_gid ON idp_user_group_rel (group_id);
COMMENT ON TABLE idp_user_group_rel IS 'local IdP user group relation';

COMMENT ON COLUMN idp_user_group_rel.id IS 'auto increment id';
COMMENT ON COLUMN idp_user_group_rel.user_id IS 'idp user id';
COMMENT ON COLUMN idp_user_group_rel.group_id IS 'idp group id';
COMMENT ON COLUMN idp_user_group_rel.current_version IS 'idp relation current version';
COMMENT ON COLUMN idp_user_group_rel.last_version IS 'idp relation last version';
COMMENT ON COLUMN idp_user_group_rel.deleted_at IS 'idp relation deleted at';

CREATE TABLE IF NOT EXISTS iceberg_cleanup_job (
  id                BIGINT        NOT NULL PRIMARY KEY,
  catalog_id        BIGINT        NOT NULL,
  namespace         VARCHAR(512)  NOT NULL,
  table_name        VARCHAR(256)  NOT NULL,
  metadata_location TEXT          NOT NULL,
  file_io_impl      VARCHAR(256)  NOT NULL,
  file_io_props     TEXT          NOT NULL,
  state             VARCHAR(16)   NOT NULL,
  attempts          INT           NOT NULL DEFAULT 0,
  last_error        VARCHAR(2048),
  heartbeat_at      BIGINT        NOT NULL DEFAULT 0,
  created_by        VARCHAR(128)  NOT NULL,
  updated_at        BIGINT        NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_state_updated ON iceberg_cleanup_job (state, updated_at);
CREATE INDEX IF NOT EXISTS idx_object ON iceberg_cleanup_job (catalog_id, namespace, table_name, state);
COMMENT ON TABLE iceberg_cleanup_job IS 'async Iceberg table cleanup jobs';
COMMENT ON COLUMN iceberg_cleanup_job.id IS 'globally unique cleanup job id';
COMMENT ON COLUMN iceberg_cleanup_job.catalog_id IS 'globally unique id of the owning catalog, stable across catalog rename';
COMMENT ON COLUMN iceberg_cleanup_job.namespace IS 'namespace of the table to be cleaned up';
COMMENT ON COLUMN iceberg_cleanup_job.table_name IS 'name of the table to be cleaned up';
COMMENT ON COLUMN iceberg_cleanup_job.metadata_location IS 'location of the table metadata file to purge';
COMMENT ON COLUMN iceberg_cleanup_job.file_io_impl IS 'FileIO implementation class used to access the table files';
COMMENT ON COLUMN iceberg_cleanup_job.file_io_props IS 'JSON-encoded FileIO properties';
COMMENT ON COLUMN iceberg_cleanup_job.state IS 'PENDING | RUNNING | SUCCEEDED | FAILED';
COMMENT ON COLUMN iceberg_cleanup_job.attempts IS 'number of processing attempts made so far';
COMMENT ON COLUMN iceberg_cleanup_job.last_error IS 'truncated reason for the most recent failure, NULL until a job fails';
COMMENT ON COLUMN iceberg_cleanup_job.heartbeat_at IS 'last heartbeat from the worker, 0 when not running';
COMMENT ON COLUMN iceberg_cleanup_job.created_by IS 'principal that requested the drop (audit)';
COMMENT ON COLUMN iceberg_cleanup_job.updated_at IS 'last state change, drives poll ordering and old finished-job cleanup';
