BEGIN;
SELECT plan(16);

-- ============================================================================
-- Setup Test Data
-- ============================================================================

DO $$
DECLARE
    test_user_id uuid := gen_random_uuid();
    tablo_no_etapes text;
    tablo_all_done text;
    tablo_in_progress text;
    tablo_mixed text;
    tablo_empty_etapes text;
    etape1_id text;
    etape2_id text;
    etape3_id text;
    etape4_id text;
    etape5_id text;
BEGIN
    -- Insert test user
    INSERT INTO auth.users (id, instance_id, aud, role, email, encrypted_password, email_confirmed_at, created_at, updated_at)
    VALUES 
        (test_user_id, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', 'status_test_' || test_user_id::text || '@test.com', 'encrypted', now(), now(), now())
    ON CONFLICT DO NOTHING;

    -- Insert test profile
    INSERT INTO public.profiles (id, email, first_name, last_name, short_user_id)
    VALUES 
        (test_user_id, 'status_test_' || test_user_id::text || '@test.com', 'Status', 'Test', substring(test_user_id::text from 1 for 8))
    ON CONFLICT DO NOTHING;

    -- Set JWT context
    PERFORM set_config('request.jwt.claims', json_build_object('sub', test_user_id::text)::text, true);

    -- Create test tablos
    -- Tablo 1: No etapes
    INSERT INTO public.tablos (owner_id, name, position)
    VALUES (test_user_id, 'Tablo No Etapes', 0)
    RETURNING id INTO tablo_no_etapes;

    -- Tablo 2: All etapes done
    INSERT INTO public.tablos (owner_id, name, position)
    VALUES (test_user_id, 'Tablo All Done', 1)
    RETURNING id INTO tablo_all_done;

    -- Tablo 3: Has in_progress tasks
    INSERT INTO public.tablos (owner_id, name, position)
    VALUES (test_user_id, 'Tablo In Progress', 2)
    RETURNING id INTO tablo_in_progress;

    -- Tablo 4: Mixed statuses
    INSERT INTO public.tablos (owner_id, name, position)
    VALUES (test_user_id, 'Tablo Mixed', 3)
    RETURNING id INTO tablo_mixed;

    -- Tablo 5: Etapes without child tasks
    INSERT INTO public.tablos (owner_id, name, position)
    VALUES (test_user_id, 'Tablo Empty Etapes', 4)
    RETURNING id INTO tablo_empty_etapes;

    -- Setup Tablo 2: All etapes done
    -- Etape 1 with all tasks done
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent)
    VALUES (tablo_all_done, 'Etape 1', 'done', 0, true)
    RETURNING id INTO etape1_id;

    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id)
    VALUES 
        (tablo_all_done, 'Task 1.1', 'done', 0, false, etape1_id),
        (tablo_all_done, 'Task 1.2', 'done', 1, false, etape1_id);

    -- Etape 2 with all tasks done
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent)
    VALUES (tablo_all_done, 'Etape 2', 'done', 1, true)
    RETURNING id INTO etape2_id;

    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id)
    VALUES 
        (tablo_all_done, 'Task 2.1', 'done', 0, false, etape2_id);

    -- Setup Tablo 3: Has in_progress tasks
    -- Etape 1 with in_progress task
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent)
    VALUES (tablo_in_progress, 'Etape 1', 'in_progress', 0, true)
    RETURNING id INTO etape3_id;

    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id)
    VALUES 
        (tablo_in_progress, 'Task 1.1', 'in_progress', 0, false, etape3_id),
        (tablo_in_progress, 'Task 1.2', 'done', 1, false, etape3_id);

    -- Setup Tablo 4: Mixed statuses
    -- Etape 1: all done
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent)
    VALUES (tablo_mixed, 'Etape 1', 'done', 0, true)
    RETURNING id INTO etape4_id;

    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id)
    VALUES 
        (tablo_mixed, 'Task 1.1', 'done', 0, false, etape4_id);

    -- Etape 2: has todo tasks (not started)
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent)
    VALUES (tablo_mixed, 'Etape 2', 'todo', 1, true)
    RETURNING id INTO etape5_id;

    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id)
    VALUES 
        (tablo_mixed, 'Task 2.1', 'todo', 0, false, etape5_id);

    -- Setup Tablo 5: Empty etapes (no child tasks)
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent)
    VALUES 
        (tablo_empty_etapes, 'Empty Etape 1', 'todo', 0, true),
        (tablo_empty_etapes, 'Empty Etape 2', 'todo', 1, true);

    -- Store test IDs
    PERFORM set_config('test.user_id', test_user_id::text, true);
    PERFORM set_config('test.tablo_no_etapes', tablo_no_etapes, true);
    PERFORM set_config('test.tablo_all_done', tablo_all_done, true);
    PERFORM set_config('test.tablo_in_progress', tablo_in_progress, true);
    PERFORM set_config('test.tablo_mixed', tablo_mixed, true);
    PERFORM set_config('test.tablo_empty_etapes', tablo_empty_etapes, true);
