/**
 * Real Estate Analytics Dashboard API
 * GET - Comprehensive dashboard analytics
 */

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";
const PropertyStatus = {
  COMING_SOON: "COMING_SOON",
  AVAILABLE: "AVAILABLE",
  UNDER_OFFER: "UNDER_OFFER",
  SOLD: "SOLD",
  RENTED: "RENTED",
  OFF_MARKET: "OFF_MARKET",
  EXPIRED: "EXPIRED",
} as const;
type PropertyStatus = (typeof PropertyStatus)[keyof typeof PropertyStatus];

const ViewingStatus = {
  REQUESTED: "REQUESTED",
  CONFIRMED: "CONFIRMED",
  IN_PROGRESS: "IN_PROGRESS",
  VIEW_COMPLETED: "VIEW_COMPLETED",
  CANCELLED: "CANCELLED",
  NO_SHOW: "NO_SHOW",
  RESCHEDULED: "RESCHEDULED",
} as const;
type ViewingStatus = (typeof ViewingStatus)[keyof typeof ViewingStatus];

const TransactionStage = {
  INQUIRY: "INQUIRY",
  QUALIFIED: "QUALIFIED",
  VIEWING_SCHEDULED: "VIEWING_SCHEDULED",
  VIEWING_COMPLETED: "VIEWING_COMPLETED",
  INTERESTED: "INTERESTED",
  OFFER_MADE: "OFFER_MADE",
  NEGOTIATION: "NEGOTIATION",
  OFFER_ACCEPTED: "OFFER_ACCEPTED",
  DEPOSIT_PAID: "DEPOSIT_PAID",
  CONTRACT_SIGNED: "CONTRACT_SIGNED",
  PAYMENT_PROCESSING: "PAYMENT_PROCESSING",
  TX_COMPLETED: "TX_COMPLETED",
  LOST: "LOST",
} as const;
type TransactionStage =
  (typeof TransactionStage)[keyof typeof TransactionStage];

export const dynamic = "force-dynamic";

/**
 * GET /api/real-estate/analytics
 * Dashboard analytics including:
 * - Property counts by status
 * - Viewing counts by status (this month)
 * - Transaction pipeline value by stage
 * - Top brokers by viewings
 * - Recent activity (last 10 viewings/transactions)
 * - Conversion funnel: listings -> viewings -> offers -> closed
 */
