import { cleanText } from "./text";
import { getAdminPassword, unauthorized } from "./http";

export function parseCookie(header: string): Record<string, string> {
  const out: Record<string, string> = {};
  if (!header) return out;
  for (const part of header.split(";")) {
    const idx = part.indexOf("=");
    if (idx === -1) continue;
    const k = part.slice(0, idx).trim();
    const v = part.slice(idx + 1).trim();
    try {
      out[k] = decodeURIComponent(v);
    } catch {
      out[k] = v;
    }
  }
  return out;
}

export async function adminSessionCookieValue(env: Env): Promise<string> {
  const password = getAdminPassword(env);
  const enc = new TextEncoder();
  const data = enc.encode(`${password}\0sproutblog_admin_v1`);
  const hash = await crypto.subtle.digest("SHA-256", data);
  return [...new Uint8Array(hash)]
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");
}

/**
 * 需要后台权限的接口：未配置密码则放行；否则校验 Cookie 或 Basic Auth。
 * 返回 null 表示已通过；返回 Response 为 401。
 */
export async function requireAdmin(
  request: Request,
  env: Env
): Promise<Response | null> {
  const password = getAdminPassword(env);
  if (!password) return null;

  const cookies = parseCookie(request.headers.get("Cookie") || "");
  const expected = await adminSessionCookieValue(env);
  if (cookies.sb_admin && cookies.sb_admin === expected) {
    return null;
  }

  const header = request.headers.get("Authorization") || "";
  if (header.startsWith("Basic ")) {
    try {
      const decoded = atob(header.slice(6));
      const split = decoded.indexOf(":");
      const inputPassword = split >= 0 ? decoded.slice(split + 1) : "";
      if (inputPassword === password) return null;
    } catch {
      /* ignore */
    }
  }

  return unauthorized();
}

/** 已配置密码且当前请求具备后台凭证（Cookie / Basic） */
export async function hasValidAdminSession(
  request: Request,
  env: Env
): Promise<boolean> {
  const password = getAdminPassword(env);
  if (!password) return false;
  return (await requireAdmin(request, env)) === null;
}

/** 是否可列出/阅读草稿（未配置密码时保持原先「全量可见」行为） */
export async function canAccessDrafts(request: Request, env: Env): Promise<boolean> {
  const password = getAdminPassword(env);
  if (!password) return true;
  return (await requireAdmin(request, env)) === null;
}
