-- Test using collection and icollection together to ensure no interaction problems

-- Test 1: Use both types in same DO block
DO $$
DECLARE
    c collection('text');
    ic icollection('text');
BEGIN
    c['key1'] := 'collection value';
    ic[1] := 'icollection value';
    
    RAISE NOTICE 'collection: %', c['key1'];
    RAISE NOTICE 'icollection: %', ic[1];
    RAISE NOTICE 'collection count: %', count(c);
    RAISE NOTICE 'icollection count: %', count(ic);
END $$;

-- Test 2: Iterate both types in same block
DO $$
DECLARE
    c collection('int4');
    ic icollection('int4');
BEGIN
    c['a'] := 1;
    c['b'] := 2;
    ic[10] := 100;
    ic[20] := 200;
    
    c := first(c);
    WHILE NOT isnull(c) LOOP
        RAISE NOTICE 'collection key: %, value: %', key(c), value(c);
        c := next(c);
    END LOOP;
    
    ic := first(ic);
    WHILE NOT isnull(ic) LOOP
        RAISE NOTICE 'icollection key: %, value: %', key(ic), value(ic);
        ic := next(ic);
    END LOOP;
END $$;

-- Test 3: Copy and sort both types
DO $$
DECLARE
    c1 collection('text');
    c2 collection('text');
    ic1 icollection('text');
    ic2 icollection('text');
BEGIN
    c1['z'] := 'last';
    c1['a'] := 'first';
    c2 := copy(c1);
    c2 := sort(c2);
    
    ic1[3] := 'third';
    ic1[1] := 'first';
    ic2 := copy(ic1);
    ic2 := sort(ic2);
    
    RAISE NOTICE 'collection sorted first key: %', first_key(c2);
    RAISE NOTICE 'icollection sorted first key: %', first_key(ic2);
END $$;

-- Test 4: Table functions for both types
SELECT 'collection keys' as type, * FROM keys_to_table(add(add('{}'::collection, 'a', 'val1'::text), 'b', 'val2'::text)) ORDER BY 1;
SELECT 'icollection keys' as type, * FROM keys_to_table(add(add('{}'::icollection, 1, 'val1'::text), 2, 'val2'::text)) ORDER BY 1;

-- Test 5: NULL handling in both types
DO $$
DECLARE
    c collection('text');
    ic icollection('text');
BEGIN
    c['key1'] := NULL;
    ic[1] := NULL;
    
    RAISE NOTICE 'collection has NULL: %', exist(c, 'key1');
    RAISE NOTICE 'icollection has NULL: %', exist(ic, 1);
END $$;

-- Test 6: Key navigation for both types
DO $$
DECLARE
    c collection('text');
    ic icollection('text');
BEGIN
    c['a'] := 'first';
    c['b'] := 'second';
    c['c'] := 'third';
    
    ic[1] := 'first';
    ic[2] := 'second';
    ic[3] := 'third';
    
    RAISE NOTICE 'collection next_key(a): %', next_key(c, 'a');
    RAISE NOTICE 'icollection next_key(1): %', next_key(ic, 1);
    RAISE NOTICE 'collection last_key: %', last_key(c);
    RAISE NOTICE 'icollection last_key: %', last_key(ic);
END $$;

-- Test 7: Delete operations on both types
DO $$
DECLARE
    c collection('text');
    ic icollection('text');
BEGIN
    c['a'] := 'val1';
    c['b'] := 'val2';
    c := delete(c, 'a');
    
    ic[1] := 'val1';
    ic[2] := 'val2';
    ic := delete(ic, 1);
    
    RAISE NOTICE 'collection count after delete: %', count(c);
    RAISE NOTICE 'icollection count after delete: %', count(ic);
END $$;

-- Test 8: JSON parsing for both types
SELECT count('{"value_type":"text","entries":{"a":"hello","b":"world"}}'::collection);
SELECT count('{"value_type":"text","entries":{"1":"hello","2":"world"}}'::icollection);

-- Test 9: Mixed operations in procedure
CREATE OR REPLACE PROCEDURE test_mixed_types(INOUT c collection, INOUT ic icollection)
LANGUAGE plpgsql
AS $$
BEGIN
    c['new'] := 'added';
    ic[99] := 'added';
END $$;

DO $$
DECLARE
    c collection('text');
    ic icollection('text');
BEGIN
    c['orig'] := 'original';
    ic[1] := 'original';
    
    CALL test_mixed_types(c, ic);
    
    RAISE NOTICE 'collection count: %', count(c);
    RAISE NOTICE 'icollection count: %', count(ic);
END $$;

DROP PROCEDURE test_mixed_types;

-- Test 10: Value type checking for both
DO $$
DECLARE
    c collection('int4');
    ic icollection('int4');
BEGIN
    c['key'] := 42;
    ic[1] := 42;
    
    RAISE NOTICE 'collection value_type: %', value_type(c);
    RAISE NOTICE 'icollection value_type: %', value_type(ic);
END $$;

-- Text-fallback coercion: store date, retrieve as text
DO $$
DECLARE
  c  collection('date');
  ic icollection('date');
  vt text;
BEGIN
  c := add(c, 'k', '2026-03-06'::date);
  vt := find(c, 'k');
  RAISE NOTICE 'collection date->text: %', vt;

  ic := add(ic, 1, '2026-03-06'::date);
  vt := find(ic, 1);
  RAISE NOTICE 'icollection date->text: %', vt;
END $$;

-- Text-fallback coercion via subscript
DO $$
DECLARE
  c  collection('date');
  vt text;
BEGIN
  c['k'] := '2026-03-06'::date;
  vt := c['k'];
  RAISE NOTICE 'subscript date->text: %', vt;
END $$;

-- copy() with NULL values
DO $$
DECLARE
  c  collection;
  c2 collection;
  ic  icollection;
  ic2 icollection;
BEGIN
  c := add(c, 'a', 'real');
  c := add(c, 'b', null::text);
  c := add(c, 'c', 'also real');
  c2 := copy(c);
  ASSERT c::text = c2::text,
    format('copy with nulls failed: orig=%s copy=%s', c, c2);

  ic := add(ic, 1, 'real');
  ic := add(ic, 2, null::text);
  ic := add(ic, 3, 'also real');
  ic2 := copy(ic);
  ASSERT ic::text = ic2::text,
    format('ic copy with nulls failed: orig=%s copy=%s', ic, ic2);
END $$;
