import { Hono } from "hono";
import { desc, eq } from "drizzle-orm";
import dayjs from "dayjs";
import { useDrizzle } from "@/lib/db.js";
import { user } from "@/db/schema.js";
import { zValidator } from "@hono/zod-validator";
import { z } from "zod";
import type { HonoEnv } from "@/types/hono.ts";

const app = new Hono<HonoEnv>();

const userUpdateSchema = z.object({
  name: z.string().min(1).max(100).optional(),
  username: z.string().min(1).max(50).optional().nullable(),
  role: z.enum(["user", "admin"]).optional(),
  banned: z.boolean().optional(),
  banReason: z.string().max(200).optional().nullable(),
});

/** GET /api/users  —  admin only */
app.get("/", async (c) => {
  const currentUser = c.get("user");
  if (currentUser?.role !== "admin") {
    return c.json({ error: "Forbidden" }, 403);
  }

  const db = useDrizzle();
  const users = await db
    .select({
      id: user.id,
      name: user.name,
      email: user.email,
      emailVerified: user.emailVerified,
      username: user.username,
      role: user.role,
      banned: user.banned,
      banReason: user.banReason,
      createdAt: user.createdAt,
    })
    .from(user)
    .orderBy(desc(user.createdAt));

  return c.json(users);
});

/** PATCH /api/users/:id  —  update role/ban status, admin only */
app.patch("/:id", zValidator("json", userUpdateSchema), async (c) => {
  const currentUser = c.get("user");
  if (currentUser?.role !== "admin") {
    return c.json({ error: "Forbidden" }, 403);
  }

  const db = useDrizzle();
  const userId = c.req.param("id");
  const body = c.req.valid("json");

  const [updated] = await db
    .update(user)
    .set({
      ...body,
      updatedAt: dayjs().toDate(),
    })
    .where(eq(user.id, userId))
    .returning({
      id: user.id,
      name: user.name,
      email: user.email,
      role: user.role,
      banned: user.banned,
      banReason: user.banReason,
    });

  if (!updated) return c.json({ error: "Not found" }, 404);
  return c.json(updated);
});

export default app;
