import { and, asc, eq } from "drizzle-orm";
import { getDb } from "@/core/db/client";
import { services } from "@/core/db/schema";
import { normalizeSlug } from "@/core/tenant/slug";
import type { TenantContext } from "@/core/tenant/types";

export type ServiceInput = {
  title: string;
  slug?: string;
  description?: string;
  sortOrder?: number;
  isPublished?: boolean;
};

export async function listDashboardServices(ctx: TenantContext) {
  const db = getDb();
  return db
    .select()
    .from(services)
    .where(eq(services.tenantId, ctx.tenantId))
    .orderBy(asc(services.sortOrder), asc(services.createdAt));
}

export async function listPublishedServices(ctx: TenantContext) {
  const db = getDb();
  return db
    .select()
    .from(services)
    .where(
      and(eq(services.tenantId, ctx.tenantId), eq(services.isPublished, true)),
    )
    .orderBy(asc(services.sortOrder), asc(services.createdAt));
}

export async function getPublishedServiceBySlug(
  ctx: TenantContext,
  slug: string,
) {
  const db = getDb();
  const [row] = await db
    .select()
    .from(services)
    .where(
      and(
        eq(services.tenantId, ctx.tenantId),
        eq(services.slug, slug),
        eq(services.isPublished, true),
      ),
    )
    .limit(1);
  return row ?? null;
}

export async function getServiceForTenant(ctx: TenantContext, serviceId: string) {
  const db = getDb();
  const [row] = await db
    .select()
    .from(services)
    .where(
      and(eq(services.id, serviceId), eq(services.tenantId, ctx.tenantId)),
    )
    .limit(1);
  return row ?? null;
}

export async function createService(ctx: TenantContext, input: ServiceInput) {
  const db = getDb();
  const slug = normalizeSlug(input.slug || input.title);
  const [row] = await db
    .insert(services)
    .values({
      tenantId: ctx.tenantId,
      title: input.title.trim(),
      slug,
      description: input.description?.trim() || null,
      sortOrder: input.sortOrder ?? 0,
      isPublished: input.isPublished ?? true,
    })
    .returning();
  return row;
}

export async function updateService(
  ctx: TenantContext,
  serviceId: string,
  input: Partial<ServiceInput>,
) {
  const existing = await getServiceForTenant(ctx, serviceId);
  if (!existing) return null;

  const db = getDb();
  const slug = input.slug
    ? normalizeSlug(input.slug)
    : input.title
      ? normalizeSlug(input.title)
      : undefined;

  const [updated] = await db
    .update(services)
    .set({
      ...(input.title !== undefined ? { title: input.title.trim() } : {}),
      ...(slug ? { slug } : {}),
      ...(input.description !== undefined
        ? { description: input.description.trim() || null }
        : {}),
      ...(input.sortOrder !== undefined ? { sortOrder: input.sortOrder } : {}),
      ...(input.isPublished !== undefined
        ? { isPublished: input.isPublished }
        : {}),
      updatedAt: new Date(),
    })
    .where(
      and(eq(services.id, serviceId), eq(services.tenantId, ctx.tenantId)),
    )
    .returning();

  return updated ?? null;
}

export async function toggleServicePublish(
  ctx: TenantContext,
  serviceId: string,
) {
  const existing = await getServiceForTenant(ctx, serviceId);
  if (!existing) return null;
  return updateService(ctx, serviceId, { isPublished: !existing.isPublished });
}

export async function deleteService(ctx: TenantContext, serviceId: string) {
  const db = getDb();
  const [deleted] = await db
    .delete(services)
    .where(
      and(eq(services.id, serviceId), eq(services.tenantId, ctx.tenantId)),
    )
    .returning({ id: services.id });
  return deleted ?? null;
}
