import type { MiddlewareHandler } from 'hono';
import { createRouter } from '@@/create-router';
import { originMiddleware } from '@@/_middlewares';
import { isSuperAdmin } from '@@/super-admin';
import * as errors from '@@/custom-errors';
import { updateUserHandler } from './update-user';
import { listUsersHandler, updateUserRoleHandler, deleteUserHandler } from './manage-users';
import { createUserHandler } from './create-user';
import { provisionLinuxHandler } from './provision-linux-route';
import { resetUserPasswordHandler } from './reset-user-password';
import { capabilityAdminRouter } from './capabilities-routes';

export const usersRouter = createRouter();
usersRouter.use(originMiddleware);

// Self-update. Any signed-in account may change its own name, username and avatar.
usersRouter.put('/', updateUserHandler);

// Everything below manages OTHER accounts and is the owner's alone. The global capability gate in
// hono.ts already refuses a non-owner here — `user-admin` is `kind: 'admin'`, so it is
// not grantable — but that router-level rule cannot see the one exception beside it: `PUT /` is
// declared `selfService` so every account can edit its own profile. This gate is what keeps that
// exception from widening to the routes below it, and it is a second lock rather than a restatement.
const ownerGate: MiddlewareHandler = async (ctx, next) => {
  if (!(await isSuperAdmin(ctx.get('user')))) throw errors.FORBIDDEN('User management is owner-only');
  return next();
};

usersRouter.get('/', ownerGate, listUsersHandler);
// POST, not PUT — and worth noting they sit one line apart. `PUT /` is the selfService exception every
// account may call on itself; `POST /` creates somebody else and is the owner's alone.
usersRouter.post('/', ownerGate, createUserHandler);
usersRouter.patch('/:id/role', ownerGate, updateUserRoleHandler);
usersRouter.post('/:id/provision-linux', ownerGate, provisionLinuxHandler);
// Generates a new platform password, returns it once, and signs the account out everywhere. Not the same
// thing as auth/reset-password.ts, which is the token flow the person runs on themselves.
usersRouter.post('/:id/password', ownerGate, resetUserPasswordHandler);
usersRouter.delete('/:id', ownerGate, deleteUserHandler);

// Which capabilities each role holds. Owner-gated inside its own router.
usersRouter.route('/', capabilityAdminRouter);
