
CREATE OR REPLACE FUNCTION assert_true(condition boolean, message text) RETURNS boolean AS $$
BEGIN
    ASSERT condition, message;
    RETURN true;
END;
$$ LANGUAGE plpgsql;

-- Test that self containment is true
SELECT
  assert_true(
    ste_vec_v1_logical_contains(
      ROW(
        ARRAY[
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry,
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
        ]
      )::cs_ste_vec_index_v1,
      ROW(
        ARRAY[
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry,
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
        ]
      )::cs_ste_vec_index_v1
    ),
    'expected to be contained but was not'
  );

-- Test that ciphertext values are ignored
SELECT
  assert_true(
    ste_vec_v1_logical_contains(
      ROW(
        ARRAY[
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'gergerger')::cs_ste_vec_v1_entry,
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'jhwfj2hjh')::cs_ste_vec_v1_entry
        ]
      )::cs_ste_vec_index_v1,
      ROW(
        ARRAY[
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'e1e11wnnn3313131')::cs_ste_vec_v1_entry,
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrfwe')::cs_ste_vec_v1_entry
        ]
      )::cs_ste_vec_index_v1
    ),
    'expected to be contained but was not'
  );

-- Test that a subset of a is contained itself
SELECT
  assert_true(
    ste_vec_v1_logical_contains(
      ROW(
        ARRAY[
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry,
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
        ]
      )::cs_ste_vec_index_v1,
      ROW(
        ARRAY[
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
        ]
      )::cs_ste_vec_index_v1
    ),
    'expected to be contained but was not'
  );

-- Test that a is not contained by b
SELECT
  assert_true(
    not ste_vec_v1_logical_contains(
      ROW(
        ARRAY[
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry,
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
        ]
      )::cs_ste_vec_index_v1,
      ROW(
        ARRAY[
          ROW('cat', ROW('dog'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
        ]
      )::cs_ste_vec_index_v1
    ),
    'expected to not be contained by was'
  );

-- Test that an empty vec is always contained
SELECT
  assert_true(
    ste_vec_v1_logical_contains(
      ROW(
        ARRAY[
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry,
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
        ]
      )::cs_ste_vec_index_v1,
      ROW(
        ARRAY[]::cs_ste_vec_v1_entry[]
      )::cs_ste_vec_index_v1
    ),
    'expected to not be contained by was'
  );

-- Test that an empty vec is always contained by an empty vec
SELECT
  assert_true(
    ste_vec_v1_logical_contains(
      ROW(
        ARRAY[]::cs_ste_vec_v1_entry[]
      )::cs_ste_vec_index_v1,
      ROW(
        ARRAY[]::cs_ste_vec_v1_entry[]
      )::cs_ste_vec_index_v1
    ),
    'expected to not be contained by was'
  );

--- Test that a superset of a is not contained by a
SELECT
  assert_true(
    not ste_vec_v1_logical_contains(
      ROW(
        ARRAY[
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry,
          ROW('cat', ROW('dog'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
        ]
      )::cs_ste_vec_index_v1,
      ROW(
        ARRAY[
          ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry,
          ROW('cat', ROW('dog'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry,
          ROW('bird', ROW('horse'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
        ]
      )::cs_ste_vec_index_v1
    ),
    'expected to not be contained but was'
  );



-- Test that self containment is true (using @>)
SELECT
  assert_true(
    ROW(
      ARRAY[
        ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry,
        ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
      ]
    )::cs_ste_vec_index_v1 @> ROW(
      ARRAY[
        ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry,
        ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
      ]
    )::cs_ste_vec_index_v1,
  'expected to be contained but was not'
);

-- Test contains is true (using @>)
SELECT
  assert_true(
    ROW(
      ARRAY[
        ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry,
        ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
      ]
    )::cs_ste_vec_index_v1 @> ROW(
      ARRAY[
        ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
      ]
    )::cs_ste_vec_index_v1,
  'expected to be contained but was not'
);

-- Test a is contained by b (using <@)
SELECT
  assert_true(
    ROW(
      ARRAY[
        ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
      ]
    )::cs_ste_vec_index_v1 <@ ROW(
      ARRAY[
        ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry,
        ROW('foo', ROW('bar'::bytea)::ore_cllw_8_v1, 'encrypted')::cs_ste_vec_v1_entry
      ]
    )::cs_ste_vec_index_v1,
  'expected to be contained but was not'
);

-- Test containment with json conversion function
SELECT
  assert_true(
    jsonb_to_cs_ste_vec_index_v1(
      '[
        ["foo", "bar", "ciphertext1"],
        ["foo", "bar", "ciphertext2"]
      ]'::jsonb
    ) @> jsonb_to_cs_ste_vec_index_v1(
      '[
        ["foo", "bar", "ciphertext3"]
    ]'::jsonb
  ),
  'expected to be contained but was not'
);


-- NEXT STEPS:
-- X Create a CAST
-- X Update the EQL functions to get an SteVec from a cipherstash value
-- Add some more E2E tests in Ruby

-- TODO: Handle this error from attempting to create PG index in Ruby tests:
--   PG::UndefinedObject: ERROR:  data type cs_ste_vec_index_v1 has no default operator class for access method "gin"
--  HINT:  You must specify an operator class for the index or define a default operator class for the data type.
