import { db } from "@minmon/db";
import { domain, service } from "@minmon/db";
import { count, desc, eq } from "drizzle-orm";

import { permissionedProcedure, router } from "../index";
import {
  byIdSchema,
  serviceCreateSchema,
  serviceListSchema,
  serviceUpdateSchema,
} from "./schemas";
import {
  createEntityId,
  requireServer,
  requireService,
  stripUndefined,
} from "./utils";

export const servicesRouter = router({
  list: permissionedProcedure("services.read").input(serviceListSchema).query(async ({ input }) => {
    if (!input?.serverId) {
      return db.select().from(service).orderBy(desc(service.createdAt), desc(service.id));
    }

    await requireServer(input.serverId);

    return db
      .select()
      .from(service)
      .where(eq(service.serverId, input.serverId))
      .orderBy(desc(service.createdAt), desc(service.id));
  }),

  byId: permissionedProcedure("services.read").input(byIdSchema).query(async ({ input }) => {
    const item = await requireService(input.id);
    const [domainCount] = await db.select({ count: count() }).from(domain).where(eq(domain.serviceId, input.id));

    return {
      ...item,
      summary: {
        domains: domainCount?.count ?? 0,
      },
    };
  }),

  create: permissionedProcedure("services.create").input(serviceCreateSchema).mutation(async ({ input }) => {
    await requireServer(input.serverId);

    const [created] = await db
      .insert(service)
      .values({
        id: createEntityId(),
        ...input,
      })
      .returning();

    return created;
  }),

  update: permissionedProcedure("services.update").input(serviceUpdateSchema).mutation(async ({ input }) => {
    const { id, serverId, ...changes } = input;
    await requireService(id);

    if (serverId) {
      await requireServer(serverId);
    }

    const [updated] = await db
      .update(service)
      .set(stripUndefined({ serverId, ...changes }))
      .where(eq(service.id, id))
      .returning();

    return updated;
  }),

  delete: permissionedProcedure("services.delete").input(byIdSchema).mutation(async ({ input }) => {
    await requireService(input.id);
    await db.delete(service).where(eq(service.id, input.id));
    return { id: input.id };
  }),
});
