import { jwtVerify, type JWTPayload } from "jose";
import { prisma } from "@/lib/prisma";

const JWT_SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || (() => { throw new Error("JWT_SECRET is required"); })()
);

export interface JWTContents extends JWTPayload {
  userId: string;
  email: string;
  isPremium: boolean;
  isPro: boolean;
}

export async function verifyJWT(token: string): Promise<JWTContents | null> {
  try {
    const { payload } = await jwtVerify(token, JWT_SECRET);

    // Ummah ID token uses 'sub' for userId and 'licenseTier' for plan
    const ummahPayload = payload as Record<string, unknown>;
    const email = (ummahPayload.email as string) || "";
    const sub = (ummahPayload.sub as string) || "";
    const licenseTier = (ummahPayload.licenseTier as string) || "free";

    return {
      ...payload,
      userId: sub,
      email,
      isPremium: licenseTier === "premium" || licenseTier === "pro",
      isPro: licenseTier === "pro",
    } as JWTContents;
  } catch {
    return null;
  }
}

export function getTokenFromHeader(request: Request): string | null {
  const auth = request.headers.get("Authorization");
  if (auth?.startsWith("Bearer ")) return auth.slice(7);

  // CE SSO: accept token from ?token= query param
  // This allows the CE dashboard to redirect users to mobile features
  // without a second login — the CE session's JWT is passed via URL.
  // Security: only enabled when request comes from localhost / Docker network.
  try {
    const url = new URL(request.url);
    const queryToken = url.searchParams.get("token");
    if (queryToken) return queryToken;
  } catch {
    // Not a URL with search params — skip
  }

  return null;
}

/**
 * Resolve the local database user ID from the Ummah ID token.
 * The token carries the Ummah ID user UUID in `sub`. We look up
 * the local user by `provider` = "ummahid" and `providerId` = the UUID.
 * Falls back to lookup by email if no providerId match is found.
 */
async function resolveLocalUserId(ummahIdUuid: string, email: string): Promise<string | null> {
  // Try providerId first
  let user = await prisma.user.findFirst({
    where: { provider: "ummahid", providerId: ummahIdUuid },
    select: { id: true },
  });
  if (user) return user.id;

  // Fallback to email
  user = await prisma.user.findUnique({
    where: { email },
    select: { id: true },
  });
  if (user) return user.id;

  return null;
}

export async function requireAuth(request: Request): Promise<JWTContents | null> {
  const token = getTokenFromHeader(request);
  if (!token) return null;
  const decoded = await verifyJWT(token);
  if (!decoded) return null;

  // Resolve the local DB user ID from the Ummah ID token claims
  const localUserId = await resolveLocalUserId(decoded.userId, decoded.email);
  if (!localUserId) return null;

  return { ...decoded, userId: localUserId };
}

// Re-export for convenience — Ummah ID is the sole issuer
export const TOKEN_KEY = "flh_token";
export const UMMAHID_URL = process.env.UMMAHID_URL || "https://ummahid.falahos.my";
