import { randomUUID } from "node:crypto";
import type {
  CreateSearchProfileInput,
  JobSearchProfile,
  SearchProfile,
  UpdateSearchProfileInput,
} from "@shared/types";
import { eq } from "drizzle-orm";
import { db } from "../db";
import { searchProfiles } from "../db/schema";

function mapRow(row: typeof searchProfiles.$inferSelect): SearchProfile {
  let data: JobSearchProfile;
  try {
    data = JSON.parse(row.data);
  } catch {
    data = {
      targetRoles: [],
      experienceLevel: "",
      mustHaveSkills: [],
      niceToHaveSkills: [],
      dealBreakers: [],
      preferredWorkArrangement: [],
      preferredLocations: [],
      minimumSalary: "",
      industriesToTarget: [],
      industriesToAvoid: [],
      aboutMe: "",
    };
  }
  return {
    id: row.id,
    name: row.name,
    data,
    createdAt: row.createdAt,
    updatedAt: row.updatedAt,
  };
}

export async function listProfiles(): Promise<SearchProfile[]> {
  const rows = await db.select().from(searchProfiles);
  return rows.map(mapRow);
}

/** When Basic Auth maps users to profiles, each user only sees rows with matching `basicAuthUser`. */
export async function listProfilesForBasicAuthUser(
  username: string,
): Promise<SearchProfile[]> {
  const u = username.trim().toLowerCase();
  if (!u) return [];
  const all = await listProfiles();
  return all.filter(
    (p) => (p.data.basicAuthUser ?? "").trim().toLowerCase() === u,
  );
}

export async function getProfileById(
  id: string,
): Promise<SearchProfile | null> {
  const [row] = await db
    .select()
    .from(searchProfiles)
    .where(eq(searchProfiles.id, id));
  return row ? mapRow(row) : null;
}

export async function createProfile(
  input: CreateSearchProfileInput,
): Promise<SearchProfile> {
  const id = randomUUID();
  const now = new Date().toISOString();
  await db.insert(searchProfiles).values({
    id,
    name: input.name,
    data: JSON.stringify(input.data),
    createdAt: now,
    updatedAt: now,
  });
  const created = await getProfileById(id);
  if (!created) throw new Error("Failed to create profile");
  return created;
}

export async function updateProfile(
  id: string,
  input: UpdateSearchProfileInput,
): Promise<SearchProfile | null> {
  const existing = await getProfileById(id);
  if (!existing) return null;

  const updates: Partial<typeof searchProfiles.$inferInsert> = {
    updatedAt: new Date().toISOString(),
  };
  if (input.name !== undefined) updates.name = input.name;
  if (input.data !== undefined) updates.data = JSON.stringify(input.data);

  await db.update(searchProfiles).set(updates).where(eq(searchProfiles.id, id));

  return getProfileById(id);
}

export async function getSearchProfileIdForBasicAuthUser(
  username: string,
): Promise<string | null> {
  const profiles = await listProfiles();
  const u = username.trim().toLowerCase();
  for (const p of profiles) {
    const bu = (p.data.basicAuthUser ?? "").trim().toLowerCase();
    if (bu && bu === u) return p.id;
  }
  return null;
}

export async function deleteProfile(id: string): Promise<boolean> {
  const result = await db
    .delete(searchProfiles)
    .where(eq(searchProfiles.id, id));
  return (result?.changes ?? 0) > 0;
}
