import { T as TOKEN } from './chunks/middleware_BbZL2mEI.mjs';
import { h as hashPassword, v as validateCredentials, c as createToken, a as verifyToken, b as changeUserPassword, g as getOneUserEmail, n as newUser, u as updateUser, d as getOneUser } from './chunks/auths_D_cJY4N0.mjs';
import { createTransport } from 'nodemailer';
import { Eta } from 'eta';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import { g as getActionQueryString, a as astroCalledServerError, A as ActionError, d as deserializeActionResult, b as ACTION_QUERY_PARAMS, c as appendForwardSlash } from './chunks/astro-designed-error-pages_CWF1RsOW.mjs';
import './chunks/astro/server_5mFihzcn.mjs';
import 'clsx';
import 'cookie';
import { d as defineAction, o as objectType, a as stringType, b as booleanType, n as numberType } from './chunks/sequence_Yn7vKis0.mjs';
import { SignJWT } from 'jose';
import { nanoid } from 'nanoid';
import { n as newMessage, g as getOneMessage, r as replyToMessage } from './chunks/message_DAReJ7u_.mjs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const eta = new Eta({
  views: join(__dirname, "./"),
  useWith: true
});
const transport = createTransport({
  host: undefined                           ,
  port: undefined                         ,
  secure: undefined                           ,
  auth: {
    // TODO: replace `user` and `pass` values from <https://forwardemail.net>
    user: undefined                             ,
    pass: undefined                             
  }
});
const sendEmail = async ({
  data = {},
  template = "welcome",
  ...rest
}) => {
  const subject = rest.subject ?? "WELCOME";
  const from = `Sambekiel & Co Resources <${rest.from ?? undefined                             }>`;
  const to = rest.to ?? undefined                          ;
  const replyTo = rest.replyTo ?? rest.from ?? undefined                          ;
  const html = await eta.renderAsync(template, {
    ...data,
    subject
  });
  const text = html.replace(/<head[^>]*>.*?<\/head>/gis, "").replace(/<[^>]*>?/gm, "");
  return await transport.sendMail({ ...rest, text, html, from, to, replyTo });
};

const apiContextRoutesSymbol = Symbol.for("context.routes");
const ENCODED_DOT = "%2E";
function toActionProxy(actionCallback = {}, aggregatedPath = "") {
  return new Proxy(actionCallback, {
    get(target, objKey) {
      if (objKey in target || typeof objKey === "symbol") {
        return target[objKey];
      }
      const path = aggregatedPath + encodeURIComponent(objKey.toString()).replaceAll(".", ENCODED_DOT);
      function action(param) {
        return handleAction(param, path, this);
      }
      Object.assign(action, {
        queryString: getActionQueryString(path),
        toString: () => action.queryString,
        // Progressive enhancement info for React.
        $$FORM_ACTION: function() {
          const searchParams = new URLSearchParams(action.toString());
          return {
            method: "POST",
            // `name` creates a hidden input.
            // It's unused by Astro, but we can't turn this off.
            // At least use a name that won't conflict with a user's formData.
            name: "_astroAction",
            action: "?" + searchParams.toString()
          };
        },
        // Note: `orThrow` does not have progressive enhancement info.
        // If you want to throw exceptions,
        //  you must handle those exceptions with client JS.
        async orThrow(param) {
          const { data, error } = await handleAction(param, path, this);
          if (error) throw error;
          return data;
        }
      });
      return toActionProxy(action, path + ".");
    }
  });
}
function getActionPath(action) {
  let path = `${"/".replace(/\/$/, "")}/_actions/${new URLSearchParams(action.toString()).get(ACTION_QUERY_PARAMS.actionName)}`;
  {
    path = appendForwardSlash(path);
  }
  return path;
}
async function handleAction(param, path, context) {
  if (context) {
    const pipeline = Reflect.get(context, apiContextRoutesSymbol);
    if (!pipeline) {
      throw astroCalledServerError();
    }
    const action = await pipeline.getAction(path);
    if (!action) throw new Error(`Action not found: ${path}`);
    return action.bind(context)(param);
  }
  const headers = new Headers();
  headers.set("Accept", "application/json");
  let body = param;
  if (!(body instanceof FormData)) {
    try {
      body = JSON.stringify(param);
    } catch (e) {
      throw new ActionError({
        code: "BAD_REQUEST",
        message: `Failed to serialize request body to JSON. Full error: ${e.message}`
      });
    }
    if (body) {
      headers.set("Content-Type", "application/json");
    } else {
      headers.set("Content-Length", "0");
    }
  }
  const rawResult = await fetch(
    getActionPath({
      toString() {
        return getActionQueryString(path);
      }
    }),
    {
      method: "POST",
      body,
      headers
    }
  );
  if (rawResult.status === 204) {
    return deserializeActionResult({ type: "empty", status: 204 });
  }
  return deserializeActionResult({
    type: rawResult.ok ? "data" : "error",
    body: await rawResult.text()
  });
}
toActionProxy();

