import type { Request, Response, NextFunction } from 'express';
import { env } from '../config/env.js';
import { MODULE_LABELS, ORG_ADMIN_ROLE, type ModuleKey } from '../config/access.js';
import prisma from '../config/db.js';
import * as projectModel from '../models/project.model.js';
import { effectiveAccess } from '../models/session.model.js';
import { sendTemplateEmail } from '../utils/mailer.js';
import { successResponse } from '../utils/response.js';

// Organization-scoped endpoints outside Administration (req.tenant from tenantAccess).

/** GET /projects: every project for "all projects" roles, otherwise only the user's own. */
async function getProjects(req: Request, res: Response, next: NextFunction) {
  try {
    const { organizationId, user } = req.tenant!;
    const { scope } = effectiveAccess(user);
    return successResponse(res, 'Projects fetched successfully', await projectModel.visibleProjects(organizationId, user.id, scope));
  } catch (error) {
    next(error);
    return;
  }
}

/** POST /access-requests: stored and emailed to the organization's active Organization Admins. */
async function createAccessRequest(req: Request, res: Response, next: NextFunction) {
  try {
    const { organizationId, user } = req.tenant!;
    const { module, path, message } = req.body as { module?: ModuleKey; path: string; message?: string };
    await prisma.accessRequest.create({
      data: { organizationId, requestedById: user.id, module: module ?? null, path, message: message || null },
    });
    const admins = await prisma.user.findMany({
      where: {
        organizationId, isActive: true, firebaseUid: { not: null },
        tenantRoles: { some: { role: { name: ORG_ADMIN_ROLE } } },
      },
      select: { name: true, email: true },
    });
    const what = module ? MODULE_LABELS[module] : 'a page';
    await Promise.all(admins.map((admin) => sendTemplateEmail({
      to: admin.email,
      subject: `${user.name} is asking for access to ${what}`,
      template: env.MAILGUN_TEMPLATE_ACCESS_REQUEST,
      variables: {
        adminName: admin.name,
        requesterName: user.name,
        requesterEmail: user.email,
        requesterRoles: user.tenantRoles.map(({ role }) => role.label ?? role.name).join(', '),
        what,
        pageUrl: `${env.TENANT_APP_URL}${path.startsWith('/') ? path : `/${path}`}`,
        usersUrl: `${env.TENANT_APP_URL}/admin/users`,
        message: message ?? '',
        organizationName: user.organization?.name ?? '',
      },
    })));
    const first = admins[0]?.name;
    const text = `${first ?? 'Your admin'}${admins.length > 1 ? ' and the other admins have' : ' has'} been notified.`;
    // The apps show `data.message` (contract: 202 { message }).
    return successResponse(res, text, { message: text }, 202);
  } catch (error) {
    next(error);
    return;
  }
}

export { getProjects, createAccessRequest };
