import { FastifyInstance } from "fastify";
import { ZodTypeProvider } from "fastify-type-provider-zod";
import { z } from "zod";
import { prisma } from "../../lib/prisma";
import { BadRequest } from "../_errors/bad-request";
import { cpfSchema } from "../../utils/validate-cpf";

export async function updateUser(app: FastifyInstance) {
  app
    .withTypeProvider<ZodTypeProvider>()
    .put('/users/:id', {
      schema: {
        summary: 'Update a user',
        tags: ['users'],
        params: z.object({
          id: z.string().cuid(),
        }),
        body: z.object({
          name: z.string().min(4).optional(),
          email: z.string().email().optional(),
          phone: z.string().min(9).optional(),
          cpf: z.string().min(11).optional(),
          zip: z.string().min(8).optional(),
          address: z.string().min(4).optional(),
          number: z.string().nullable().optional(),
          complement: z.string().nullable().optional(),
          district: z.string().nullable().optional(),
          city: z.string().min(2).optional(),
          state: z.string().min(2).optional(),
          details: z.string().nullable().optional(),
        }),
        response: {
          200: z.object({
            message: z.string(),
          }),
        },
      },
    }, async (request, reply) => {
      const userId = request.params.id;
      const {
        name,
        email,
        phone,
        cpf,
        zip,
        address,
        number,
        complement,
        district,
        city,
        state,
        details,
      } = request.body;

      // Verifique se o user existe
      const existingUser = await prisma.user.findUnique({
        where: {
          id: userId,
        },
      });

      if (!existingUser) {
        throw new BadRequest('User not found.');
      }

      // Verificar se o email já existe
      if (email && email !== existingUser.email) {
        const existingEmail = await prisma.user.findFirst({
          where: {
            email: email,
          },
        });


        if (existingEmail !== null) {
          throw new BadRequest('Another user with the same email already exists.');
        }
      }

      if (cpf && cpf !== existingUser.cpf) {
        const cpfValidation = cpfSchema.safeParse(cpf)

        if (!cpfValidation.success) {
          throw new BadRequest('CPF invalid.');
        }

        const cpfNumbersOnly = cpf.replace(/\D/g, '')

        // Verificar se o CPF já existe

        const existingCpf = await prisma.user.findFirst({
          where: {
            cpf: cpfNumbersOnly,
          },
        });

        if (existingCpf !== null) {
          throw new BadRequest('Another user with the same CPF already exists.');
        }
      }

      // Atualize os dados do user
      const updatedUser = await prisma.user.update({
        where: {
          id: userId,
        },
        data: {
          name: name ?? existingUser.name,
          email: email ?? existingUser.email,
          phone: phone ?? existingUser.phone,
          cpf: cpf ?? existingUser.cpf,
          zip: zip ?? existingUser.zip,
          address: address ?? existingUser.address,
          number: number ?? existingUser.number,
          complement: complement ?? existingUser.complement,
          district: district ?? existingUser.district,
          city: city ?? existingUser.city,
          state: state ?? existingUser.state,
          details: details ?? existingUser.details,
        },
      });

      return reply.status(200).send({ message: 'User updated successfully.' });
    });
}
