import type { Database } from "@xtablo/shared-types";
import { Hono } from "hono";
import { createFactory } from "hono/factory";
import { checkTabloMember } from "../helpers/helpers.js";
import type { AuthEnv } from "../types/app.types.js";

type Note = Database["public"]["Tables"]["notes"]["Row"];

const factory = createFactory<AuthEnv>();

/**
 * Fetch notes shared with a specific tablo
 */
const getTabloNotes = factory.createHandlers(checkTabloMember, async (c) => {
  const tabloId = c.req.param("tabloId");

  if (!tabloId) {
    return c.json({ error: "Tablo ID is required" }, 400);
  }

  const supabase = c.get("supabase");

  // Find the tablo owner
  const { data: tabloData, error: tabloError } = await supabase
    .from("tablos")
    .select("owner_id")
    .eq("id", tabloId)
    .single();

  if (tabloError) {
    console.error("Error fetching tablo:", tabloError);
    return c.json({ error: "Failed to fetch tablo" }, 500);
  }

  if (!tabloData) {
    return c.json({ error: "Tablo not found" }, 404);
  }

  const tabloOwnerId = tabloData.owner_id;

  // Find notes shared with this specific tablo or all tablos
  const { data, error } = await supabase
    .from("note_access")
    .select(`
      note_id,
      notes!inner (
        id,
        title,
        content,
        user_id,
        created_at,
        updated_at,
        deleted_at
      )
    `)
    .eq("is_active", true)
    .eq("user_id", tabloOwnerId)
    .or(`tablo_id.eq.${tabloId},tablo_id.is.null`)
    .is("notes.deleted_at", null);

  if (error) {
    return c.json({ error: "An error occurred" }, 500);
  }

  // Extract notes from the join result and remove duplicates
  type JoinedResult = { note_id: string; notes: Note[] };
  const extractedNotes = (data as JoinedResult[])
    .map((item) => (Array.isArray(item.notes) ? item.notes[0] : item.notes))
    .filter((note) => note !== null && note !== undefined);

  // Remove duplicates by note id (in case a note is shared both with all tablos and this specific tablo)
  const uniqueNotes = Array.from(new Map(extractedNotes.map((note) => [note.id, note])).values());

  return c.json({ notes: uniqueNotes });
});

export const getNotesRouter = () => {
  const notesRouter = new Hono();
  notesRouter.get("/:tabloId", ...getTabloNotes);

  return notesRouter;
};
