import { prisma } from '@/db';
import { auth } from '@/lib/auth';
import { parseError } from '@/lib/errors';
import { DB_TABLE, LOG_ACTION } from '@/types/enum';
import { authMiddleware } from '@lib/middleware';
import { createServerFn } from '@tanstack/react-start';
import { getRequestHeaders } from '@tanstack/react-start/server';
import z from 'zod';
import { saveFile } from './disk-storage';
import { createAuditLog } from './repository';
import { changePasswordBESchema } from './user.schema';

export const updateProfile = createServerFn({ method: 'POST' })
  .middleware([authMiddleware])
  .validator(z.instanceof(FormData))
  .handler(async ({ data: formData, context: { user } }) => {
    try {
      let imageKey;
      const file = formData.get('file') as File;
      if (file) {
        const uuid = crypto.randomUUID();
        if (!(file instanceof File)) throw new Error('File not found');
        const buffer = Buffer.from(await file.arrayBuffer());
        imageKey = await saveFile(`${uuid}.${file.type.split('/')[1]}`, buffer);
      }

      const getOldUser = await prisma.user.findUnique({
        where: { id: user.id },
      });

      const name = formData.get('name') as string;

      const newUser = JSON.parse(JSON.stringify({ name, image: imageKey }));
      const keys = Object.keys(newUser);
      const oldUser = Object.fromEntries(
        Object.entries(getOldUser || {}).filter(([key]) => keys.includes(key)),
      );

      const headers = getRequestHeaders();
      const result = await auth.api.updateUser({
        body: newUser,
        headers,
      });

      await createAuditLog({
        action: LOG_ACTION.UPDATE,
        tableName: DB_TABLE.USER,
        recordId: user.id,
        oldValue: JSON.stringify(oldUser),
        newValue: JSON.stringify(newUser),
        userId: user.id,
      });

      return result;
    } catch (error) {
      console.error(error);
      const { message, code } = parseError(error);
      throw { message, code };
    }
  });

export const changePassword = createServerFn({ method: 'POST' })
  .middleware([authMiddleware])
  .validator(changePasswordBESchema)
  .handler(async ({ data, context: { user } }) => {
    try {
      const headers = getRequestHeaders();
      const result = await auth.api.changePassword({
        body: {
          newPassword: data.newPassword, // required
          currentPassword: data.currentPassword, // required
          revokeOtherSessions: true,
        },
        headers,
      });

      await createAuditLog({
        action: LOG_ACTION.CHANGE_PASSWORD,
        tableName: DB_TABLE.ACCOUNT,
        recordId: user.id,
        oldValue: 'Change Password',
        newValue: 'Change Password',
        userId: user.id,
      });

      return result;
    } catch (error) {
      // console.error(error);
      const { message, code } = parseError(error);
      throw { message, code };
    }
  });
