CREATE TABLE IF NOT EXISTS ops.compliance_dictionaries (
    id                   BIGSERIAL PRIMARY KEY,
    code                 VARCHAR(64) NOT NULL,
    name                 VARCHAR(64) NOT NULL,
    platform_scope       VARCHAR(16) NOT NULL DEFAULT 'all',
    applicable_platforms TEXT[],
    default_level        VARCHAR(16) NOT NULL DEFAULT 'block',
    enabled              BOOLEAN NOT NULL DEFAULT TRUE,
    version              INT NOT NULL DEFAULT 1,
    description          TEXT,
    created_by           BIGINT,
    updated_by           BIGINT,
    created_at           TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at           TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    CONSTRAINT uk_compliance_dictionaries_code UNIQUE (code),
    CONSTRAINT ck_compliance_dictionary_platform_scope CHECK (platform_scope IN ('all', 'specific')),
    CONSTRAINT ck_compliance_dictionary_platforms CHECK (
        (platform_scope = 'all' AND (applicable_platforms IS NULL OR cardinality(applicable_platforms) = 0))
        OR
        (platform_scope = 'specific' AND cardinality(applicable_platforms) >= 1)
    ),
    CONSTRAINT ck_compliance_dictionary_default_level CHECK (default_level IN ('block', 'high', 'medium', 'info'))
);

CREATE INDEX IF NOT EXISTS idx_compliance_dictionaries_enabled_version
    ON ops.compliance_dictionaries (enabled, version, id);

CREATE TABLE IF NOT EXISTS ops.compliance_dictionary_terms (
    id             BIGSERIAL PRIMARY KEY,
    dictionary_id  BIGINT NOT NULL REFERENCES ops.compliance_dictionaries(id) ON DELETE CASCADE,
    match_type     VARCHAR(24) NOT NULL DEFAULT 'exact',
    pattern        TEXT NOT NULL,
    level_override VARCHAR(16),
    hint           TEXT,
    reference_law  TEXT,
    enabled        BOOLEAN NOT NULL DEFAULT TRUE,
    created_at     TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at     TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    CONSTRAINT ck_compliance_term_match_type CHECK (match_type IN ('exact', 'regex')),
    CONSTRAINT ck_compliance_term_level CHECK (level_override IS NULL OR level_override IN ('block', 'high', 'medium', 'info')),
    CONSTRAINT ck_compliance_term_pattern CHECK (char_length(trim(pattern)) > 0)
);

CREATE INDEX IF NOT EXISTS idx_compliance_terms_dictionary_enabled
    ON ops.compliance_dictionary_terms (dictionary_id, enabled, id);

CREATE TABLE IF NOT EXISTS ops.compliance_dictionary_versions (
    id            BIGSERIAL PRIMARY KEY,
    dictionary_id BIGINT NOT NULL REFERENCES ops.compliance_dictionaries(id) ON DELETE CASCADE,
    version       INT NOT NULL,
    snapshot      JSONB NOT NULL DEFAULT '{}'::jsonb,
    published_by  BIGINT,
    published_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    CONSTRAINT uk_compliance_dictionary_versions UNIQUE (dictionary_id, version)
);

CREATE INDEX IF NOT EXISTS idx_compliance_dictionary_versions_latest
    ON ops.compliance_dictionary_versions (dictionary_id, version DESC);

CREATE TABLE IF NOT EXISTS ops.compliance_policies (
    id                   BIGINT PRIMARY KEY DEFAULT 1,
    master_enabled       BOOLEAN NOT NULL DEFAULT TRUE,
    enforcement_mode     VARCHAR(24) NOT NULL DEFAULT 'mandatory',
    enabled_dictionaries JSONB NOT NULL DEFAULT '[]'::jsonb,
    llm_judge_enabled    BOOLEAN NOT NULL DEFAULT FALSE,
    llm_categories       JSONB NOT NULL DEFAULT '[]'::jsonb,
    revision             BIGINT NOT NULL DEFAULT 1,
    updated_by           BIGINT,
    created_at           TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at           TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    CONSTRAINT ck_compliance_policy_singleton CHECK (id = 1),
    CONSTRAINT ck_compliance_policy_mode CHECK (enforcement_mode IN ('mandatory', 'advisory', 'disabled'))
);

INSERT INTO ops.compliance_policies (
    id,
    master_enabled,
    enforcement_mode,
    enabled_dictionaries,
    llm_judge_enabled,
    llm_categories
)
VALUES (1, TRUE, 'mandatory', '[]'::jsonb, FALSE, '[]'::jsonb)
ON CONFLICT DO NOTHING;
