import { Hono } from "hono";
import { zValidator } from "@hono/zod-validator";
import { setCookie, deleteCookie, getCookie } from "hono/cookie";
import { hash, verify } from "@node-rs/argon2";
import { uuidv7 } from "uuidv7";
import { signupSchema, loginSchema } from "@pijulab/shared";
import {
  findUserByEmail,
  findUserByUsername,
  createUser,
  createSession,
  deleteSession,
} from "../db/queries.js";
import { sessionMiddleware } from "../middleware/auth.js";

export const authRouter = new Hono()
  .post("/signup", zValidator("json", signupSchema), async (c) => {
    const { username, email, password } = c.req.valid("json");

    const [existingEmail, existingUsername] = await Promise.all([
      findUserByEmail(email),
      findUserByUsername(username),
    ]);
    if (existingEmail) return c.json({ message: "Email already in use" }, 409);
    if (existingUsername) return c.json({ message: "Username already taken" }, 409);

    const passwordHash = await hash(password);
    const userId = await createUser({ username, email, passwordHash });

    const sessionId = uuidv7();
    const expiresAt = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000);
    await createSession({ id: sessionId, userId, expiresAt });

    setCookie(c, "pijulab_session", sessionId, {
      httpOnly: true,
      sameSite: "Lax",
      path: "/",
      expires: expiresAt,
    });

    return c.json({ id: userId, username, email }, 201);
  })

  .post("/login", zValidator("json", loginSchema), async (c) => {
    const { email, password } = c.req.valid("json");

    const user = await findUserByEmail(email);
    if (!user) return c.json({ message: "Invalid email or password" }, 401);

    const valid = await verify(user.password_hash, password);
    if (!valid) return c.json({ message: "Invalid email or password" }, 401);

    const sessionId = uuidv7();
    const expiresAt = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000);
    await createSession({ id: sessionId, userId: user.id, expiresAt });

    setCookie(c, "pijulab_session", sessionId, {
      httpOnly: true,
      sameSite: "Lax",
      path: "/",
      expires: expiresAt,
    });

    return c.json({ id: user.id, username: user.username, email: user.email });
  })

  .post("/logout", sessionMiddleware, async (c) => {
    const sessionId = getCookie(c, "pijulab_session");
    if (sessionId) {
      await deleteSession(sessionId);
    }
    deleteCookie(c, "pijulab_session", { path: "/" });
    return c.json({ ok: true });
  });