import { z } from "zod";
import type { TRPCContext } from "../trpc.js";
import {
  auditLogByEntityInputSchema,
  auditLogListInputSchema,
  auditLogTimelineInputSchema,
} from "./audit-log-inputs.js";
import {
  formatAuditDetailEntry,
  formatAuditListEntry,
  getAuditActivitySummary,
  getAuditEntriesByEntity,
  getAuditEntryById,
  getAuditTimeline,
  listAuditEntries,
  toAuditListInput,
  toAuditTimelineInput,
} from "./audit-log-support.js";

export { auditLogByEntityInputSchema, auditLogListInputSchema, auditLogTimelineInputSchema };

export const auditLogEntryByIdInputSchema = z.object({
  id: z.string(),
});

export const auditLogActivitySummaryInputSchema = z.object({
  startDate: z.date().optional(),
  endDate: z.date().optional(),
});

type AuditLogContext = Pick<TRPCContext, "db">;

export async function listAuditLogEntries(
  ctx: AuditLogContext,
  input: z.infer<typeof auditLogListInputSchema>,
) {
  return listAuditEntries(ctx.db, toAuditListInput({
    entityType: input.entityType,
    entityId: input.entityId,
    userId: input.userId,
    action: input.action,
    source: input.source,
    startDate: input.startDate,
    endDate: input.endDate,
    search: input.search,
    limit: input.limit,
    cursor: input.cursor,
  }));
}

export async function listAuditLogEntriesDetail(
  ctx: AuditLogContext,
  input: z.infer<typeof auditLogListInputSchema>,
) {
  const result = await listAuditLogEntries(ctx, input);
  return {
    items: result.items.map(formatAuditListEntry),
    nextCursor: result.nextCursor ?? null,
  };
}

export async function getAuditLogEntryById(
  ctx: AuditLogContext,
  input: z.infer<typeof auditLogEntryByIdInputSchema>,
) {
  return getAuditEntryById(ctx.db, input.id);
}

export async function getAuditLogEntryByIdDetail(
  ctx: AuditLogContext,
  input: z.infer<typeof auditLogEntryByIdInputSchema>,
) {
  const entry = await getAuditEntryById(ctx.db, input.id);
  return formatAuditDetailEntry(entry);
}

export async function getAuditLogEntriesByEntity(
  ctx: AuditLogContext,
  input: z.infer<typeof auditLogByEntityInputSchema>,
) {
  return getAuditEntriesByEntity(ctx.db, input);
}

export async function getAuditLogEntriesByEntityDetail(
  ctx: AuditLogContext,
  input: z.infer<typeof auditLogByEntityInputSchema>,
) {
  const entries = await getAuditEntriesByEntity(ctx.db, input);
  return {
    entityType: input.entityType,
    entityId: input.entityId,
    entityName: entries[0]?.entityName ?? null,
    itemCount: entries.length,
    items: entries.map(formatAuditDetailEntry),
  };
}

export async function getAuditLogTimeline(
  ctx: AuditLogContext,
  input: z.infer<typeof auditLogTimelineInputSchema>,
) {
  return getAuditTimeline(ctx.db, toAuditTimelineInput({
    startDate: input.startDate,
    endDate: input.endDate,
    limit: input.limit,
  }));
}

export async function getAuditLogTimelineDetail(
  ctx: AuditLogContext,
  input: z.infer<typeof auditLogTimelineInputSchema>,
) {
  const timeline = await getAuditLogTimeline(ctx, input);
  return Object.fromEntries(
    Object.entries(timeline).map(([dateKey, entries]) => [
      dateKey,
      entries.map(formatAuditDetailEntry),
    ]),
  );
}

export async function getAuditLogActivitySummary(
  ctx: AuditLogContext,
  input: z.infer<typeof auditLogActivitySummaryInputSchema>,
) {
  return getAuditActivitySummary(ctx.db, input);
}
