/**
 * Real Estate Broker Detail API
 * GET    - Broker detail with today's schedule
 * PUT    - Update broker profile
 * DELETE - Deactivate broker (soft delete)
 */

import { NextRequest } from "next/server";
import { auth } from "@/lib/auth";
import { prisma } from "@/lib/db";
import { getAuthenticatedEmail } from "@/lib/utils/auth-helpers.util";
import { getEffectiveOwnerId } from "@/lib/utils/organization-data";
import { logger } from "@/lib/logger";
import { ApiResponses } from "@/lib/utils/api-response.util";
import { withRateLimit, rateLimiters } from "@/lib/rate-limiter";
import { getErrorMessage } from "@/lib/errors";
import { getDataSource } from "@/lib/data-source";
import { withCSRF } from "@/lib/csrf";

export const dynamic = "force-dynamic";

/**
 * GET /api/real-estate/brokers/[id]
 * Broker detail with today's schedule (viewings count, next viewing).
 */
export const GET = withRateLimit(
  async (
    request: NextRequest,
    { params }: { params: Promise<{ id: string }> },
  ) => {
    try {
      const { id } = await params;

      const userEmail = await getAuthenticatedEmail(request, auth);
      if (!userEmail) {
        return ApiResponses.unauthorized();
      }

      const user = await prisma.users.findUnique({
        where: { email: userEmail },
        select: { id: true },
      });
      if (!user) {
        return ApiResponses.notFound("User not found");
      }

      const effectiveUserId = await getEffectiveOwnerId(user.id);

      // ── Convex data-source branch ──────────────────────────────────
      if (getDataSource("real_estate") === "convex") {
        try {
          const { convexQuery } = await import("@/lib/convex-client");

          const broker = await convexQuery(
            "real_estate/queries:getBrokerById",
            { id: id as any },
          );

          if (broker) {
            // Get today's viewings from Convex
            const todayStartMs = new Date(
              new Date().setHours(0, 0, 0, 0),
            ).getTime();
            const todayEndMs = new Date(
              new Date().setHours(23, 59, 59, 999),
            ).getTime();
            const availData = await convexQuery(
              "real_estate/queries:getBrokerAvailability",
              {
                brokerId: id,
                startDate: todayStartMs,
                endDate: todayEndMs,
              },
            );
            const todayViewings = (availData as any)?.viewings || [];
            const now = new Date();
            const currentTime = `${now.getHours().toString().padStart(2, "0")}:${now.getMinutes().toString().padStart(2, "0")}`;
            const nextViewing =
              todayViewings.find(
                (v: any) =>
                  v.viewingTime >= currentTime && v.status !== "VIEW_COMPLETED",
              ) || null;

            return ApiResponses.success({
              broker,
              todaySchedule: {
                viewingsCount: todayViewings.length,
                viewings: todayViewings,
                nextViewing,
              },
            });
          }
        } catch (error) {
          console.error(
            "[Convex fallback] real_estate brokers/[id] GET:",
            error,
          );
          // Fall through to Prisma
        }
      }

      const broker = await prisma.broker.findFirst({
        where: {
          id,
          userId: effectiveUserId,
        },
        include: {
          availability: {
            where: {
              date: {
                gte: new Date(new Date().setHours(0, 0, 0, 0)),
                lt: new Date(new Date().setHours(23, 59, 59, 999)),
              },
            },
          },
        },
      });

      if (!broker) {
        return ApiResponses.notFound("Broker not found");
      }

      // Get today's viewings
      const todayStart = new Date();
      todayStart.setHours(0, 0, 0, 0);
      const todayEnd = new Date();
      todayEnd.setHours(23, 59, 59, 999);

      const todayViewings = await prisma.propertyViewing.findMany({
        where: {
          brokerId: id,
          viewingDate: { gte: todayStart, lte: todayEnd },
          status: { notIn: ["CANCELLED", "NO_SHOW"] },
        },
        orderBy: { viewingTime: "asc" },
        select: {
          id: true,
          viewingTime: true,
          status: true,
          clientName: true,
          property: {
            select: { titleEn: true, titleAr: true },
          },
        },
      });

      // Find next upcoming viewing
      const now = new Date();
      const currentTime = `${now.getHours().toString().padStart(2, "0")}:${now.getMinutes().toString().padStart(2, "0")}`;
      const nextViewing =
        todayViewings.find(
          (v) => v.viewingTime >= currentTime && v.status !== "VIEW_COMPLETED",
        ) || null;

      return ApiResponses.success({
        broker,
        todaySchedule: {
          viewingsCount: todayViewings.length,
          viewings: todayViewings,
          nextViewing,
        },
      });
    } catch (error) {
      logger.error("[Broker Detail API] GET error", {
        error: getErrorMessage(error),
      });
      return ApiResponses.serverError("Failed to fetch broker details");
    }
  },
  rateLimiters.authGeneral,
);

/**
 * PUT /api/real-estate/brokers/[id]
 * Update broker profile. If setting isActive=false, check for pending viewings.
 */
