import { Op } from 'sequelize';
import db from '@/db/models';
import ForbiddenError from '@/shared/errors/forbidden';
import { hasGlobalAccess } from '@/services/shared/access';
import type { CurrentUser } from '@/db/api/types';

export interface PlatformStats {
  readonly tenants: {
    readonly organizations: number;
    readonly schools: number;
    readonly campuses: number;
    readonly classes: number;
  };
  readonly users: {
    readonly total: number;
    /** Count per role name (e.g. `{ teacher: 12, owner: 1 }`). */
    readonly byRole: Record<string, number>;
  };
  readonly content: {
    readonly frameEntries: number;
    readonly quizzes: number;
    readonly documents: number;
  };
  readonly activeSessions: number;
}

/**
 * Platform-wide statistics for the global scope (super_admin / system_admin).
 * Counts are unscoped on purpose — this is the only place tenant isolation does
 * not apply, because the audience is the platform operator.
 */
export default class PlatformService {
  static async stats(currentUser?: CurrentUser): Promise<PlatformStats> {
    if (!hasGlobalAccess(currentUser)) {
      throw new ForbiddenError();
    }

    const roles = await db.roles.findAll({ attributes: ['id', 'name'] });

    const [
      organizations,
      schools,
      campuses,
      classes,
      totalUsers,
      roleCounts,
      frameEntries,
      quizzes,
      documents,
      activeSessions,
    ] = await Promise.all([
      db.organizations.count(),
      db.schools.count(),
      db.campuses.count(),
      db.classes.count(),
      db.users.count(),
      Promise.all(
        roles.map((role) =>
          db.users.count({
            include: [
              { model: db.roles, as: 'app_role', where: { id: role.id }, required: true },
            ],
          }),
        ),
      ),
      db.frame_entries.count(),
      db.content_catalog.count({
        where: { content_type: { [Op.iLike]: '%quiz%' } },
      }),
      db.policy_documents.count(),
      db.auth_refresh_tokens.count({
        distinct: true,
        col: 'userId',
        where: {
          revokedAt: { [Op.is]: null },
          expiresAt: { [Op.gt]: new Date() },
        },
      }),
    ]);

    const byRole: Record<string, number> = {};
    roles.forEach((role, index) => {
      const name = role.name ?? 'unassigned';
      const count = roleCounts[index] ?? 0;
      if (count > 0) {
        byRole[name] = count;
      }
    });

    return {
      tenants: { organizations, schools, campuses, classes },
      users: { total: totalUsers, byRole },
      content: { frameEntries, quizzes, documents },
      activeSessions,
    };
  }
}