END $$;

-- ============================================================================
-- Test 1: Function exists and is accessible
-- ============================================================================

SELECT has_function(
    'public',
    'compute_tablo_status',
    ARRAY['text'],
    'compute_tablo_status function should exist'
);

SELECT function_returns(
    'public',
    'compute_tablo_status',
    ARRAY['text'],
    'text',
    'compute_tablo_status should return text'
);

-- ============================================================================
-- Test 2: Tablo with no etapes should return 'todo'
-- ============================================================================

SELECT is(
    public.compute_tablo_status(current_setting('test.tablo_no_etapes')),
    'todo',
    'Tablo with no etapes should have status "todo"'
);

-- ============================================================================
-- Test 3: Tablo with all etapes done should return 'done'
-- ============================================================================

SELECT is(
    public.compute_tablo_status(current_setting('test.tablo_all_done')),
    'done',
    'Tablo with all etapes completed should have status "done"'
);

-- ============================================================================
-- Test 4: Tablo with in_progress tasks should return 'in_progress'
-- ============================================================================

SELECT is(
    public.compute_tablo_status(current_setting('test.tablo_in_progress')),
    'in_progress',
    'Tablo with tasks in progress should have status "in_progress"'
);

-- ============================================================================
-- Test 5: Tablo with mixed etapes (some done, some todo) should return 'in_progress'
-- ============================================================================

SELECT is(
    public.compute_tablo_status(current_setting('test.tablo_mixed')),
    'in_progress',
    'Tablo with mixed etapes (some done, some todo) should have status "in_progress"'
);

-- ============================================================================
-- Test 6: Tablo with empty etapes (no child tasks) should return 'todo'
-- Updated: Now returns 'todo' when there are no tasks present (etapes exist but no child tasks)
-- ============================================================================

SELECT is(
    public.compute_tablo_status(current_setting('test.tablo_empty_etapes')),
    'todo',
    'Tablo with etapes that have no child tasks should have status "todo" (no tasks present)'
);

-- ============================================================================
-- Test 6.25: Explicit test for no tasks present - should return 'todo'
-- ============================================================================

DO $$
DECLARE
    no_tasks_tablo_id text;
    no_tasks_etape_id text;
BEGIN
    -- Create a tablo with etapes but explicitly no child tasks
    INSERT INTO public.tablos (owner_id, name, position)
    VALUES (current_setting('test.user_id')::uuid, 'No Tasks Tablo', 8)
    RETURNING id INTO no_tasks_tablo_id;

    -- Create an etape (parent task)
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent)
    VALUES (no_tasks_tablo_id, 'Etape Without Tasks', 'todo', 0, true)
    RETURNING id INTO no_tasks_etape_id;

    -- Explicitly do NOT create any child tasks

    PERFORM set_config('test.no_tasks_tablo', no_tasks_tablo_id, true);
END $$;

SELECT is(
    public.compute_tablo_status(current_setting('test.no_tasks_tablo')),
    'todo',
    'Tablo with etapes but no child tasks should return "todo" (fix: no tasks present)'
);

-- ============================================================================
-- Test 6.5: Tablo with partial progress (some tasks done, some todo) should return 'in_progress'
-- ============================================================================

DO $$
DECLARE
    partial_tablo_id text;
    partial_etape_id text;
BEGIN
    -- Create a tablo with partial progress
    INSERT INTO public.tablos (owner_id, name, position)
    VALUES (current_setting('test.user_id')::uuid, 'Partial Progress Tablo', 7)
    RETURNING id INTO partial_tablo_id;

    -- Create an etape
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent)
    VALUES (partial_tablo_id, 'Partial Etape', 'in_progress', 0, true)
    RETURNING id INTO partial_etape_id;

    -- Create multiple tasks with mixed statuses
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id)
    VALUES 
        (partial_tablo_id, 'Done Task 1', 'done', 0, false, partial_etape_id),
        (partial_tablo_id, 'Done Task 2', 'done', 1, false, partial_etape_id),
        (partial_tablo_id, 'Todo Task 1', 'todo', 2, false, partial_etape_id),
        (partial_tablo_id, 'Todo Task 2', 'todo', 3, false, partial_etape_id);

    PERFORM set_config('test.partial_tablo', partial_tablo_id, true);
