/**
 * Quotations Domain Adapter
 *
 * Routes quotations, quotation_items, quotation_payments, and deals
 * to Convex. These models exist ONLY in Convex (no Prisma models).
 *
 * When DS_QUOTATIONS=prisma (default), operations throw since there
 * are no Prisma tables. When DS_QUOTATIONS=convex, uses Convex backend.
 */

import { prisma } from "@/lib/db";
import { convexQuery, convexMutation } from "@/lib/convex-client";
import { getDataSource } from "@/lib/data-source";
import {
  convexToPrismaShape,
  convexToPrismaShapeMany,
  applyPagination,
  dateToConvexTimestamp,
  type ConvexDoc,
} from "./base";

const DOMAIN = "quotations" as const;
const TS_FIELDS = [
  "createdAt",
  "updatedAt",
  "sentAt",
  "respondedAt",
  "validUntil",
  "paidAt",
];
const ITEM_TS_FIELDS = ["createdAt", "updatedAt"];
const PAYMENT_TS_FIELDS = ["createdAt", "paidAt"];
const DEAL_TS_FIELDS = [
  "createdAt",
  "updatedAt",
  "closedAt",
  "expectedCloseDate",
];

function requireConvex(): void {
  if (getDataSource(DOMAIN) !== "convex") {
    throw new Error(
      "Quotations domain requires DS_QUOTATIONS=convex (no Prisma model exists)",
    );
  }
}

// ─── Quotations ─────────────────────────────────────────────────────────────

export const quotationsAdapter = {
  async findMany(args: {
    where?: Record<string, unknown>;
    orderBy?: Record<string, unknown>;
    skip?: number;
    take?: number;
  }) {
    requireConvex();
    const filters = args.where || {};
    const docs =
      (await convexQuery<ConvexDoc[]>("quotations/queries:getQuotations", {
        userId: filters.userId as string,
        status: filters.status as string | undefined,
        limit: (args.skip ?? 0) + (args.take ?? 50) + 10,
      })) || [];
    const shaped = convexToPrismaShapeMany<Record<string, unknown>>(
      docs,
      TS_FIELDS,
    );
    return applyPagination(shaped, args.skip, args.take);
  },

  async findUnique(args: { where: { id: string } }) {
    requireConvex();
    const doc = await convexQuery<ConvexDoc | null>(
      "quotations/queries:getById",
      {
        id: args.where.id,
      },
    );
    return doc
      ? convexToPrismaShape<Record<string, unknown>>(doc, TS_FIELDS)
      : null;
  },

  async create(args: { data: Record<string, unknown> }) {
    requireConvex();
    const d = args.data;
    const convexId = await convexMutation<string>(
      "quotations/mutations:createQuotation",
      {
        userId: d.userId as string,
        customerId: d.customerId as string | undefined,
        title: d.title as string,
        notes: d.notes as string | undefined,
        currency: d.currency as string | undefined,
        taxRate: d.taxRate as number | undefined,
        discountRate: d.discountRate as number | undefined,
        validUntil: dateToConvexTimestamp(
          d.validUntil as Date | string | undefined,
        ),
      },
    );
    return { ...d, id: d.id || convexId || "" };
  },

  async update(args: { where: { id: string }; data: Record<string, unknown> }) {
    requireConvex();
    const d = args.data;
    await convexMutation("quotations/mutations:updateQuotation", {
      id: args.where.id,
      title: d.title as string | undefined,
      notes: d.notes as string | undefined,
      status: d.status as string | undefined,
      taxRate: d.taxRate as number | undefined,
      discountRate: d.discountRate as number | undefined,
      validUntil: dateToConvexTimestamp(
        d.validUntil as Date | string | undefined,
      ),
    });
    return this.findUnique({ where: { id: args.where.id } });
  },

  async delete(args: { where: { id: string } }) {
    requireConvex();
    await convexMutation("quotations/mutations:updateQuotation", {
      id: args.where.id,
      status: "CANCELLED",
    });
    return { id: args.where.id };
  },

  async count(args?: { where?: Record<string, unknown> }) {
    requireConvex();
    const docs = await this.findMany({ where: args?.where });
    return docs.length;
  },
};

// ─── Quotation Items ────────────────────────────────────────────────────────

export const quotationItemsAdapter = {
  async findMany(args: { where?: Record<string, unknown> }) {
    requireConvex();
    const filters = args.where || {};
    const docs =
      (await convexQuery<ConvexDoc[]>("quotations/queries:getItems", {
        quotationId: filters.quotationId as string,
      })) || [];
    return convexToPrismaShapeMany<Record<string, unknown>>(
      docs,
      ITEM_TS_FIELDS,
    );
  },

  async create(args: { data: Record<string, unknown> }) {
    requireConvex();
    const d = args.data;
    const convexId = await convexMutation<string>(
      "quotations/mutations:addItem",
      {
        quotationId: d.quotationId as string,
        description: d.description as string,
        quantity: d.quantity as number,
        unitPrice: d.unitPrice as number,
        sortOrder: d.sortOrder as number | undefined,
      },
    );
    return { ...d, id: d.id || convexId || "" };
  },

  async delete(args: { where: { id: string } }) {
    requireConvex();
    await convexMutation("quotations/mutations:removeItem", {
      id: args.where.id,
    });
    return { id: args.where.id };
  },
};

