import "./util/checkEnv.ts";

import { BskyAgent } from "@atproto/api";
import { serve } from "@hono/node-server";
import { Hono } from "hono";
import { HTTPException } from "hono/http-exception";
import { Redis } from "ioredis";
import { getOEmbed } from "./routes/getOEmbed.ts";
import { getPost } from "./routes/getPost.tsx";
import { getProfile } from "./routes/getProfile.tsx";

// biome-ignore lint/style/noNonNullAssertion: check is ran at app start
const redis = new Redis(6379, process.env.REDIS_HOSTNAME!);

const agent = new BskyAgent({
  // biome-ignore lint/style/noNonNullAssertion: check is ran at app start
  service: process.env.BSKY_SERVICE_URL!,
  persistSession: async (_evt, session) => {
    if (session) {
      await redis.set("session", JSON.stringify(session));
    }
  },
});

const app = new Hono<HonoEnv>();

app.use("*", async (c, next) => {
  const session = await redis.get("session");
  try {
    if (session) {
      const login = await agent.resumeSession(JSON.parse(session));
      if (!login.success) {
        await agent.login({
          // biome-ignore lint/style/noNonNullAssertion: check is ran at app start
          identifier: process.env.BSKY_AUTH_USERNAME!,
          // biome-ignore lint/style/noNonNullAssertion: check is ran at app start
          password: process.env.BSKY_AUTH_PASSWORD!,
        });
      }
    } else {
      await agent.login({
        // biome-ignore lint/style/noNonNullAssertion: check is ran at app start
        identifier: process.env.BSKY_AUTH_USERNAME!,
        // biome-ignore lint/style/noNonNullAssertion: check is ran at app start
        password: process.env.BSKY_AUTH_PASSWORD!,
      });
    }
    c.set("Agent", agent);
  } catch (error) {
    const err = new Error("Failed to login to Bluesky!", {
      cause: error,
    });
    throw new HTTPException(500, {
      message: `${err.message} \n\n ${err.cause} \n\n ${err.stack}`,
    });
  }
  return next();
});

app.get("/profile/:user/post/:post", getPost);
app.get("/https://bsky.app/profile/:user/post/:post", getPost);

app.get("/profile/:user", getProfile);
app.get("/https://bsky.app/profile/:user", getProfile);

app.get("/oembed", getOEmbed);

serve(
  {
    ...app,
    port: Number(process.env.PORT ?? 8787),
  },
  (addr) => {
    console.log(`Listening on http://localhost:${addr.port}`);
  },
);