END $$;

SELECT is(
    public.compute_tablo_status(current_setting('test.partial_tablo')),
    'in_progress',
    'Tablo with some tasks done and some todo should have status "in_progress"'
);

-- ============================================================================
-- Test 7: Verify status computation in user_tablos view
-- ============================================================================

SELECT is(
    (SELECT status FROM public.user_tablos WHERE id = current_setting('test.tablo_no_etapes')),
    'todo',
    'user_tablos view should show computed status for tablo with no etapes'
);

SELECT is(
    (SELECT status FROM public.user_tablos WHERE id = current_setting('test.tablo_all_done')),
    'done',
    'user_tablos view should show computed status for tablo with all done'
);

SELECT is(
    (SELECT status FROM public.user_tablos WHERE id = current_setting('test.tablo_in_progress')),
    'in_progress',
    'user_tablos view should show computed status for tablo in progress'
);

-- ============================================================================
-- Test 8: Test status changes when tasks are updated
-- ============================================================================

DO $$
DECLARE
    test_tablo_id text;
    test_etape_id text;
    test_task_id text;
BEGIN
    -- Create a new tablo for dynamic testing
    INSERT INTO public.tablos (owner_id, name, position)
    VALUES (current_setting('test.user_id')::uuid, 'Dynamic Test Tablo', 5)
    RETURNING id INTO test_tablo_id;

    -- Create an etape
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent)
    VALUES (test_tablo_id, 'Dynamic Etape', 'todo', 0, true)
    RETURNING id INTO test_etape_id;

    -- Create a todo task
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id)
    VALUES (test_tablo_id, 'Dynamic Task', 'todo', 0, false, test_etape_id)
    RETURNING id INTO test_task_id;

    -- Store IDs for testing
    PERFORM set_config('test.dynamic_tablo', test_tablo_id, true);
    PERFORM set_config('test.dynamic_task', test_task_id, true);
END $$;

-- Initially should be 'todo'
SELECT is(
    public.compute_tablo_status(current_setting('test.dynamic_tablo')),
    'todo',
    'New tablo with todo task should have status "todo"'
);

-- Update task to in_progress
DO $$
BEGIN
    UPDATE public.tasks
    SET status = 'in_progress'
    WHERE id = current_setting('test.dynamic_task');
END $$;

SELECT is(
    public.compute_tablo_status(current_setting('test.dynamic_tablo')),
    'in_progress',
    'Tablo should change to "in_progress" when task is updated'
);

-- Update task to done
DO $$
BEGIN
    UPDATE public.tasks
    SET status = 'done'
    WHERE id = current_setting('test.dynamic_task');
END $$;

SELECT is(
    public.compute_tablo_status(current_setting('test.dynamic_tablo')),
    'done',
    'Tablo should change to "done" when all tasks are completed'
);

-- ============================================================================
-- Test 9: Test with tasks in 'in_review' status (should count as in_progress)
-- ============================================================================

DO $$
DECLARE
    review_tablo_id text;
    review_etape_id text;
BEGIN
    -- Create a tablo with in_review tasks
    INSERT INTO public.tablos (owner_id, name, position)
    VALUES (current_setting('test.user_id')::uuid, 'Review Test Tablo', 6)
    RETURNING id INTO review_tablo_id;

    -- Create an etape
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent)
    VALUES (review_tablo_id, 'Review Etape', 'in_review', 0, true)
    RETURNING id INTO review_etape_id;

    -- Create an in_review task
    INSERT INTO public.tasks (tablo_id, title, status, position, is_parent, parent_task_id)
    VALUES (review_tablo_id, 'Review Task', 'in_review', 0, false, review_etape_id);

    PERFORM set_config('test.review_tablo', review_tablo_id, true);
END $$;

SELECT is(
    public.compute_tablo_status(current_setting('test.review_tablo')),
    'in_progress',
    'Tablo with in_review tasks should have status "in_progress"'
);

SELECT * FROM finish();
ROLLBACK;

