/**
 * ICD Test Runner — CRUD: Teams
 * Admin team lifecycle (create → read → update → members → team-scoped
 * endpoints → team tasks → groups → grants → permissions → audit →
 * usage → assignments → member remove → delete).
 */
(function () {
  'use strict';
  var T = window.ICD;
  if (!T) return;
  if (!T.crud) T.crud = {};

  T.crud.teams = async function (testTag) {

    // ── Teams CRUD (admin — create team, exercise team-scoped endpoints) ──
    if (T.user.role === 'admin') {
      var teamId = null;

      await T.test('crud', 'teams', 'POST /admin/teams (create)', async function () {
        var d = await T.apiPost('/admin/teams', { name: testTag + '-team', description: 'ICD test team' });
        T.assertShape(d, T.S.team, 'team');
        teamId = d.id;
        T.registerCleanup(function () { if (teamId) return T.safeDelete('/admin/teams/' + teamId); });
      });

      if (teamId) {
        await T.test('crud', 'teams', 'GET /admin/teams/:id (read)', async function () {
          var d = await T.apiGet('/admin/teams/' + teamId);
          T.assertShape(d, T.S.team, 'team');
          T.assert(d.id === teamId, 'id mismatch');
        });

        await T.test('crud', 'teams', 'PUT /admin/teams/:id (update)', async function () {
          var d = await T.apiPut('/admin/teams/' + teamId, { name: testTag + '-team-updated' });
          T.assert(typeof d === 'object', 'expected object');
        });

        // Add current user as team admin
        await T.test('crud', 'teams', 'POST /admin/teams/:id/members (add self)', async function () {
          var d = await T.apiPost('/admin/teams/' + teamId + '/members', { user_id: T.user.id, role: 'admin' });
          T.assert(typeof d === 'object', 'expected object');
        });

        await T.test('crud', 'teams', 'GET /admin/teams/:id/members', async function () {
          var d = await T.apiGet('/admin/teams/' + teamId + '/members');
          T.assertHasKey(d, 'data', '/team-members');
          T.assert(Array.isArray(d.data), 'data should be array');
          T.assert(d.data.length >= 1, 'expected at least 1 member');
        });

        // Team-scoped endpoints (via team admin routes)
        await T.test('crud', 'teams', 'GET /teams/:teamId/members (team route)', async function () {
          var d = await T.apiGet('/teams/' + teamId + '/members');
          T.assertHasKey(d, 'data', '/team-members');
        });

        // Member update + remove (need a second user — use admin self-membership)
        await T.test('crud', 'teams', 'PUT /admin/teams/:id/members/:mid (update role)', async function () {
          // Get own membership ID
          var d = await T.apiGet('/admin/teams/' + teamId + '/members');
          var me = d.data.find(function (m) { return m.user_id === T.user.id; });
          T.assert(me, 'should find self in members');
          // Update role to member then back to admin
          var r = await T.apiPut('/admin/teams/' + teamId + '/members/' + me.id, { role: 'member' });
          T.assert(typeof r === 'object', 'expected object');
          // Restore admin role
          await T.apiPut('/admin/teams/' + teamId + '/members/' + me.id, { role: 'admin' });
        });

        // Team groups listing
        await T.test('crud', 'teams', 'GET /teams/:teamId/groups', async function () {
          var d = await T.apiGet('/teams/' + teamId + '/groups');
          T.assertHasKey(d, 'data', '/team-groups');
          T.assert(Array.isArray(d.data), 'data should be array');
        });

        // ── Team Tasks CRUD ──
        var teamTaskId = null;

        await T.test('crud', 'teams', 'POST /teams/:teamId/tasks (create team task)', async function () {
          var d = await T.apiPost('/teams/' + teamId + '/tasks', {
            name: testTag + '-team-task',
            task_type: 'prompt',
            schedule: '@daily',
            user_prompt: 'Team task test',
            model_id: 'test-model'
          });
          T.assertShape(d, T.S.taskFull, 'team task');
          T.assert(d.scope === 'team', 'team task scope should be team');
          T.assert(d.team_id === teamId, 'team_id should match');
          teamTaskId = d.id;
          T.registerCleanup(function () { if (teamTaskId) return T.safeDelete('/teams/' + teamId + '/tasks/' + teamTaskId); });
        });

        await T.test('crud', 'teams', 'GET /teams/:teamId/tasks (list team tasks)', async function () {
          var d = await T.apiGet('/teams/' + teamId + '/tasks');
          T.assertHasKey(d, 'data', '/team-tasks');
          T.assert(Array.isArray(d.data), 'data should be array');
          if (teamTaskId) {
            T.assert(d.data.length >= 1, 'should have at least 1 team task');
            var found = d.data.some(function (t) { return t.id === teamTaskId; });
            T.assert(found, 'created team task should be in list');
          }
        });

        if (teamTaskId) {
          await T.test('crud', 'teams', 'PUT /teams/:teamId/tasks/:id (update team task)', async function () {
            var d = await T.apiPut('/teams/' + teamId + '/tasks/' + teamTaskId, {
              name: testTag + '-team-task-updated'
            });
            T.assert(d.name === testTag + '-team-task-updated', 'name not updated');
          });

          await T.test('crud', 'teams', 'GET /teams/:teamId/tasks/:id/runs (team task runs)', async function () {
            var d = await T.apiGet('/teams/' + teamId + '/tasks/' + teamTaskId + '/runs');
            T.assertHasKey(d, 'data', '/team-task-runs');
            T.assert(Array.isArray(d.data), 'data should be array');
          });

          await T.test('crud', 'teams', 'POST /teams/:teamId/tasks/:id/run (team task run)', async function () {
            var d = await T.apiPost('/teams/' + teamId + '/tasks/' + teamTaskId + '/run', {});
            T.assertHasKey(d, 'scheduled', '/team-run');
            T.assert(d.scheduled === true, 'should be scheduled');
          });

          await T.test('crud', 'teams', 'POST /teams/:teamId/tasks/:id/kill (team task kill)', async function () {
            var token = await T.getAuthToken();
            var d = await T.authFetch(token, 'POST', '/teams/' + teamId + '/tasks/' + teamTaskId + '/kill');
            T.assert(d._status === 200 || d._status === 404,
              'expected 200 or 404, got ' + d._status);
          });

          await T.test('crud', 'teams', 'DELETE /teams/:teamId/tasks/:id (delete team task)', async function () {
            await T.safeDelete('/teams/' + teamId + '/tasks/' + teamTaskId);
            teamTaskId = null;
          });
        }

        await T.test('crud', 'teams', 'GET /teams/:teamId/roles', async function () {
          var d = await T.apiGet('/teams/' + teamId + '/roles');
          T.assertHasKey(d, 'data', '/team-roles');
          T.assert(typeof d.data === 'object', 'data should be object (role overrides map)');
        });

        await T.test('crud', 'teams', 'GET /teams/:teamId/audit', async function () {
          var d = await T.apiGet('/teams/' + teamId + '/audit');
          T.assertHasKey(d, 'data', '/team-audit');
          T.assert(Array.isArray(d.data), 'data should be array');
          T.assertHasKey(d, 'total', '/team-audit pagination');
          T.assertHasKey(d, 'page', '/team-audit pagination');
        });

        await T.test('crud', 'teams', 'GET /teams/:teamId/audit/actions', async function () {
          var d = await T.apiGet('/teams/' + teamId + '/audit/actions');
          T.assertHasKey(d, 'actions', '/team-audit-actions');
          T.assert(Array.isArray(d.actions), 'actions should be array');
        });

        await T.test('crud', 'teams', 'GET /teams/:teamId/usage', async function () {
          var d = await T.apiGet('/teams/' + teamId + '/usage');
          T.assertHasKey(d, 'totals', '/team-usage');
          T.assertHasKey(d, 'results', '/team-usage');
        });

        await T.test('crud', 'teams', 'GET /teams/:teamId/assignments', async function () {
          var d = await T.apiGet('/teams/' + teamId + '/assignments');
          T.assert(typeof d === 'object', 'expected object');
        });

        // Admin groups CRUD within team context
        var groupId = null;

        await T.test('crud', 'teams', 'POST /admin/groups (create team group)', async function () {
          var d = await T.apiPost('/admin/groups', { name: testTag + '-group', scope: 'team', team_id: teamId });
          T.assertShape(d, T.S.group, 'group');
          groupId = d.id;
          T.registerCleanup(function () { if (groupId) return T.safeDelete('/admin/groups/' + groupId); });
        });

        if (groupId) {
          await T.test('crud', 'teams', 'GET /admin/groups/:id', async function () {
            var d = await T.apiGet('/admin/groups/' + groupId);
            T.assertShape(d, T.S.group, 'group');
          });

          await T.test('crud', 'teams', 'PUT /admin/groups/:id (set permissions)', async function () {
            var d = await T.apiPut('/admin/groups/' + groupId, {
              permissions: ['model.use', 'kb.read', 'channel.create']
            });
            T.assert(typeof d === 'object', 'expected object');
          });

          await T.test('crud', 'teams', 'POST /admin/groups/:id/members (add self)', async function () {
            var d = await T.apiPost('/admin/groups/' + groupId + '/members', { user_id: T.user.id });
            T.assert(typeof d === 'object', 'expected object');
          });

          await T.test('crud', 'teams', 'GET /admin/groups/:id/members', async function () {
            var d = await T.apiGet('/admin/groups/' + groupId + '/members');
            T.assertHasKey(d, 'data', '/group-members');
            T.assert(Array.isArray(d.data), 'data should be array');
          });

          await T.test('crud', 'teams', 'DELETE /admin/groups/:id/members/:uid', async function () {
            await T.safeDelete('/admin/groups/' + groupId + '/members/' + T.user.id);
          });

          await T.test('crud', 'teams', 'DELETE /admin/groups/:id', async function () {
            await T.safeDelete('/admin/groups/' + groupId);
            groupId = null;
          });
        }

        // Grants
        await T.test('crud', 'teams', 'GET /admin/grants/persona/:id (404 = no grant)', async function () {
          // No persona to test, just verify the endpoint responds
          try {
            var d = await T.apiGet('/admin/grants/persona/00000000-0000-0000-0000-000000000000');
            T.assert(typeof d === 'object', 'expected object');
          } catch (e) {
            if (e.message && e.message.indexOf('404') !== -1) return; // expected
            throw e;
          }
        });

        // User permissions
        await T.test('crud', 'teams', 'GET /admin/users/:id/permissions', async function () {
          var d = await T.apiGet('/admin/users/' + T.user.id + '/permissions');
          T.assertHasKey(d, 'permissions', '/user-permissions');
          T.assert(Array.isArray(d.permissions), 'permissions should be array');
          T.assertHasKey(d, 'user_id', '/user-permissions');
          T.assertHasKey(d, 'groups', '/user-permissions contributing groups');
          T.assert(Array.isArray(d.groups), 'groups should be array');
        });

        // List all permissions
        await T.test('crud', 'teams', 'GET /admin/permissions', async function () {
          var d = await T.apiGet('/admin/permissions');
          T.assertHasKey(d, 'permissions', '/admin/permissions');
          T.assert(Array.isArray(d.permissions), 'permissions should be array');
          T.assert(d.permissions.length > 0, 'should have at least 1 permission');
        });

        // Member remove (remove self then re-add to keep admin for cleanup)
        await T.test('crud', 'teams', 'DELETE /admin/teams/:id/members/:mid (remove)', async function () {
          var d = await T.apiGet('/admin/teams/' + teamId + '/members');
          var me = d.data.find(function (m) { return m.user_id === T.user.id; });
          T.assert(me, 'should find self in members');
          var r = await T.safeDelete('/admin/teams/' + teamId + '/members/' + me.id);
          T.assert(typeof r === 'object' || r === undefined, 'expected object or void');
          // Re-add self as admin for cleanup
          await T.apiPost('/admin/teams/' + teamId + '/members', { user_id: T.user.id, role: 'admin' });
        });

        await T.test('crud', 'teams', 'DELETE /admin/teams/:id', async function () {
          await T.safeDelete('/admin/teams/' + teamId);
          teamId = null;
        });
      }
    }

  };
})();