// ─── Quotation Payments ─────────────────────────────────────────────────────

export const quotationPaymentsAdapter = {
  async findMany(args: { where?: Record<string, unknown> }) {
    requireConvex();
    const filters = args.where || {};
    const docs =
      (await convexQuery<ConvexDoc[]>("quotations/queries:getPayments", {
        quotationId: filters.quotationId as string,
      })) || [];
    return convexToPrismaShapeMany<Record<string, unknown>>(
      docs,
      PAYMENT_TS_FIELDS,
    );
  },

  async create(args: { data: Record<string, unknown> }) {
    requireConvex();
    const d = args.data;
    const convexId = await convexMutation<string>(
      "quotations/mutations:recordPayment",
      {
        quotationId: d.quotationId as string,
        amount: d.amount as number,
        currency: d.currency as string | undefined,
        method: d.method as string | undefined,
        stripePaymentIntentId: d.stripePaymentIntentId as string | undefined,
        reference: d.reference as string | undefined,
        manualNotes: d.manualNotes as string | undefined,
        recordedBy: d.recordedBy as string | undefined,
      },
    );
    return { ...d, id: d.id || convexId || "" };
  },
};

// ─── Deals ──────────────────────────────────────────────────────────────────

export const dealsAdapter = {
  async findMany(args: {
    where?: Record<string, unknown>;
    skip?: number;
    take?: number;
  }) {
    requireConvex();
    const filters = args.where || {};
    const docs =
      (await convexQuery<ConvexDoc[]>("quotations/queries:getDeals", {
        userId: filters.userId as string,
        stage: filters.stage as string | undefined,
      })) || [];
    const shaped = convexToPrismaShapeMany<Record<string, unknown>>(
      docs,
      DEAL_TS_FIELDS,
    );
    return applyPagination(shaped, args.skip, args.take);
  },

  async findUnique(args: { where: { id: string } }) {
    requireConvex();
    const docs = await this.findMany({});
    return (
      docs.find((d: Record<string, unknown>) => d.id === args.where.id) || null
    );
  },

  async count(args?: { where?: Record<string, unknown> }) {
    requireConvex();
    const docs = await this.findMany({ where: args?.where });
    return docs.length;
  },
};

// ─── Quotation Recurring Templates (Prisma passthrough) ───────────────────

export const quotationRecurringTemplatesAdapter = {
  async create(args: {
    data: Record<string, unknown>;
    include?: Record<string, unknown>;
  }) {
    return prisma.quotation_recurring_templates.create(args as never);
  },

  async findFirst(args: {
    where?: Record<string, unknown>;
    include?: Record<string, unknown>;
  }) {
    return prisma.quotation_recurring_templates.findFirst(args as never);
  },

  async findUnique(args: {
    where: Record<string, unknown>;
    include?: Record<string, unknown>;
  }) {
    return prisma.quotation_recurring_templates.findUnique(args as never);
  },

  async findMany(args: {
    where?: Record<string, unknown>;
    include?: Record<string, unknown>;
    orderBy?: Record<string, unknown>;
    skip?: number;
    take?: number;
    select?: Record<string, unknown>;
  }) {
    return prisma.quotation_recurring_templates.findMany(args as never);
  },

  async update(args: {
    where: Record<string, unknown>;
    data: Record<string, unknown>;
    include?: Record<string, unknown>;
  }) {
    return prisma.quotation_recurring_templates.update(args as never);
  },

  async count(args?: { where?: Record<string, unknown> }) {
    return prisma.quotation_recurring_templates.count(args as never);
  },
};

// ─── Quotation Settings (Prisma passthrough) ──────────────────────────────

export const quotationSettingsAdapter = {
  async findUnique(args: { where: { userId: string } }) {
    return prisma.quotation_settings.findUnique(args as never);
  },

  async create(args: { data: Record<string, unknown> }) {
    return prisma.quotation_settings.create(args as never);
  },

  async update(args: {
    where: Record<string, unknown>;
    data: Record<string, unknown>;
  }) {
    return prisma.quotation_settings.update(args as never);
  },
};

// ─── Quotation Reminders (Prisma passthrough) ─────────────────────────────

export const quotationRemindersAdapter = {
  async create(args: { data: Record<string, unknown> }) {
    return prisma.quotation_reminders.create(args as never);
  },

  async findUnique(args: { where: Record<string, unknown> }) {
    return prisma.quotation_reminders.findUnique(args as never);
  },
};
