import { ActionError, defineAction } from 'astro:actions';
import { z } from 'astro:schema';
import { db } from '@db/database.ts';
import { Session } from '@util/session.ts';
import { Permissions } from '@util/permissions.ts';

export const user = {
  addUser: defineAction({
    input: z.object({
      firstname: z.string(),
      lastname: z.string(),
      birthday: z.string().date(),
      telephone: z.string().nullable(),
      username: z.string(),
      edition: z.enum(['java', 'bedrock']),
      uuid: z.string().nullable()
    }),
    handler: async (input, context) => {
      Session.actionSessionFromCookies(context.cookies, Permissions.Users);

      if (await db.existsUser({ username: input.username })) {
        throw new ActionError({
          code: 'CONFLICT',
          message: 'Der Benutzername ist bereits registriert'
        });
      }

      const { id } = await db.addUser({
        firstname: input.firstname,
        lastname: input.lastname,
        birthday: input.birthday,
        telephone: input.telephone,
        username: input.username,
        edition: input.edition,
        uuid: input.uuid
      });

      return {
        id: id
      };
    }
  }),
  editUser: defineAction({
    input: z.object({
      id: z.number(),
      firstname: z.string(),
      lastname: z.string(),
      birthday: z.string().date(),
      telephone: z.string().nullable(),
      username: z.string(),
      edition: z.enum(['java', 'bedrock']),
      uuid: z.string().nullable()
    }),
    handler: async (input, context) => {
      Session.actionSessionFromCookies(context.cookies, Permissions.Users);

      const user = await db.existsUser({ username: input.username });
      if (user && user.id !== input.id) {
        throw new ActionError({
          code: 'CONFLICT',
          message: 'Ein Spieler mit dem Benutzernamen existiert bereits'
        });
      }

      await db.editUser({
        id: input.id,
        firstname: input.firstname,
        lastname: input.lastname,
        birthday: input.birthday,
        telephone: input.telephone,
        username: input.username,
        edition: input.edition,
        uuid: input.uuid
      });
    }
  }),
  deleteUser: defineAction({
    input: z.object({
      id: z.number()
    }),
    handler: async (input, context) => {
      Session.actionSessionFromCookies(context.cookies, Permissions.Users);

      await db.deleteUser(input);
    }
  }),
  users: defineAction({
    input: z.object({
      username: z.string().nullish(),
      limit: z.number().optional()
    }),
    handler: async (input, context) => {
      Session.actionSessionFromCookies(context.cookies, Permissions.Users);

      const users = await db.getUsers(input);

      return {
        users: users
      };
    }
  }),
  addBlocked: defineAction({
    input: z.object({
      uuid: z.string(),
      comment: z.string().nullable()
    }),
    handler: async (input, context) => {
      Session.actionSessionFromCookies(context.cookies, Permissions.Users);

      const { id } = await db.addBlockedUser(input);

      return {
        id: id
      };
    }
  }),
  editBlocked: defineAction({
    input: z.object({
      id: z.number(),
      uuid: z.string(),
      comment: z.string().nullable()
    }),
    handler: async (input, context) => {
      Session.actionSessionFromCookies(context.cookies, Permissions.Users);

      await db.editBlockedUser(input);
    }
  }),
  deleteBlocked: defineAction({
    input: z.object({
      id: z.number()
    }),
    handler: async (input, context) => {
      Session.actionSessionFromCookies(context.cookies, Permissions.Users);

      await db.deleteBlockedUser(input);
    }
  }),
  blocked: defineAction({
    handler: async (_, context) => {
      Session.actionSessionFromCookies(context.cookies, Permissions.Users);

      return {
        blocked: await db.getBlockedUsers({})
      };
    }
  }),
  addDirectInvitation: defineAction({
    handler: async (_, context) => {
      Session.actionSessionFromCookies(context.cookies, Permissions.Users);

      return await db.addDirectSignup({});
    }
  }),
  deleteDirectInvitation: defineAction({
    input: z.object({
      hash: z.string()
    }),
    handler: async (input, context) => {
      Session.actionSessionFromCookies(context.cookies, Permissions.Users);

      await db.deleteDirectSignup({ hash: input.hash });
    }
  }),
  directInvitations: defineAction({
    handler: async (_, context) => {
      Session.actionSessionFromCookies(context.cookies, Permissions.Users);

      return {
        directInvitations: await db.getDirectSignups({})
      };
    }
  })
};