export const GET = withRateLimit(async (request: NextRequest) => {
  try {
    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 analytics = await convexQuery(
          "real_estate/queries:getRealEstateAnalytics",
          { userId: effectiveUserId },
        );

        if (analytics) {
          return ApiResponses.success(analytics);
        }
      } catch (error) {
        console.error("[Convex fallback] real_estate analytics:", error);
        // Fall through to Prisma
      }
    }

    // Date ranges
    const now = new Date();
    const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
    const monthEnd = new Date(
      now.getFullYear(),
      now.getMonth() + 1,
      0,
      23,
      59,
      59,
      999,
    );

    // --- Property counts by status ---
    const propertyStatuses: PropertyStatus[] = [
      "COMING_SOON",
      "AVAILABLE",
      "UNDER_OFFER",
      "SOLD",
      "RENTED",
      "OFF_MARKET",
      "EXPIRED",
    ];
    const propertyCounts: Record<string, number> = {};
    let totalProperties = 0;

    const propertyCountResults = await Promise.all(
      propertyStatuses.map((status) =>
        prisma.property.count({
          where: { userId: effectiveUserId, status },
        }),
      ),
    );
    propertyStatuses.forEach((status, i) => {
      propertyCounts[status] = propertyCountResults[i];
      totalProperties += propertyCountResults[i];
    });

    // --- Viewing counts by status (this month) ---
    const viewingStatuses: ViewingStatus[] = [
      "REQUESTED",
      "CONFIRMED",
      "IN_PROGRESS",
      "VIEW_COMPLETED",
      "CANCELLED",
      "NO_SHOW",
      "RESCHEDULED",
    ];
    const viewingCounts: Record<string, number> = {};
    let totalViewingsThisMonth = 0;

    const viewingCountResults = await Promise.all(
      viewingStatuses.map((status) =>
        prisma.propertyViewing.count({
          where: {
            userId: effectiveUserId,
            status,
            viewingDate: { gte: monthStart, lte: monthEnd },
          },
        }),
      ),
    );
    viewingStatuses.forEach((status, i) => {
      viewingCounts[status] = viewingCountResults[i];
      totalViewingsThisMonth += viewingCountResults[i];
    });

    // --- Transaction pipeline by stage ---
    const txStages: TransactionStage[] = [
      "INQUIRY",
      "QUALIFIED",
      "VIEWING_SCHEDULED",
      "VIEWING_COMPLETED",
      "INTERESTED",
      "OFFER_MADE",
      "NEGOTIATION",
      "OFFER_ACCEPTED",
      "DEPOSIT_PAID",
      "CONTRACT_SIGNED",
      "PAYMENT_PROCESSING",
      "TX_COMPLETED",
      "LOST",
    ];

    const pipelineData: Array<{
      stage: string;
      count: number;
      totalValue: number;
    }> = [];
    let totalPipelineValue = 0;

    const txResults = await Promise.all(
      txStages.map(async (stage) => {
        const [count, aggregation] = await Promise.all([
          prisma.realEstateTransaction.count({
            where: { userId: effectiveUserId, stage },
          }),
          prisma.realEstateTransaction.aggregate({
            where: { userId: effectiveUserId, stage },
            _sum: { agreedAmount: true, offerAmount: true },
          }),
        ]);
        const value =
          (aggregation._sum.agreedAmount || 0) +
          (aggregation._sum.agreedAmount
            ? 0
            : aggregation._sum.offerAmount || 0);
        return { stage, count, totalValue: value };
      }),
    );
    for (const result of txResults) {
      pipelineData.push(result);
      if (result.stage !== "LOST" && result.stage !== "TX_COMPLETED") {
        totalPipelineValue += result.totalValue;
      }
    }

    // --- Top brokers by viewings this month ---
    const activeBrokers = await prisma.broker.findMany({
      where: { userId: effectiveUserId, isActive: true },
      select: {
        id: true,
        nameEn: true,
        nameAr: true,
        totalViewings: true,
        totalClosings: true,
      },
    });

    const topBrokers = await Promise.all(
      activeBrokers.map(async (broker) => {
        const monthViewings = await prisma.propertyViewing.count({
          where: {
            brokerId: broker.id,
            viewingDate: { gte: monthStart, lte: monthEnd },
          },
        });
        return {
          ...broker,
          viewingsThisMonth: monthViewings,
        };
      }),
    );
    topBrokers.sort((a, b) => b.viewingsThisMonth - a.viewingsThisMonth);

    // --- Recent activity ---
    const [recentViewings, recentTransactions] = await Promise.all([
      prisma.propertyViewing.findMany({
        where: { userId: effectiveUserId },
        orderBy: { updatedAt: "desc" },
        take: 10,
        select: {
          id: true,
          clientName: true,
          viewingDate: true,
          viewingTime: true,
          status: true,
          createdAt: true,
          property: { select: { titleEn: true } },
          broker: { select: { nameEn: true } },
        },
      }),
      prisma.realEstateTransaction.findMany({
        where: { userId: effectiveUserId },
        orderBy: { updatedAt: "desc" },
        take: 10,
        select: {
          id: true,
          clientName: true,
          stage: true,
          offerAmount: true,
          agreedAmount: true,
          currency: true,
          updatedAt: true,
          property: { select: { titleEn: true } },
        },
      }),
    ]);

    // --- Conversion funnel ---
    const [totalListings, totalWithViewings, totalWithOffers, totalClosed] =
      await Promise.all([
        prisma.property.count({
          where: { userId: effectiveUserId },
        }),
        prisma.property.count({
          where: {
            userId: effectiveUserId,
            viewings: { some: {} },
          },
        }),
        prisma.realEstateTransaction.count({
          where: {
            userId: effectiveUserId,
            stage: {
              in: [
                "OFFER_MADE",
                "NEGOTIATION",
                "OFFER_ACCEPTED",
                "DEPOSIT_PAID",
                "CONTRACT_SIGNED",
                "PAYMENT_PROCESSING",
                "TX_COMPLETED",
              ],
            },
          },
        }),
        prisma.realEstateTransaction.count({
          where: {
            userId: effectiveUserId,
            stage: "TX_COMPLETED",
          },
        }),
      ]);

    const conversionFunnel = {
      listings: totalListings,
      viewings: totalWithViewings,
      offers: totalWithOffers,
      closed: totalClosed,
      listingToViewingRate:
        totalListings > 0
          ? Math.round((totalWithViewings / totalListings) * 100)
          : 0,
      viewingToOfferRate:
        totalWithViewings > 0
          ? Math.round((totalWithOffers / totalWithViewings) * 100)
          : 0,
      offerToCloseRate:
        totalWithOffers > 0
          ? Math.round((totalClosed / totalWithOffers) * 100)
          : 0,
      overallConversionRate:
        totalListings > 0 ? Math.round((totalClosed / totalListings) * 100) : 0,
    };

    return ApiResponses.success({
      properties: {
        byStatus: propertyCounts,
        total: totalProperties,
      },
      viewings: {
        byStatus: viewingCounts,
        totalThisMonth: totalViewingsThisMonth,
        period: {
          start: monthStart.toISOString(),
          end: monthEnd.toISOString(),
        },
      },
      pipeline: {
        byStage: pipelineData,
        totalActivePipelineValue: totalPipelineValue,
      },
      topBrokers: topBrokers.slice(0, 10),
      recentActivity: {
        viewings: recentViewings,
        transactions: recentTransactions,
      },
      conversionFunnel,
    });
  } catch (error) {
    logger.error("[Analytics API] GET error", {
      error: getErrorMessage(error),
    });
    return ApiResponses.serverError("Failed to fetch analytics");
  }
}, rateLimiters.authGeneral);