const secret = new TextEncoder().encode(undefined                              );
const login = defineAction({
  accept: "form",
  input: objectType({
    email: stringType().email(),
    password: stringType()
  }),
  handler: async ({ email, password }, ctx) => {
    const hash = await hashPassword(password);
    console.log({ hash });
    const user = await validateCredentials({ email, password });
    if (!user) {
      throw new ActionError({
        code: "UNAUTHORIZED",
        message: "Invalid email/password"
      });
    }
    const token = await new SignJWT({
      user: { ...user, password: void 0 }
    }).setProtectedHeader({ alg: "HS256" }).setJti(nanoid()).setIssuedAt().sign(secret);
    ctx.cookies.set(TOKEN, token, {
      httpOnly: true,
      path: "/",
      maxAge: 60 * 60 * 24 * 2
      // 2 days in seconds
    });
    return {
      message: "You're logged in!",
      token
    };
  }
});
const forgotPassword = defineAction({
  accept: "form",
  input: objectType({
    email: stringType().email()
  }),
  handler: async ({ email }, ctx) => {
    try {
      const token = await createToken(email);
      const base_url = `${ctx.url.protocol}//${ctx.url.host}`;
      const link = `${base_url}/dashboard/reset-password?token=${token.token}`;
      console.log({ base_url, link });
      await Promise.all([
        sendEmail({
          data: {
            link,
            name: token.user?.firstName ?? "",
            email: token.user?.email ?? email
          },
          to: email,
          subject: "PASSWORD RESET",
          template: "reset"
        })
      ]);
      return {
        message: "Kindly check your email"
      };
    } catch (error) {
      console.log(error);
      if (error instanceof ActionError) {
        throw error;
      }
      throw new ActionError({
        code: "INTERNAL_SERVER_ERROR",
        message: "Something went wrong"
      });
    }
  }
});
const resetPassword = defineAction({
  accept: "form",
  input: objectType({
    email: stringType().email(),
    token: stringType(),
    password: stringType().min(6),
    confirm_password: stringType()
  }).refine((data) => data.password === data.confirm_password, {
    message: "Passwords don't match",
    path: ["confirm_password"]
  }),
  handler: async ({ email, token, password }, ctx) => {
    try {
      const valid = await verifyToken({ email, token });
      if (!valid) {
        throw new ActionError({
          code: "UNAUTHORIZED",
          message: "Invalid / Expired token"
        });
      }
      await Promise.all([changeUserPassword({ email, password })]);
      return {
        message: "Password Changed, Login to continue"
      };
    } catch (error) {
      console.log(error);
      if (error instanceof ActionError) {
        throw error;
      }
      throw new ActionError({
        code: "INTERNAL_SERVER_ERROR",
        message: "Something went wrong"
      });
    }
  }
});
const register = defineAction({
  accept: "form",
  input: objectType({
    email: stringType().email(),
    lastName: stringType(),
    firstName: stringType()
  }),
  handler: async ({ email, lastName, firstName }, ctx) => {
    const exists = await getOneUserEmail(email);
    if (exists) {
      throw new ActionError({
        code: "CONFLICT",
        message: `User with Email '${email}' already exists`
      });
    }
    const password = await hashPassword(
      firstName.trim().split(" ")[0].toLowerCase()
    );
    try {
      await newUser({
        lastName,
        firstName,
        email,
        password
      });
    } catch (error) {
      throw new ActionError({
        code: "INTERNAL_SERVER_ERROR",
        message: "Error Creating User",
        stack: JSON.stringify(error)
      });
    }
    return {
      message: "Account Created!"
    };
  }
});
const logout = defineAction({
  input: objectType({}).optional().nullable(),
  handler: async (input, ctx) => {
    ctx.cookies.delete(TOKEN, { path: "/" });
  }
});
const updateProfile = defineAction({
  accept: "form",
  input: objectType({
    email: stringType().email(),
    lastName: stringType(),
    firstName: stringType(),
    phone: stringType(),
    address: stringType(),
    username: stringType(),
    id: numberType(),
    self: booleanType().optional().nullable()
  }),
  handler: async ({ email, firstName, lastName, username, phone, address, id, self }, ctx) => {
    const user = await updateUser(
      {
        email,
        firstName,
        lastName,
        username,
        phone,
        address
      },
      id
    );
    if (!user) {
      throw new ActionError({
        code: "INTERNAL_SERVER_ERROR",
        message: "Error Updating User"
      });
    }
    if (self) {
      const dbUser = await getOneUser(id);
      ctx.locals.user = { ...dbUser, password: void 0 };
      const token = await new SignJWT({
        user: { ...dbUser, password: void 0 }
      }).setProtectedHeader({ alg: "HS256" }).setJti(nanoid()).setIssuedAt().sign(secret);
      ctx.cookies.set(TOKEN, token, {
        httpOnly: true,
        path: "/",
        maxAge: 60 * 60 * 24 * 2
        // 2 days in seconds
      });
    }
    console.log(ctx.locals.user);
    return {
      message: "Profile Updated Successfully"
    };
  }
});

