-- pgTAP: item_tags + shopping_item_tags structural invariants (Fase 11)
-- Run with: psql -U postgres -d postgres -f supabase/tests/014_item_tags.sql
--
-- These pgTAP assertions verify schema-level invariants only (publication
-- membership, REPLICA IDENTITY, unique constraint, cascade behaviour). The
-- per-role RLS semantics (member can insert, non-member denied, cross-
-- collective attach rejected) are covered by the Vitest integration suite
-- (packages/test-utils/tests/rls-item-tags.test.ts) which connects as an
-- authenticated role — pgTAP runs as postgres which bypasses RLS.

CREATE EXTENSION IF NOT EXISTS pgtap;

BEGIN;
SELECT plan(8);

-- T-01: item_tags is in the supabase_realtime publication
SELECT ok(
    EXISTS (
        SELECT 1 FROM pg_publication_tables
        WHERE pubname = 'supabase_realtime'
        AND   schemaname = 'public'
        AND   tablename  = 'item_tags'
    ),
    'T-01: item_tags is part of the supabase_realtime publication'
);

-- T-02: shopping_item_tags is in the supabase_realtime publication
SELECT ok(
    EXISTS (
        SELECT 1 FROM pg_publication_tables
        WHERE pubname = 'supabase_realtime'
        AND   schemaname = 'public'
        AND   tablename  = 'shopping_item_tags'
    ),
    'T-02: shopping_item_tags is part of the supabase_realtime publication'
);

-- T-03: REPLICA IDENTITY FULL on item_tags
SELECT results_eq(
    $$ SELECT relreplident::text FROM pg_class c
       JOIN   pg_namespace n ON n.oid = c.relnamespace
       WHERE  n.nspname = 'public' AND c.relname = 'item_tags' $$,
    $$ VALUES ('f') $$,
    'T-03: item_tags has REPLICA IDENTITY FULL'
);

-- T-04: REPLICA IDENTITY FULL on shopping_item_tags
SELECT results_eq(
    $$ SELECT relreplident::text FROM pg_class c
       JOIN   pg_namespace n ON n.oid = c.relnamespace
       WHERE  n.nspname = 'public' AND c.relname = 'shopping_item_tags' $$,
    $$ VALUES ('f') $$,
    'T-04: shopping_item_tags has REPLICA IDENTITY FULL'
);

-- T-05: UNIQUE (collective_id, name) enforced
INSERT INTO public.item_tags (collective_id, name, color)
VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'pgtap-vegano', 'green');

SELECT throws_ok(
    $$ INSERT INTO public.item_tags (collective_id, name, color)
       VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'pgtap-vegano', 'red') $$,
    '23505',
    NULL,
    'T-05: (collective_id, name) unique constraint enforced'
);

-- T-06: color CHECK constraint rejects unknown palette entries
SELECT throws_ok(
    $$ INSERT INTO public.item_tags (collective_id, name, color)
       VALUES ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'pgtap-bad-color', 'rainbow') $$,
    '23514',
    NULL,
    'T-06: color CHECK constraint blocks values outside the 8-preset palette'
);

-- T-07: shopping_item_tags cascades on item_tags DELETE
INSERT INTO public.item_tags (id, collective_id, name, color)
VALUES (
    'eeeeeeee-1111-1111-1111-111111111111',
    'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
    'pgtap-cascade-tag',
    'sky'
);

INSERT INTO public.shopping_item_tags (item_id, tag_id)
SELECT id, 'eeeeeeee-1111-1111-1111-111111111111'
FROM   public.shopping_items
WHERE  list_id = 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'
ORDER BY sort_order
LIMIT 1;

DELETE FROM public.item_tags WHERE id = 'eeeeeeee-1111-1111-1111-111111111111';

SELECT is(
    (SELECT count(*)::int FROM public.shopping_item_tags
     WHERE tag_id = 'eeeeeeee-1111-1111-1111-111111111111'),
    0,
    'T-07: deleting a tag cascades shopping_item_tags rows'
);

-- T-08: deleting the collective cascades item_tags + shopping_item_tags
-- Build an isolated mini-tree: collective → list → item, plus a tag attached.
INSERT INTO public.collectives (id, name, emoji, created_by)
VALUES ('aaaaaaaa-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'pgtap-cascade-collective', '🧪', '11111111-1111-1111-1111-111111111111');

INSERT INTO public.collective_members (collective_id, user_id, role)
VALUES ('aaaaaaaa-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '11111111-1111-1111-1111-111111111111', 'admin');

INSERT INTO public.shopping_lists (id, collective_id, name, status, created_by)
VALUES (
    'bbbbbbbb-1111-1111-1111-111111111111',
    'aaaaaaaa-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
    'cascade list', 'active', '11111111-1111-1111-1111-111111111111'
);

INSERT INTO public.shopping_items (id, list_id, name, sort_order, created_by)
VALUES (
    'cccccccc-1111-1111-1111-111111111111',
    'bbbbbbbb-1111-1111-1111-111111111111',
    'cascade item', 0, '11111111-1111-1111-1111-111111111111'
);

INSERT INTO public.item_tags (id, collective_id, name, color)
VALUES ('eeeeeeee-2222-2222-2222-222222222222',
        'aaaaaaaa-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
        'cascade tag', 'pink');

INSERT INTO public.shopping_item_tags (item_id, tag_id)
VALUES ('cccccccc-1111-1111-1111-111111111111',
        'eeeeeeee-2222-2222-2222-222222222222');

DELETE FROM public.collectives WHERE id = 'aaaaaaaa-bbbb-bbbb-bbbb-bbbbbbbbbbbb';

SELECT ok(
    NOT EXISTS (SELECT 1 FROM public.item_tags WHERE id = 'eeeeeeee-2222-2222-2222-222222222222')
    AND NOT EXISTS (SELECT 1 FROM public.shopping_item_tags WHERE tag_id = 'eeeeeeee-2222-2222-2222-222222222222'),
    'T-08: deleting a collective cascades item_tags + shopping_item_tags'
);

SELECT * FROM finish();
ROLLBACK;
