import express, { type Application, type Request, type Response, type RequestHandler } from 'express';
import type { Repository } from '../db/repository.js';
import { requireAuth } from './auth.js';

const passthrough: RequestHandler = (_req, _res, next) => next();

/**
 * /api/users/me endpoints.
 *
 * When `authActive` is true, routes are gated by `requireAuth` and rely on
 * `req.user.id` being populated by passport. When auth is disabled (tests or
 * standalone mode), the guard is skipped and callers are expected to inject
 * `req.user` via their own middleware (e.g. the test harness).
 */
export function mountUsersApi(app: Application, repo: Repository, authActive = true): void {
  const guard = authActive ? requireAuth : passthrough;

  // Viewer's orgs for the visibility ('org' scope) picker: Gitea orgs (cached
  // at OAuth callback) + local orgs (membership). Returning both here means
  // every picker (CreateTaskDialog / Schedules / DetailPanel / Preferences)
  // lists local orgs without any client change.
  app.get('/api/users/me/orgs', guard, (req: Request, res: Response) => {
    const user = req.user as Express.User | undefined;
    if (!user) {
      // Defensive: with authActive=false and no injected user, return 401-shaped error.
      res.status(401).json({ error: 'Unauthorized' });
      return;
    }
    const gitea = repo.listUserGiteaOrgs(user.id);
    const local = repo.listUserLocalOrgs(user.id).map(o => ({ orgId: o.orgId, orgName: o.name, fetchedAt: '' }));
    res.json({ orgs: [...gitea, ...local] });
  });

  // Update viewer's per-user preferences (currently just default visibility).
  app.patch('/api/users/me/preferences', guard, express.json(), (req: Request, res: Response) => {
    const user = req.user as Express.User | undefined;
    if (!user) {
      res.status(401).json({ error: 'Unauthorized' });
      return;
    }
    const body = (req.body ?? {}) as {
      defaultVisibility?: unknown;
      defaultVisibilityOrgId?: unknown;
    };
    const { defaultVisibility, defaultVisibilityOrgId } = body;
    if (defaultVisibility !== undefined && defaultVisibility !== null &&
        !['private', 'org', 'public'].includes(defaultVisibility as string)) {
      res.status(400).json({ error: 'invalid defaultVisibility' });
      return;
    }
    if (defaultVisibility === 'org') {
      const scopeId = typeof defaultVisibilityOrgId === 'string' ? defaultVisibilityOrgId : '';
      if (!scopeId) {
        res.status(400).json({ error: 'default_visibility_org_id is required when defaultVisibility is "org"' });
        return;
      }
      if (!user.orgIds.includes(scopeId)) {
        res.status(400).json({ error: 'default_visibility_org_id must be one of your orgs' });
        return;
      }
    }
    repo.updateUser(user.id, {
      defaultVisibility: (defaultVisibility as 'private' | 'org' | 'public' | undefined) ?? undefined,
      defaultVisibilityOrgId: (defaultVisibilityOrgId as string | null | undefined) ?? null,
    });
    res.json({ ok: true });
  });
}