const UserActions = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
  __proto__: null,
  forgotPassword,
  login,
  logout,
  register,
  resetPassword,
  updateProfile
}, Symbol.toStringTag, { value: 'Module' }));

new TextEncoder().encode(undefined                              );
const sendMessage = defineAction({
  accept: "form",
  input: objectType({
    email: stringType().email(),
    name: stringType(),
    subject: stringType(),
    message: stringType()
  }),
  handler: async ({ name, email, subject, message }) => {
    const [chat, mail] = await Promise.all([
      newMessage({
        name,
        email,
        subject,
        message
      }),
      sendEmail({
        from: email,
        subject,
        text: message,
        to: "info@sambekiel.com"
      })
    ]);
    if (!chat || !mail) {
      throw new ActionError({
        code: "INTERNAL_SERVER_ERROR",
        message: "Error Occured While Submitting"
      });
    }
    return {
      message: "Message Sent Successfully"
    };
  }
});
const replyMessage = defineAction({
  accept: "form",
  input: objectType({
    email: stringType().email(),
    name: stringType(),
    subject: stringType(),
    message: stringType(),
    chat_id: numberType()
  }),
  handler: async ({ message, chat_id }, ctx) => {
    const dbChat = await getOneMessage(Number(chat_id));
    if (!dbChat) {
      throw new ActionError({
        code: "NOT_FOUND",
        message: "You can not reply a non-existing message"
      });
    }
    const [chat, mail] = await Promise.all([
      replyToMessage({
        message,
        chatId: chat_id,
        // @ts-ignore
        repliedBy: ctx.locals.user.id
      }),
      sendEmail({
        to: dbChat?.chat?.email,
        subject: `Re: ${dbChat?.chat?.subject}`,
        text: message,
        from: "info@sambekiel.com"
      })
    ]);
    if (!chat || !mail) {
      throw new ActionError({
        code: "INTERNAL_SERVER_ERROR",
        message: "Error Occured While Submitting"
      });
    }
    return {
      message: "Message Sent Successfully"
    };
  }
});

const ChatActions = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
  __proto__: null,
  replyMessage,
  sendMessage
}, Symbol.toStringTag, { value: 'Module' }));

const server = {
  ...UserActions,
  ...ChatActions
};

export { server };
