import { badRequest } from "@infra/errors";
import { asyncRoute, fail, ok } from "@infra/http";
import { logger } from "@infra/logger";
import * as profilesRepo from "@server/repositories/profiles";
import { setSetting } from "@server/repositories/settings";
import { getProfile } from "@server/services/profile";
import { generateProfileFromResume } from "@server/services/profile-generator";
import { jobSearchProfileSchema } from "@shared/settings-registry";
import { type Request, type Response, Router } from "express";

export const profilesRouter = Router();

profilesRouter.get(
  "/",
  asyncRoute(async (_req: Request, res: Response) => {
    const profiles = await profilesRepo.listProfiles();
    return ok(res, profiles);
  }),
);

profilesRouter.get(
  "/:id",
  asyncRoute(async (req: Request, res: Response) => {
    const profile = await profilesRepo.getProfileById(req.params.id);
    if (!profile) {
      return fail(res, badRequest("Profile not found"));
    }
    return ok(res, profile);
  }),
);

profilesRouter.post(
  "/",
  asyncRoute(async (req: Request, res: Response) => {
    const { name, data } = req.body;
    if (!name || typeof name !== "string" || name.trim().length === 0) {
      throw badRequest("Profile name is required");
    }
    const parsed = jobSearchProfileSchema.safeParse(data);
    if (!parsed.success) {
      throw badRequest("Invalid profile data", {
        issues: parsed.error.issues,
      });
    }
    const profile = await profilesRepo.createProfile({
      name: name.trim(),
      data: parsed.data,
    });
    return ok(res, profile);
  }),
);

profilesRouter.patch(
  "/:id",
  asyncRoute(async (req: Request, res: Response) => {
    const { name, data } = req.body;
    const updates: { name?: string; data?: typeof data } = {};
    if (name !== undefined) {
      if (typeof name !== "string" || name.trim().length === 0) {
        throw badRequest("Profile name must be a non-empty string");
      }
      updates.name = name.trim();
    }
    if (data !== undefined) {
      const parsed = jobSearchProfileSchema.safeParse(data);
      if (!parsed.success) {
        throw badRequest("Invalid profile data", {
          issues: parsed.error.issues,
        });
      }
      updates.data = parsed.data;
    }
    const profile = await profilesRepo.updateProfile(req.params.id, updates);
    if (!profile) {
      return fail(res, badRequest("Profile not found"));
    }
    return ok(res, profile);
  }),
);

profilesRouter.delete(
  "/:id",
  asyncRoute(async (req: Request, res: Response) => {
    const deleted = await profilesRepo.deleteProfile(req.params.id);
    if (!deleted) {
      return fail(res, badRequest("Profile not found"));
    }
    return ok(res, { deleted: true });
  }),
);

profilesRouter.post(
  "/:id/activate",
  asyncRoute(async (req: Request, res: Response) => {
    const profile = await profilesRepo.getProfileById(req.params.id);
    if (!profile) {
      return fail(res, badRequest("Profile not found"));
    }
    await setSetting("activeProfileId", profile.id);
    await setSetting("jobSearchProfile", JSON.stringify(profile.data));
    return ok(res, { activated: true, profileId: profile.id });
  }),
);

profilesRouter.post(
  "/generate-from-resume",
  asyncRoute(async (_req: Request, res: Response) => {
    logger.info("Generating profile from resume");
    const resumeProfile = await getProfile();
    if (
      !resumeProfile ||
      typeof resumeProfile !== "object" ||
      Array.isArray(resumeProfile)
    ) {
      throw badRequest(
        "No resume profile available. Configure Reactive Resume in Settings first.",
      );
    }
    const generated = await generateProfileFromResume(
      resumeProfile as Record<string, unknown>,
    );
    return ok(res, generated);
  }),
);
