/**
 * Client Portal — session management via server-side sessions.
 *
 * Clients authenticate via magic links (no Clerk). The session is a
 * signed JSON payload in a server-side session. All /client/* and
 * /api/client-portal/data/* routes use getClientSession() instead
 * of getCurrentUser().
 */

import { cookies } from "next/headers";
import { prisma } from "@/lib/prisma";
import { resolvePortalConfig, type PortalConfig } from "@/lib/portal-config";
import { hasPermission as checkPerm } from "@/lib/portal-permissions";

const COOKIE_NAME = "meseo_client_session";
const COOKIE_MAX_AGE = 7 * 24 * 60 * 60; // 7 days
const SECRET = process.env.CLIENT_SESSION_SECRET || process.env.CRON_SECRET || "meseo-client-dev-secret";

export interface ClientSession {
  portalId: string;
  clientUserId: string;
  brandId: string;
  email: string;
  role: string;
  agencyName: string | null;
  agencyLogo: string | null;
  primaryColor: string | null;
  permissions: Record<string, boolean>;
  allowedPages: string[];
  portalConfig: PortalConfig;
  hideSourceBranding: boolean;
}

/** Simple HMAC-like signature using base64(JSON) + hash suffix. */
function sign(payload: string): string {
  let hash = 0;
  const str = payload + SECRET;
  for (let i = 0; i < str.length; i++) { hash = ((hash << 5) - hash + str.charCodeAt(i)) | 0; }
  return payload + "." + Math.abs(hash).toString(36);
}

function verify(token: string): string | null {
  const dot = token.lastIndexOf(".");
  if (dot < 0) return null;
  const payload = token.slice(0, dot);
  if (sign(payload) !== token) return null;
  return payload;
}

export function setClientSessionCookie(session: ClientSession): void {
  const payload = Buffer.from(JSON.stringify(session)).toString("base64");
  const signed = sign(payload);
  cookies().set(COOKIE_NAME, signed, {
    httpOnly: true,
    secure: process.env.NODE_ENV === "production",
    sameSite: "lax",
    path: "/",
    maxAge: COOKIE_MAX_AGE,
  });
}

export function clearClientSessionCookie(): void {
  cookies().set(COOKIE_NAME, "", { httpOnly: true, path: "/", maxAge: 0 });
}

export function getClientSession(): ClientSession | null {
  const raw = cookies().get(COOKIE_NAME)?.value;
  if (!raw) return null;
  const payload = verify(raw);
  if (!payload) return null;
  try {
    return JSON.parse(Buffer.from(payload, "base64").toString("utf8")) as ClientSession;
  } catch { return null; }
}

/**
 * Checks that the client session is valid and the requested brand
 * matches. Returns the session + fresh portal config, or an error.
 */
export async function requireClientAuth(brandId: string): Promise<
  { ok: true; session: ClientSession } | { ok: false; error: string; status: number }
> {
  const session = getClientSession();
  if (!session) return { ok: false, error: "Not authenticated", status: 401 };
  if (session.brandId !== brandId) return { ok: false, error: "Access denied", status: 403 };

  // Verify the user + portal still exist and are active
  const user = await prisma.clientUser.findUnique({
    where: { id: session.clientUserId },
    include: { portal: true },
  });
  if (!user || !user.isActive || !user.portal.isEnabled) {
    return { ok: false, error: "Session expired", status: 401 };
  }

  return { ok: true, session };
}

/**
 * Checks that a specific page is allowed for this portal.
 */
export function pageAllowed(session: ClientSession, page: string): boolean {
  if (session.portalConfig?.pages?.[page]?.enabled) return true;
  return session.allowedPages.includes(page);
}

/**
 * Checks a specific section within a page.
 */
export function sectionAllowed(session: ClientSession, page: string, section: string): boolean {
  const pageConfig = session.portalConfig?.pages?.[page];
  if (!pageConfig?.enabled) return false;
  if (!pageConfig.sections) return true;
  return pageConfig.sections[section] !== false;
}

/**
 * Checks a specific granular permission for the client user.
 */
export function permissionAllowed(session: ClientSession, permission: string): boolean {
  return checkPerm(session.role, session.permissions, permission);
}

/**
 * Returns 403 if the session lacks the given permission.
 */
export function requirePermission(session: ClientSession, permission: string): { ok: true } | { ok: false; error: string; status: 403 } {
  if (!permissionAllowed(session, permission)) {
    return { ok: false, error: `Permission denied: ${permission}`, status: 403 };
  }
  return { ok: true };
}
