import { sql } from "@/lib/db";
import { issueSession, toProfile } from "@/lib/users";

const TOKENINFO_URL = "https://oauth2.googleapis.com/tokeninfo?id_token=";

type GoogleTokenInfo = {
  aud?: string;
  sub?: string;
  email?: string;
  email_verified?: string | boolean;
  name?: string;
  exp?: string;
  error_description?: string;
};

export async function POST(req: Request) {
  const { idToken } = await req.json();

  if (!idToken || typeof idToken !== "string") {
    return Response.json({ error: "Missing idToken." }, { status: 400 });
  }

  const audience = process.env.GOOGLE_OAUTH_CLIENT_ID ?? process.env.EXPO_PUBLIC_GOOGLE_AUTH_WEB_CLIENT_ID;

  if (!audience) {
    return Response.json(
      { error: "Server is missing GOOGLE_OAUTH_CLIENT_ID." },
      { status: 500 },
    );
  }

  try {
    const response = await fetch(`${TOKENINFO_URL}${idToken}`);

    if (!response.ok) {
      return Response.json(
        { error: "Invalid Google token." },
        { status: 401 },
      );
    }

    const info = (await response.json()) as GoogleTokenInfo;

    if (
      info.aud !== audience ||
      !info.sub ||
      !info.email ||
      (info.email_verified !== true && info.email_verified !== "true") ||
      (info.exp && Number(info.exp) * 1000 < Date.now())
    ) {
      return Response.json(
        { error: "Google token failed validation." },
        { status: 401 },
      );
    }

    const name = info.name?.trim() || info.email.split("@")[0];

    const rows = await sql<{
      id: string;
      name: string;
      email: string;
      role: string | null;
    }>`
      INSERT INTO users (name, email, google_sub, email_verified)
      VALUES (${name}, ${info.email.toLowerCase()}, ${info.sub}, TRUE)
      ON CONFLICT (email) DO UPDATE SET
        google_sub = EXCLUDED.google_sub,
        email_verified = TRUE,
        name = CASE WHEN users.name = split_part(users.email, '@', 1)
                    THEN EXCLUDED.name ELSE users.name END
      RETURNING id, name, email, role
    `;

    const user = rows[0];

    if (!user) {
      return Response.json({ error: "Could not create user." }, { status: 500 });
    }

    const session = issueSession(user);

    return Response.json({
      data: { token: session.token, user: toProfile(user) },
    });
  } catch (error) {
    console.error("[GOOGLE_AUTH]: ", error);
    return Response.json({ error: "Internal Server Error" }, { status: 500 });
  }
}
