import { z } from "zod";
import { router, publicProcedure } from "../trpc";

export const contactsRouter = router({
  getAll: publicProcedure.query(async ({ ctx }) => {
    return await ctx.queryBuilder
      .selectFrom("contacts")
      .select(["id", "firstName", "lastName", "mail", "phone1", "phone2", "notes", "createdAt", "updatedAt"])
      .orderBy("createdAt", "desc")
      .execute();
  }),

  search: publicProcedure
    .input(z.object({ query: z.string(), limit: z.number().default(5) }))
    .query(async ({ ctx, input }) => {
      const searchTerm = input.query.trim();
      
      // If no search term, return recent contacts
      if (!searchTerm) {
        return await ctx.queryBuilder
          .selectFrom("contacts")
          .select(["id", "firstName", "lastName", "mail"])
          .orderBy("createdAt", "desc")
          .limit(input.limit)
          .execute();
      }

      // Search by firstName, lastName, or mail using orWhere
      return await ctx.queryBuilder
        .selectFrom("contacts")
        .select(["id", "firstName", "lastName", "mail"])
        .where("firstName", "contains", searchTerm)
        .orWhere("lastName", "contains", searchTerm)
        .orWhere("mail", "contains", searchTerm)
        .orderBy("createdAt", "desc")
        .limit(input.limit)
        .execute();
    }),

  getById: publicProcedure
    .input(z.object({ id: z.number() }))
    .query(async ({ ctx, input }) => {
      return await ctx.queryBuilder
        .selectFrom("contacts")
        .select(["id", "firstName", "lastName", "mail", "phone1", "phone2", "notes", "createdAt", "updatedAt"])
        .with({ company: qb => qb.select(["id", "name", "website"]) })
        .where("id", "=", input.id)
        .executeTakeFirst();
    }),

  create: publicProcedure
    .input(
      z.object({
        firstName: z.string().min(1),
        lastName: z.string().min(1),
        mail: z.string().email().optional().or(z.literal("")),
        phone1: z.string().optional(),
        phone2: z.string().optional(),
        notes: z.string().optional(),
        company: z.array(z.number()).optional(),
      })
    )
    .mutation(async ({ ctx, input }) => {
      // Filter out empty mail
      const values = {
        ...input,
        mail: input.mail || undefined,
      };
      return await ctx.queryBuilder
        .insertInto("contacts")
        .values(values)
        .executeTakeFirst();
    }),

  update: publicProcedure
    .input(
      z.object({
        id: z.number(),
        firstName: z.string().optional(),
        lastName: z.string().optional(),
        mail: z.string().email().optional().or(z.literal("")),
        phone1: z.string().optional(),
        phone2: z.string().optional(),
        notes: z.string().optional(),
        company: z.array(z.number()).optional(),
      })
    )
    .mutation(async ({ ctx, input }) => {
      const { id, ...data } = input;
      // Filter out undefined values and empty mail
      const updateData = Object.fromEntries(
        Object.entries(data).filter(([key, v]) => {
          if (v === undefined) return false;
          if (key === "mail" && v === "") return false;
          return true;
        })
      ) as typeof data;
      return await ctx.queryBuilder
        .update("contacts")
        .set(updateData)
        .where("id", "=", id)
        .execute();
    }),

  delete: publicProcedure
    .input(z.object({ id: z.number() }))
    .mutation(async ({ ctx, input }) => {
      return await ctx.queryBuilder
        .deleteFrom("contacts")
        .where("id", "=", input.id)
        .execute();
    }),
});
