import { Handlers, PageProps } from "$fresh/server.ts";
import { Page } from "@/components/Page.tsx";
import { PostgresError, queryObject } from "@/db/mod.ts";
import { hash } from "https://deno.land/x/bcrypt@v0.4.1/mod.ts";

type UserID = string;

interface RegistrationError {
  message: string;
}

export const handler: Handlers<UserID | RegistrationError | null> = {
  async POST(request, context) {
    const formData = (await request.formData());
    const username = formData.get("username");
    const password = formData.get("password");
    // TODO: verify that username conforms to some regex? no spaces?
    if (!username) {
      return await context.render({ message: "no username provided" });
    }
    if (!password) {
      return await context.render({ message: "no password provided" });
    }
    const password_digest = await hash(password.toString());
    try {
      const result = await queryObject<{ userId: string }>(
        `
        with new_user as (
          insert into "user" (username, password_digest, status)
            values ($username, $password_digest, 'unverified')
            returning id as user_id
        ), new_team as (
          insert into "team" (display_name)
            values ($team_name)
            returning id as team_id
        )
        insert into "team_user" (user_id, team_id, status)
          values (
            (select user_id from new_user),
            (select team_id from new_team),
            'owner'
          ) returning user_id
        `,
        { username, password_digest, team_name: `${username}'s First Team` },
      );
      console.debug(result);
      if (!result) throw "insert failed";
      const { rows: [{ userId: id }] } = result;
      return await context.render(id);
    } catch (err) {
      if (
        err instanceof PostgresError && err.fields.code == "23505" &&
        err.fields.constraint == "user_username_key"
      ) {
        return await context.render({
          message: `A user with username '${username}' already exists`,
        });
      } else if (
        err instanceof PostgresError && err.fields.code == "23514" &&
        err.fields.constraint == "valid_username"
      ) {
        return await context.render({
          message:
            `Username must ONLY be comprised of letters, number, dashes, and underscores`,
        });
      }
      throw err;
    }
  },
};

export default function Register(
  { data: userId }: PageProps<UserID | RegistrationError | null>,
) {
  if (typeof userId == "string") {
    return RegistrationSuccessful(userId);
  } else {
    return RegistrationForm(userId);
  }
}

function RegistrationSuccessful(_userId: UserID) {
  return (
    <Page>
      <p>
        You're all signed up! Let's go <a href="/login">log in</a>!
      </p>
    </Page>
  );
}

function RegistrationForm(props?: RegistrationError | null) {
  console.log(props);
  return (
    <Page>
      <h1 class="text-4xl mb-4">Register your account</h1>
      {props != null &&
        (
          <p class="text-red-500">
            <strong>Error</strong>: {props.message}
          </p>
        )}
      <form class="flex flex-col max-w-lg" method="post">
        <label for="username">Username</label>
        <input type="text" name="username" />
        <label for="password">Password</label>
        <input type="password" name="password" />
        <input
          class="bg-blue-800 px-4 p-2 mt-2"
          type="submit"
          value="Register"
        />
      </form>
    </Page>
  );
}
