/**
 * Appointment Types Domain Adapter
 *
 * Routes appointment_types model directly to Convex queries/mutations.
 */

import { convexQuery, convexMutation } from "@/lib/convex-client";

type ConvexDoc = Record<string, unknown>;

function shapeDocs(docs: ConvexDoc[]): ConvexDoc[] {
  return docs.map((d) => ({ ...d, id: (d.prismaId as string) || (d._id as string) }));
}

export const appointmentTypesAdapter = {
  async findMany(args: {
    where?: Record<string, unknown>;
    select?: Record<string, unknown>;
    orderBy?: Record<string, unknown> | Record<string, unknown>[];
    skip?: number;
    take?: number;
  }) {
    const orgId = args.where?.organizationId as string | undefined;
    if (!orgId) return [];
    const isActive = args.where?.isActive;
    const fn = isActive === true
      ? "appointment_types/queries:getActiveByOrganization"
      : "appointment_types/queries:list";
    const docs = await convexQuery<ConvexDoc[]>(fn, { organizationId: orgId });
    let filtered = docs ?? [];
    // Apply additional where filters in memory
    const category = args.where?.category as string | undefined;
    if (category) {
      filtered = filtered.filter(d => d.category === category);
    }
    // Filter out null categories if requested
    if (args.where?.category && typeof args.where.category === 'object') {
      const op = args.where.category as Record<string, unknown>;
      if ('not' in op && op.not === null) {
        filtered = filtered.filter(d => d.category != null && d.category !== '');
      }
    }
    return shapeDocs(filtered);
  },

  async findFirst(args: { where?: Record<string, unknown>; select?: Record<string, unknown> }) {
    const orgId = args.where?.organizationId as string | undefined;
    if (!orgId) return null;
    const docs = await convexQuery<ConvexDoc[]>(
      "appointment_types/queries:list",
      { organizationId: orgId },
    );
    return docs?.[0] ? { ...docs[0], id: (docs[0].prismaId as string) || (docs[0]._id as string) } : null;
  },

  async findUnique(args: { where: Record<string, unknown> }) {
    const id = (args.where.id || args.where._id) as string;
    if (!id) return null;
    const doc = await convexQuery<ConvexDoc | null>(
      "appointment_types/queries:getById",
      { id },
    );
    return doc ? { ...doc, id: (doc.prismaId as string) || (doc._id as string) } : null;
  },

  async groupBy(args: {
    by: string[];
    where?: Record<string, unknown>;
    _count?: Record<string, boolean>;
    orderBy?: Record<string, unknown>;
  }) {
    const orgId = args.where?.organizationId as string | undefined;
    if (!orgId) return [];
    const docs = await convexQuery<ConvexDoc[]>(
      "appointment_types/queries:getActiveByOrganization",
      { organizationId: orgId },
    );
    if (!docs?.length) return [];

    // Group by the requested fields
    const byFields = args.by ?? ['category'];
    const groupMap = new Map<string, ConvexDoc>();
    for (const doc of docs) {
      const key = byFields.map(f => String(doc[f] ?? '')).join('|');
      if (!groupMap.has(key)) {
        const group: ConvexDoc = { _count: { id: 0 } };
        for (const f of byFields) group[f] = doc[f];
        groupMap.set(key, group);
      }
      (groupMap.get(key)!._count as Record<string, number>).id++;
    }

    return [...groupMap.values()].sort(
      (a, b) => ((b._count as Record<string, number>).id ?? 0) - ((a._count as Record<string, number>).id ?? 0)
    );
  },

  async aggregate(args: { where?: Record<string, unknown>; _max?: Record<string, boolean> }) {
    const orgId = args.where?.organizationId as string | undefined;
    if (!orgId) return { _max: { sortOrder: -1 } };
    const docs = await convexQuery<ConvexDoc[]>(
      "appointment_types/queries:list",
      { organizationId: orgId },
    );
    const sortOrders = (docs ?? []).map((d) => (d.sortOrder as number) ?? 0);
    return { _max: { sortOrder: sortOrders.length ? Math.max(...sortOrders) : -1 } };
  },

  async create(args: { data: Record<string, unknown> }) {
    const data = args.data;
    await convexMutation("appointment_types/mutations:createBulk", {
      organizationId: data.organizationId as string,
      types: [{
        nameEn: data.nameEn as string,
        nameAr: (data.nameAr as string) || "",
        duration: (data.duration as number) || 30,
        price: data.price as number | undefined,
        category: data.category as string | undefined,
        categoryAr: data.categoryAr as string | undefined,
        itemType: data.itemType as string | undefined,
        isActive: (data.isActive as boolean) ?? true,
        sortOrder: (data.sortOrder as number) || 0,
      }],
    });
    return data;
  },

  async createMany(args: { data: Record<string, unknown>[]; skipDuplicates?: boolean }) {
    if (!args.data.length) return { count: 0 };
    const orgId = args.data[0].organizationId as string;
    if (!orgId) return { count: 0 };

    await convexMutation("appointment_types/mutations:createBulk", {
      organizationId: orgId,
      types: args.data.map((d) => ({
        nameEn: d.nameEn as string,
        nameAr: (d.nameAr as string) || "",
        duration: (d.duration as number) || 30,
        price: d.price as number | undefined,
        category: d.category as string | undefined,
        categoryAr: d.categoryAr as string | undefined,
        itemType: d.itemType as string | undefined,
        isActive: (d.isActive as boolean) ?? true,
        sortOrder: (d.sortOrder as number) || 0,
      })),
    });
    return { count: args.data.length };
  },

  async update(args: { where: Record<string, unknown>; data: Record<string, unknown> }) {
    // Not yet implemented in Convex — no-op
    void args;
    return args.data;
  },

  async count(args?: { where?: Record<string, unknown> }) {
    const orgId = args?.where?.organizationId as string | undefined;
    if (!orgId) return 0;
    const docs = await convexQuery<ConvexDoc[]>(
      "appointment_types/queries:list",
      { organizationId: orgId },
    );
    return docs?.length ?? 0;
  },
};