export const PUT = withRateLimit(
  withCSRF(
    async (
      request: NextRequest,
      { params }: { params: Promise<{ id: string }> },
    ) => {
      try {
        const { id } = await params;

        const userEmail = await getAuthenticatedEmail(request, auth);
        if (!userEmail) {
          return ApiResponses.unauthorized();
        }

        const user = await prisma.users.findUnique({
          where: { email: userEmail },
          select: { id: true },
        });
        if (!user) {
          return ApiResponses.notFound("User not found");
        }

        const effectiveUserId = await getEffectiveOwnerId(user.id);

        const body = await request.json();

        // ── Convex data-source branch ──────────────────────────────────
        if (getDataSource("real_estate") === "convex") {
          try {
            const { convexMutation } = await import("@/lib/convex-client");

            const updateArgs: Record<string, unknown> = { id: id as any };
            const allowedFields = [
              "nameEn",
              "nameAr",
              "phone",
              "email",
              "whatsappNumber",
              "photoUrl",
              "bioEn",
              "bioAr",
              "licenseNumber",
              "languages",
              "areaSpecializations",
              "typeSpecializations",
              "workingDays",
              "workStartTime",
              "workEndTime",
              "maxViewingsPerDay",
              "isActive",
            ];
            for (const field of allowedFields) {
              if (body[field] !== undefined) {
                updateArgs[field] =
                  typeof body[field] === "string"
                    ? body[field].trim()
                    : body[field];
              }
            }

            const brokerId = await convexMutation(
              "real_estate/mutations:updateBroker",
              updateArgs,
            );

            if (brokerId) {
              logger.info("[Broker Detail API] Broker updated via Convex", {
                brokerId: id,
              });
              return ApiResponses.success({ broker: { id: brokerId } });
            }
          } catch (error) {
            console.error(
              "[Convex fallback] real_estate brokers/[id] PUT:",
              error,
            );
            // Fall through to Prisma
          }
        }

        // Verify broker belongs to this org
        const existing = await prisma.broker.findFirst({
          where: { id, userId: effectiveUserId },
        });
        if (!existing) {
          return ApiResponses.notFound("Broker not found");
        }

        // If deactivating, check for pending viewings
        let pendingViewingsWarning: string | null = null;
        if (body.isActive === false && existing.isActive === true) {
          const pendingViewings = await prisma.propertyViewing.count({
            where: {
              brokerId: id,
              status: { in: ["REQUESTED", "CONFIRMED"] },
              viewingDate: { gte: new Date() },
            },
          });

          if (pendingViewings > 0) {
            pendingViewingsWarning = `This broker has ${pendingViewings} pending/confirmed viewings. They should be reassigned before deactivation.`;
          }
        }

        // Build update data -- only update provided fields
        const updateData: Record<string, unknown> = {};
        const allowedFields = [
          "nameEn",
          "nameAr",
          "phone",
          "email",
          "whatsappNumber",
          "photoUrl",
          "bioEn",
          "bioAr",
          "licenseNumber",
          "languages",
          "areaSpecializations",
          "typeSpecializations",
          "workingDays",
          "workStartTime",
          "workEndTime",
          "maxViewingsPerDay",
          "isActive",
        ];

        for (const field of allowedFields) {
          if (body[field] !== undefined) {
            updateData[field] =
              typeof body[field] === "string"
                ? body[field].trim()
                : body[field];
          }
        }

        const broker = await prisma.broker.update({
          where: { id },
          data: updateData,
        });

        logger.info("[Broker Detail API] Broker updated", { brokerId: id });

        return ApiResponses.success({
          broker,
          ...(pendingViewingsWarning
            ? { warning: pendingViewingsWarning }
            : {}),
        });
      } catch (error) {
        logger.error("[Broker Detail API] PUT error", {
          error: getErrorMessage(error),
        });
        return ApiResponses.serverError("Failed to update broker");
      }
    },
  ),
  rateLimiters.authGeneral,
);

/**
 * DELETE /api/real-estate/brokers/[id]
 * Deactivate broker (soft delete - set isActive=false).
 */
export const DELETE = withRateLimit(
  withCSRF(
    async (
      request: NextRequest,
      { params }: { params: Promise<{ id: string }> },
    ) => {
      try {
        const { id } = await params;

        const userEmail = await getAuthenticatedEmail(request, auth);
        if (!userEmail) {
          return ApiResponses.unauthorized();
        }

        const user = await prisma.users.findUnique({
          where: { email: userEmail },
          select: { id: true },
        });
        if (!user) {
          return ApiResponses.notFound("User not found");
        }

        const effectiveUserId = await getEffectiveOwnerId(user.id);

        // ── Convex data-source branch ──────────────────────────────────
        if (getDataSource("real_estate") === "convex") {
          try {
            const { convexMutation } = await import("@/lib/convex-client");

            const brokerId = await convexMutation(
              "real_estate/mutations:updateBroker",
              { id: id as any, isActive: false },
            );

            if (brokerId) {
              logger.info("[Broker Detail API] Broker deactivated via Convex", {
                brokerId: id,
              });
              return ApiResponses.success({
                broker: { id: brokerId },
                deactivated: true,
                pendingViewings: 0,
              });
            }
          } catch (error) {
            console.error(
              "[Convex fallback] real_estate brokers/[id] DELETE:",
              error,
            );
            // Fall through to Prisma
          }
        }

        const existing = await prisma.broker.findFirst({
          where: { id, userId: effectiveUserId },
        });
        if (!existing) {
          return ApiResponses.notFound("Broker not found");
        }

        // Check for pending viewings
        const pendingViewings = await prisma.propertyViewing.count({
          where: {
            brokerId: id,
            status: { in: ["REQUESTED", "CONFIRMED"] },
            viewingDate: { gte: new Date() },
          },
        });

        // Soft delete
        const broker = await prisma.broker.update({
          where: { id },
          data: { isActive: false },
        });

        logger.info("[Broker Detail API] Broker deactivated", {
          brokerId: id,
          pendingViewings,
        });

        return ApiResponses.success({
          broker,
          deactivated: true,
          pendingViewings,
          ...(pendingViewings > 0
            ? {
                warning: `${pendingViewings} pending viewings need to be reassigned.`,
              }
            : {}),
        });
      } catch (error) {
        logger.error("[Broker Detail API] DELETE error", {
          error: getErrorMessage(error),
        });
        return ApiResponses.serverError("Failed to deactivate broker");
      }
    },
  ),
  rateLimiters.authGeneral,
);
