/**
 * Real Estate Domain Adapter
 *
 * Routes property, property_viewing, and broker models
 * to Convex. These models exist ONLY in Convex (no Prisma models).
 *
 * When DS_REAL_ESTATE=prisma (default), operations throw since there
 * are no Prisma tables. When DS_REAL_ESTATE=convex, uses Convex backend.
 */

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

const DOMAIN = "real_estate" as const;
const PROPERTY_TS_FIELDS = ["createdAt", "updatedAt", "listedAt", "soldAt"];
const VIEWING_TS_FIELDS = [
  "createdAt",
  "updatedAt",
  "viewingDate",
  "confirmedAt",
  "completedAt",
  "cancelledAt",
];
const BROKER_TS_FIELDS = ["createdAt", "updatedAt"];

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

// ─── Property ───────────────────────────────────────────────────────────────

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

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

  async findFirst(args: { where?: Record<string, unknown> }) {
    requireConvex();
    const docs = await this.findMany({ where: args.where, take: 1 });
    return docs[0] || null;
  },

  async create(args: { data: Record<string, unknown> }) {
    requireConvex();
    const d = args.data;
    const convexId = await convexMutation<string>(
      "real_estate/mutations:createProperty",
      {
        userId: d.userId as string,
        organizationId: d.organizationId as string | undefined,
        titleEn: d.titleEn as string,
        titleAr: d.titleAr as string | undefined,
        descriptionEn: d.descriptionEn as string | undefined,
        descriptionAr: d.descriptionAr as string | undefined,
        propertyType: d.propertyType as string,
        listingType: d.listingType as string,
        city: d.city as string,
        district: d.district as string | undefined,
        price: d.price as number,
        currency: d.currency as string | undefined,
        bedrooms: d.bedrooms as number | undefined,
        bathrooms: d.bathrooms as number | undefined,
        builtUpArea: d.builtUpArea as number | undefined,
      },
    );
    return { ...d, id: d.id || convexId || "" };
  },

  async update(args: { where: { id: string }; data: Record<string, unknown> }) {
    requireConvex();
    const d = args.data;
    await convexMutation("real_estate/mutations:updateProperty", {
      id: args.where.id,
      titleEn: d.titleEn as string | undefined,
      titleAr: d.titleAr as string | undefined,
      descriptionEn: d.descriptionEn as string | undefined,
      status: d.status as string | undefined,
      price: d.price as number | undefined,
      bedrooms: d.bedrooms as number | undefined,
      bathrooms: d.bathrooms as number | undefined,
    });
    return this.findUnique({ where: { id: args.where.id } });
  },

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

// ─── Property Viewing ───────────────────────────────────────────────────────

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

  async create(args: { data: Record<string, unknown> }) {
    requireConvex();
    const d = args.data;
    const convexId = await convexMutation<string>(
      "real_estate/mutations:scheduleViewing",
      {
        userId: d.userId as string,
        organizationId: d.organizationId as string | undefined,
        propertyId: d.propertyId as string,
        brokerId: d.brokerId as string | undefined,
        clientName: d.clientName as string,
        clientPhone: d.clientPhone as string,
        clientEmail: d.clientEmail as string | undefined,
        viewingType: d.viewingType as string | undefined,
        viewingDate: dateToConvexTimestamp(
          d.viewingDate as Date | string | number,
        ),
        viewingTime: d.viewingTime as string,
        duration: d.duration as number | undefined,
      },
    );
    return { ...d, id: d.id || convexId || "" };
  },

  async update(args: { where: { id: string }; data: Record<string, unknown> }) {
    requireConvex();
    if (args.data.status) {
      await convexMutation("real_estate/mutations:updateViewingStatus", {
        id: args.where.id,
        status: args.data.status as string,
      });
    }
    return { ...args.data, id: args.where.id };
  },

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

// ─── Broker ─────────────────────────────────────────────────────────────────

export const brokerAdapter = {
  async findMany(args: {
    where?: Record<string, unknown>;
    skip?: number;
    take?: number;
  }) {
    requireConvex();
    const filters = args.where || {};
    const docs =
      (await convexQuery<ConvexDoc[]>("real_estate/queries:getBrokers", {
        userId: filters.userId as string,
        isActive: filters.isActive as boolean | undefined,
      })) || [];
    const shaped = convexToPrismaShapeMany<Record<string, unknown>>(
      docs,
      BROKER_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;
  },
};
