import { forbidden } from "@infra/errors";
import { fail } from "@infra/http";
import { logger } from "@infra/logger";
import { getSearchProfileIdForBasicAuthUser } from "@server/repositories/profiles";
import type { NextFunction, Request, RequestHandler, Response } from "express";
import {
  isBasicAuthEnabled,
  parseBasicAuthUsername,
} from "./basic-auth-credentials";
import { runWithRequestContext } from "./request-context";

export const DEFAULT_JOB_OWNER_PROFILE_ID = "__default__";

/**
 * Resolves the search profile id for the current request (Basic Auth → profile.basicAuthUser).
 * When Basic Auth is off, returns {@link DEFAULT_JOB_OWNER_PROFILE_ID}.
 */
export async function resolveRequestJobOwnerProfileId(
  req: Request,
): Promise<string> {
  if (!isBasicAuthEnabled()) {
    return DEFAULT_JOB_OWNER_PROFILE_ID;
  }

  const username = parseBasicAuthUsername(req.headers.authorization);
  if (!username?.trim()) {
    return DEFAULT_JOB_OWNER_PROFILE_ID;
  }

  const profileId = await getSearchProfileIdForBasicAuthUser(username);
  if (!profileId) {
    logger.warn("Basic Auth user has no matching search profile", {
      username: username.trim(),
    });
    return "__unmapped__";
  }
  return profileId;
}

function isAuthBootstrapPath(path: string): boolean {
  const p = path.split("?")[0] || path;
  return p === "/api/auth/verify" || p === "/api/auth/basic-status";
}

/**
 * When Basic Auth is enabled, require a matching search profile for mutating API calls
 * (handled in route handlers). This middleware only sets {@link DEFAULT_JOB_OWNER_PROFILE_ID}
 * or the resolved profile id on the request context for downstream filtering.
 */
export function jobOwnerContextMiddleware(): RequestHandler {
  return (req: Request, res: Response, next: NextFunction) => {
    if (!req.path.startsWith("/api")) {
      next();
      return;
    }

    void (async () => {
      try {
        let ownerProfileId = await resolveRequestJobOwnerProfileId(req);
        if (
          ownerProfileId === "__unmapped__" &&
          isAuthBootstrapPath(req.path)
        ) {
          ownerProfileId = DEFAULT_JOB_OWNER_PROFILE_ID;
        } else if (ownerProfileId === "__unmapped__") {
          fail(
            res,
            forbidden(
              "No job search profile is linked to this login. Set basicAuthUser on a profile in Settings.",
            ),
          );
          return;
        }
        runWithRequestContext({ ownerProfileId }, () => next());
      } catch (error) {
        next(error);
      }
    })();
  };
}
