import { Hono } from "hono";
import { createFactory } from "hono/factory";
import { writeCalendarFileToR2 } from "../helpers/helpers.js";
import { MiddlewareManager } from "../middlewares/middleware.js";
import type { BaseEnv } from "../types/app.types.js";

const factory = createFactory<BaseEnv>();

const syncCalendars = factory.createHandlers(async (c) => {
  const supabase = c.get("supabase");
  const s3 = c.get("s3_client");

  const { data, error } = await supabase
    .from("calendar_subscriptions")
    .select("token, tablo_id, tablos(name)");
  if (error) {
    return c.json({ error: error.message }, 500);
  }

  const calendarSubscriptionsData = data as unknown as [
    {
      token: string;
      tablo_id: string;
      tablos: { name: string };
    },
  ];

  calendarSubscriptionsData.forEach(async (subscription) => {
    const tabloName = subscription.tablos.name.replace(/ /g, "_");
    await writeCalendarFileToR2(s3, supabase, {
      tabloName,
      token: subscription.token,
      tablo_id: subscription.tablo_id,
    });
  });

  return c.json({ message: "Synced calendars" });
});

const syncTabloNames = factory.createHandlers(async (c) => {
  const supabase = c.get("supabase");
  const streamServerClient = c.get("streamServerClient");

  const fifteenMinutesInMilliseconds = 1000 * 60 * 15;

  const { data, error } = await supabase
    .from("tablos")
    .select("id, name")
    .gt("updated_at", new Date(Date.now() - fifteenMinutesInMilliseconds).toISOString());

  if (error) {
    return c.json({ error: error.message }, 500);
  }

  const tablosData = data as { id: string; name: string }[];

  tablosData.forEach(async (tablo) => {
    const channel = streamServerClient.channel("messaging", tablo.id);
    try {
      await channel.update({
        // @ts-ignore
        name: tablo.name,
      });
    } catch (error) {
      console.error(`error updating channel, tablo id: ${tablo.id}, error: ${error}`);
    }
  });

  return c.json({ message: `Synced ${tablosData.length} tablo names` });
});

const syncStripeSubscriptions = factory.createHandlers(async (c) => {
  const data = await c.get("stripeSync").syncBackfill({ object: "all" });

  return c.json({ message: `Synced ${data.subscriptions?.synced} stripe subscriptions` });
});

export const getTaskRouter = () => {
  const taskRouter = new Hono();
  const middlewareManager = MiddlewareManager.getInstance();

  taskRouter.use(middlewareManager.basicAuth);

  taskRouter.post("/sync-calendars", ...syncCalendars);
  taskRouter.post("/sync-tablo-names", ...syncTabloNames);
  taskRouter.post("/sync-stripe-subscriptions", ...syncStripeSubscriptions);

  return taskRouter;
};
