import { jsonResponse, readBody } from "../../lib/http";
import { requireAdmin, canAccessDrafts, hasValidAdminSession } from "../../lib/auth";
import {
  listPosts,
  readPost,
  createOrUpdatePost,
  bumpViewCount,
  deletePost,
  type PostRow
} from "../../db/posts";

function numPublished(p: PostRow): number {
  return Number(p.published) ? 1 : 0;
}

async function listForRequest(
  request: Request,
  env: Env,
  url: URL
): Promise<Response> {
  const q = (url.searchParams.get("q") || "").trim();
  const seeAll = await canAccessDrafts(request, env);
  const publishedOnly = !seeAll;
  const posts = await listPosts(env.DB, { publishedOnly, q });
  return jsonResponse({ ok: true, posts });
}

export async function handlePostsCollection(
  request: Request,
  env: Env,
  url: URL
): Promise<Response> {
  if (request.method === "GET") {
    return listForRequest(request, env, url);
  }

  if (request.method === "POST") {
    const denied = await requireAdmin(request, env);
    if (denied) return denied;
    const data = await readBody(request);
    try {
      const created = await createOrUpdatePost(env.DB, data, null);
      return jsonResponse({ ok: true, post: created }, 201);
    } catch (e) {
      const msg = e instanceof Error ? e.message : String(e);
      return jsonResponse({ ok: false, error: msg }, 400);
    }
  }

  return jsonResponse({ ok: false, error: "Method not allowed" }, 405);
}

export async function handlePostItem(
  request: Request,
  env: Env,
  url: URL,
  idOrSlug: string
): Promise<Response> {
  const bump = url.searchParams.get("bump") === "1";

  if (request.method === "GET") {
    const post = await readPost(env.DB, idOrSlug);
    if (!post) return jsonResponse({ ok: false, error: "Not found" }, 404);

    const draftsOk = await canAccessDrafts(request, env);
    if (!draftsOk && numPublished(post) !== 1) {
      return jsonResponse({ ok: false, error: "Not found" }, 404);
    }

    let row = post;
    const shouldBump =
      bump &&
      numPublished(post) === 1 &&
      !(await hasValidAdminSession(request, env));
    if (shouldBump) {
      await bumpViewCount(env.DB, Number(post.id));
      const refreshed = await readPost(env.DB, idOrSlug);
      if (refreshed) row = refreshed;
    }

    return jsonResponse({ ok: true, post: row });
  }

  if (request.method === "PUT") {
    const denied = await requireAdmin(request, env);
    if (denied) return denied;
    const data = await readBody(request);
    const existing = await readPost(env.DB, idOrSlug);
    if (!existing) return jsonResponse({ ok: false, error: "Not found" }, 404);
    try {
      const updated = await createOrUpdatePost(
        env.DB,
        data,
        Number(existing.id)
      );
      return jsonResponse({ ok: true, post: updated });
    } catch (e) {
      const msg = e instanceof Error ? e.message : String(e);
      return jsonResponse({ ok: false, error: msg }, 400);
    }
  }

  if (request.method === "DELETE") {
    const denied = await requireAdmin(request, env);
    if (denied) return denied;
    const post = await readPost(env.DB, idOrSlug);
    if (!post) return jsonResponse({ ok: false, error: "Not found" }, 404);
    await deletePost(env.DB, Number(post.id));
    return jsonResponse({ ok: true, deleted: post.id });
  }

  return jsonResponse({ ok: false, error: "Method not allowed" }, 405);
}
