import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';

import { withAuth, withPermission } from '@/lib/api/helpers';
import { errorResponse } from '@/lib/errors';
import { parseOperationalFilters } from '@/lib/services/reports/operational-filters';
import {
  getOperationalKpis,
  getUtilisationHeatmap,
  getStatusMixOverTime,
  getTenancyChurn,
  getTenureDistribution,
  getSigningBoxPlot,
  getOccupancyByArea,
  getDocumentsInPipeline,
  getTenanciesEndingSoon,
  getVacantBerths,
  getStuckSigning,
  getHighestValueVacant,
  getOperationalAreaOptions,
  operationalHasData,
} from '@/lib/services/reports/operational.service';

const querySchema = z.object({
  from: z.string().datetime().optional(),
  to: z.string().datetime().optional(),
});

function resolveRange(from?: string, to?: string): { from: Date; to: Date } {
  const now = new Date();
  const defaultFrom = new Date(now);
  defaultFrom.setDate(defaultFrom.getDate() - 30);
  return {
    from: from ? new Date(from) : defaultFrom,
    to: to ? new Date(to) : now,
  };
}

export const GET = withAuth(
  withPermission('reports', 'view_dashboard', async (req: NextRequest, ctx) => {
    try {
      const params = req.nextUrl.searchParams;
      const { from, to } = querySchema.parse({
        from: params.get('from') ?? undefined,
        to: params.get('to') ?? undefined,
      });
      const range = resolveRange(from, to);
      const filters = parseOperationalFilters(params);

      const [
        kpis,
        utilisationHeatmap,
        statusMix,
        tenancyChurn,
        tenureDistribution,
        signingBoxPlot,
        occupancyByArea,
        docsInPipeline,
        endingSoon,
        vacantBerths,
        stuckSigning,
        highestValueVacant,
        areaOptions,
        hasData,
      ] = await Promise.all([
        getOperationalKpis(ctx.portId, range, filters),
        getUtilisationHeatmap(ctx.portId, 24, filters),
        getStatusMixOverTime(ctx.portId),
        getTenancyChurn(ctx.portId),
        getTenureDistribution(ctx.portId),
        getSigningBoxPlot(ctx.portId),
        getOccupancyByArea(ctx.portId, filters),
        getDocumentsInPipeline(ctx.portId),
        getTenanciesEndingSoon(ctx.portId),
        getVacantBerths(ctx.portId, 60, filters),
        getStuckSigning(ctx.portId),
        getHighestValueVacant(ctx.portId, 10, filters),
        getOperationalAreaOptions(ctx.portId),
        operationalHasData(ctx.portId),
      ]);

      return NextResponse.json({
        data: {
          kpis,
          utilisationHeatmap,
          statusMix,
          tenancyChurn,
          tenureDistribution,
          signingBoxPlot,
          occupancyByArea,
          docsInPipeline,
          endingSoon,
          vacantBerths,
          stuckSigning,
          highestValueVacant,
          areaOptions,
          hasData,
          range: {
            from: range.from.toISOString(),
            to: range.to.toISOString(),
          },
        },
      });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);
