import { z } from "zod/v4";
import { RedisClient } from "bun";
import { logger } from "hono/logger";
import { subjects } from "@/subjects.js";
import { issuer } from "@openauthjs/openauth";
import { User } from "@nestri/core/user/index";
import { RedisStorage } from "./src/storage.js";
import { CodeProvider } from "@openauthjs/openauth/provider/code";

const storage = RedisStorage({
  client: new RedisClient(process.env.REDIS_URL),
});

const app = issuer({
  subjects,
  storage,
  providers: {
    email: CodeProvider({
      async request(_req, state, form, error) {
        console.log(state);
        const params = new URLSearchParams();
        if (error) {
          params.set("error", error.type);
        }
        if (state.type === "start") {
          return Response.redirect(
            process.env.AUTH_FRONTEND_URL + "/auth/email?" + params.toString(),
            302,
          );
        }

        if (state.type === "code") {
          return Response.redirect(
            process.env.AUTH_FRONTEND_URL + "/auth/code?" + params.toString(),
            302,
          );
        }

        return new Response("ok");
      },
      async sendCode(claims, code) {
        const email = z.email().parse(claims.email);
        console.log(`Sending code ${code} to email ${email}`);
      },
    }),
  },
  success: async (ctx, res) => {
    let email = res.claims.email;

    if (!email) throw new Error("No email found");

    let userID = await User.fromEmail(email).then((x) => x?.id);
    if (!userID) {
      console.log("creating account for", email);
      userID = await User.create({
        email: email!,
        name: null,
      });
    }
    return ctx.subject("user", email!, {
      userID: userID!,
      email: email,
    });
  },
  async allow(input) {
    const url = new URL(input.redirectURI);
    return (
      url.hostname.endsWith("localhost") || url.hostname.endsWith("nestri.io")
    );
  },
}).use(logger());

export default {
  port: 3000,
  fetch: app.fetch,
};
