import type { Request, Response } from "express";
import { z } from "zod";
import { eq } from "drizzle-orm";
import { getDb } from "../../db/client.js";
import { users } from "../../db/schema.js";
import { HttpError } from "../../middleware/errorHandler.js";

const patchSchema = z.object({
  displayName: z.string().min(1).max(80).optional(),
  avatarUrl: z.string().max(500_000).nullable().optional(),
  username: z
    .string()
    .min(3)
    .max(30)
    .regex(/^[a-zA-Z0-9_.-]+$/)
    .nullable()
    .optional(),
});

function publicUser(u: typeof users.$inferSelect) {
  return {
    id: u.id,
    email: u.email,
    username: u.username,
    displayName: u.displayName,
    avatarUrl: u.avatarUrl,
  };
}

export async function getMe(req: Request, res: Response) {
  const db = getDb();
  const [user] = await db
    .select()
    .from(users)
    .where(eq(users.id, req.userId!))
    .limit(1);
  if (!user) throw new HttpError(404, "user_not_found");
  res.json({ user: publicUser(user) });
}

export async function patchMe(req: Request, res: Response) {
  const db = getDb();
  const input = patchSchema.parse(req.body);

  if (input.username) {
    const [clash] = await db
      .select({ id: users.id })
      .from(users)
      .where(eq(users.username, input.username))
      .limit(1);
    if (clash && clash.id !== req.userId) {
      throw new HttpError(409, "username_taken");
    }
  }

  const [user] = await db
    .update(users)
    .set({ ...input, updatedAt: Date.now() })
    .where(eq(users.id, req.userId!))
    .returning();
  if (!user) throw new HttpError(404, "user_not_found");
  res.json({ user: publicUser(user) });
}
