/**
 * ICD Test Runner — AuthZ Tier
 * Permission boundary tests: cross-user isolation, role enforcement.
 */
(function () {
  'use strict';
  var T = window.ICD;
  if (!T) return;

  T.runAuthz = async function () {
    if (!T.fixtures.ready) {
      if (typeof UI !== 'undefined') UI.toast('Provision test fixtures first', 'warning');
      return;
    }

    var testUser = T.getFixtureUser('-user');
    var teamAdmin = T.getFixtureUser('-tadmin');
    var testAdmin = T.getFixtureUser('-admin2');

    if (!testUser || !testUser.token) {
      T.results.push({ tier: 'authz', domain: 'setup', name: 'SKIP', status: 'fail', duration: 0,
        detail: 'Test user not provisioned or login failed (no token)' });
      return;
    }

    // ── Regular user MUST be denied admin routes ──

    var adminGets = [
      '/admin/stats', '/admin/users', '/admin/settings',
      '/admin/configs', '/admin/models', '/admin/personas',
      '/admin/teams', '/admin/groups', '/admin/surfaces',
      '/admin/providers/health', '/admin/routing/policies',
      '/admin/permissions', '/admin/roles', '/admin/vault/status',
      '/admin/storage/status', '/admin/audit', '/admin/pricing',
      '/admin/tasks', '/admin/projects', '/admin/channels/archived',
      '/admin/extensions'
    ];

    for (var ai = 0; ai < adminGets.length; ai++) {
      await (async function (path) {
        await T.test('authz', 'admin-deny', 'user → GET ' + path + ' (expect 403)', async function () {
          var d = await T.authFetch(testUser.token, 'GET', path);
          T.assert(d._status === 403 || d._status === 401,
            'expected 403/401 for non-admin, got ' + d._status);
        });
      })(adminGets[ai]);
    }

    // ── Regular user MUST NOT be able to create admin resources ──

    await T.test('authz', 'admin-deny', 'user → POST /admin/users (expect 403)', async function () {
      var d = await T.authFetch(testUser.token, 'POST', '/admin/users', {
        username: 'should-not-exist', password: 'x', email: 'no@no.no', role: 'user'
      });
      T.assert(d._status === 403 || d._status === 401,
        'expected 403/401, got ' + d._status);
    });

    await T.test('authz', 'admin-deny', 'user → POST /admin/teams (expect 403)', async function () {
      var d = await T.authFetch(testUser.token, 'POST', '/admin/teams', {
        name: 'should-not-exist'
      });
      T.assert(d._status === 403 || d._status === 401,
        'expected 403/401, got ' + d._status);
    });

    await T.test('authz', 'admin-deny', 'user → POST /admin/groups (expect 403)', async function () {
      var d = await T.authFetch(testUser.token, 'POST', '/admin/groups', {
        name: 'should-not-exist', scope: 'global'
      });
      T.assert(d._status === 403 || d._status === 401,
        'expected 403/401, got ' + d._status);
    });

    await T.test('authz', 'admin-deny', 'user → POST /admin/surfaces/install (expect 403)', async function () {
      var d = await T.authFetch(testUser.token, 'POST', '/admin/surfaces/install', {});
      T.assert(d._status === 403 || d._status === 401 || d._status === 400,
        'expected 403/401/400, got ' + d._status);
    });

    await T.test('authz', 'admin-deny', 'user → PUT /admin/users/:id/role (expect 403)', async function () {
      var d = await T.authFetch(testUser.token, 'PUT', '/admin/users/' + testUser.id + '/role', { role: 'admin' });
      T.assert(d._status === 403 || d._status === 401,
        'CRITICAL: non-admin was able to escalate role! got ' + d._status);
    });

    await T.test('authz', 'admin-deny', 'user → POST /admin/users/:id/reset-password (expect 403)', async function () {
      var d = await T.authFetch(testUser.token, 'POST', '/admin/users/' + testUser.id + '/reset-password', { new_password: 'hacked' });
      T.assert(d._status === 403 || d._status === 401,
        'CRITICAL: non-admin was able to reset passwords! got ' + d._status);
    });

    // ── Regular user SHOULD be able to access their own stuff ──

    await T.test('authz', 'user-allow', 'user → GET /profile (expect 200)', async function () {
      var d = await T.authFetch(testUser.token, 'GET', '/profile');
      T.assertStatus(d, 200, 'profile');
      T.assert(d.username === testUser.username, 'username mismatch');
    });

    await T.test('authz', 'user-allow', 'user → GET /channels (expect 200)', async function () {
      var d = await T.authFetch(testUser.token, 'GET', '/channels');
      T.assertStatus(d, 200, 'channels');
    });

    await T.test('authz', 'user-allow', 'user → GET /models/enabled (expect 200)', async function () {
      var d = await T.authFetch(testUser.token, 'GET', '/models/enabled');
      T.assertStatus(d, 200, 'models');
    });

    await T.test('authz', 'user-allow', 'user → GET /surfaces (expect 200)', async function () {
      var d = await T.authFetch(testUser.token, 'GET', '/surfaces');
      T.assertStatus(d, 200, 'surfaces');
    });

    await T.test('authz', 'user-allow', 'user → GET /notifications/unread-count (expect 200)', async function () {
      var d = await T.authFetch(testUser.token, 'GET', '/notifications/unread-count');
      T.assertStatus(d, 200, 'unread-count');
    });

    await T.test('authz', 'user-allow', 'user → GET /teams/mine (expect 200)', async function () {
      var d = await T.authFetch(testUser.token, 'GET', '/teams/mine');
      T.assertStatus(d, 200, 'teams/mine');
    });

    await T.test('authz', 'user-allow', 'user → GET /groups/mine (expect 200)', async function () {
      var d = await T.authFetch(testUser.token, 'GET', '/groups/mine');
      T.assertStatus(d, 200, 'groups/mine');
    });

    // ── Permission-gated operations ──

    await T.test('authz', 'perm-gate', 'user → POST /workflows (expect 403, no workflow.create)', async function () {
      var d = await T.authFetch(testUser.token, 'POST', '/workflows', {
        name: 'should-not-exist', slug: 'should-not-exist', entry_mode: 'team_only'
      });
      T.assert(d._status === 403 || d._status === 401,
        'expected 403 (no workflow.create), got ' + d._status);
    });

    // ── Team admin can manage their team but NOT platform admin ──

    if (teamAdmin && teamAdmin.token && T.fixtures.team) {
      await T.test('authz', 'team-scope', 'teamAdmin → GET /teams/:id/members (expect 200)', async function () {
        var d = await T.authFetch(teamAdmin.token, 'GET', '/teams/' + T.fixtures.team.id + '/members');
        T.assertStatus(d, 200, 'team-members');
      });

      await T.test('authz', 'team-scope', 'teamAdmin → GET /teams/:id/personas (expect 200)', async function () {
        var d = await T.authFetch(teamAdmin.token, 'GET', '/teams/' + T.fixtures.team.id + '/personas');
        T.assertStatus(d, 200, 'team-personas');
      });

      await T.test('authz', 'team-scope', 'teamAdmin → GET /teams/:id/providers (expect 200)', async function () {
        var d = await T.authFetch(teamAdmin.token, 'GET', '/teams/' + T.fixtures.team.id + '/providers');
        T.assertStatus(d, 200, 'team-providers');
      });

      await T.test('authz', 'team-scope', 'teamAdmin → GET /admin/stats (expect 403)', async function () {
        var d = await T.authFetch(teamAdmin.token, 'GET', '/admin/stats');
        T.assert(d._status === 403 || d._status === 401,
          'team admin should not have platform admin, got ' + d._status);
      });

      await T.test('authz', 'team-scope', 'teamAdmin → PUT /admin/users/:id/role (expect 403)', async function () {
        var d = await T.authFetch(teamAdmin.token, 'PUT', '/admin/users/' + teamAdmin.id + '/role', { role: 'admin' });
        T.assert(d._status === 403 || d._status === 401,
          'CRITICAL: team admin was able to escalate to platform admin! got ' + d._status);
      });
    }

    // ── Second admin CAN access admin routes ──

    if (testAdmin && testAdmin.token) {
      await T.test('authz', 'admin-allow', 'admin2 → GET /admin/stats (expect 200)', async function () {
        var d = await T.authFetch(testAdmin.token, 'GET', '/admin/stats');
        T.assertStatus(d, 200, 'admin-stats');
      });

      await T.test('authz', 'admin-allow', 'admin2 → GET /admin/users (expect 200)', async function () {
        var d = await T.authFetch(testAdmin.token, 'GET', '/admin/users');
        T.assertStatus(d, 200, 'admin-users');
      });
    }

    // ── Expired/invalid token ──

    await T.test('authz', 'token', 'bogus token → GET /profile (expect 401)', async function () {
      var d = await T.authFetch('this-is-not-a-valid-token', 'GET', '/profile');
      T.assert(d._status === 401, 'expected 401 for bogus token, got ' + d._status);
    });

    await T.test('authz', 'token', 'empty token → GET /profile (expect 401)', async function () {
      var d = await T.authFetch('', 'GET', '/profile');
      T.assert(d._status === 401, 'expected 401 for empty token, got ' + d._status);
    });

    // ── Cross-user resource isolation ──

    var userChannel = null;
    await T.test('authz', 'isolation', 'admin creates private channel', async function () {
      var d = await T.apiPost('/channels', { title: 'authz-private-' + Date.now(), type: 'direct' });
      T.assertHasKey(d, 'id', 'channel');
      userChannel = d.id;
      T.registerCleanup(function () { if (userChannel) return T.safeDelete('/channels/' + userChannel); });
    });

    if (userChannel && testUser.token) {
      await T.test('authz', 'isolation', 'user → GET /channels/:id (expect 403/404)', async function () {
        var d = await T.authFetch(testUser.token, 'GET', '/channels/' + userChannel);
        T.assert(d._status === 403 || d._status === 404,
          'user should not see another user\'s channel, got ' + d._status);
      });

      await T.test('authz', 'isolation', 'user → DELETE /channels/:id (expect 403/404)', async function () {
        var d = await T.authFetch(testUser.token, 'DELETE', '/channels/' + userChannel);
        T.assert(d._status === 403 || d._status === 404,
          'user should not delete another user\'s channel, got ' + d._status);
      });

      await T.test('authz', 'isolation', 'user → GET /channels/:id/path (expect 403/404)', async function () {
        var d = await T.authFetch(testUser.token, 'GET', '/channels/' + userChannel + '/path');
        T.assert(d._status === 403 || d._status === 404,
          'user should not read another user\'s messages, got ' + d._status);
      });
    }
  };
})();
