import { db } from "@/app/db/db";
import { NextRequest, NextResponse } from "next/server";
import { portfolio, portfolioUsers} from "@/app/db/schema/portfolio";
import { user } from "@/app/db/schema/users";
import {
  recommendation,
  recommendationMaterials,
  planRecommendations,
  plan,
  scenario,
} from "@/app/db/schema/recommendations";
import {
  propertyTargets,
  propertyDetailsEpc,
  property,
} from "@/app/db/schema/property";
import { eq, inArray, Name } from "drizzle-orm";
import { z } from "zod";

const UpdateBodySchema = z.object({
  name: z.optional(z.string()),
  budget: z.optional(z.number()),
  goal: z.optional(z.string()),
  status: z.optional(z.string()),
});

export async function PUT(request: NextRequest, props: { params: Promise<{ portfolioId: string }> }) {
  const params = await props.params;
  const body = await request.json();
  let validatedBody;

  try {
    validatedBody = UpdateBodySchema.parse(body);
  } catch (error) {
    console.error("Invalid input: ", error);
    return new NextResponse(JSON.stringify({ msg: "Invalid input" }), {
      status: 400,
    });
  }

  const portfolioId = params.portfolioId;
  const name = validatedBody.name;
  const budget = validatedBody.budget;
  const goal = validatedBody.goal;
  const status = validatedBody.status;


  await db
    .update(portfolio)
    .set(body)
    .where(eq(portfolio.id, BigInt(portfolioId)));

  // Returning a successful response
  return new NextResponse(JSON.stringify({}), {
    status: 200,
  });
}

export async function DELETE(request: NextRequest, props: { params: Promise<{ portfolioId: string }> }) {
  const params = await props.params;
  try {
    const portfolioId = params.portfolioId;

    // 1) Fetch the portfolio ids
    // 2) Fetch the recommendation ids
    // 3) Delete all entries from RecommendationMaterials for these recommendationsP
    // 4) Delete all entries from PlanRecommendations that reference plans in the portfolio
    // 5) Delete all Plans associated with the portfolio
    // 6) Delete all Scenarios associated with the portfolio
    // 7) Delete all Recommendations associated with the properties
    // 8) Delete PropertyTargetsModel, PropertyDetailsEpcModel, and PropertyModel
    // 9) Delete portfolioUsers
    // 10) Then, we finally delete the portfolio!!!

    // Step 1) Fetch the property ids for the portfolio
    const propertyIdsResponse = await db.query.property.findMany({
      columns: { id: true },
      where: eq(property.portfolioId, BigInt(portfolioId)),
    });
    const propertyIds = propertyIdsResponse.map((property) => property.id);

    // Step 2) Fetch the recommendation ids - filter the recommendation table, where propertyId is in the propertyIds
    // if there are no prpoperty Ids, we make recommendationIds an empty array
    let recommendationIds: bigint[] = [];
    if (propertyIds.length) {
      const recommendations = await db.query.recommendation.findMany({
        columns: { id: true },
        where: inArray(recommendation.propertyId, propertyIds),
      });
      recommendationIds = recommendations.map(
        (recommendation) => recommendation.id
      );
    }

    // Step 3) Delete all entries from RecommendationMaterials for these recommendations
    if (recommendationIds.length) {
      await db
        .delete(recommendationMaterials)
        .where(
          inArray(recommendationMaterials.recommendationId, recommendationIds)
        );
    }

    // Step 4) Delete all entries from PlanRecommendations that reference plans in the portfolio
    // Get the plan ids
    const plans = await db.query.plan.findMany({
      columns: { id: true },
      where: eq(plan.portfolioId, BigInt(portfolioId)),
    });
    const planIds = plans.map((plan) => plan.id);

    if (planIds.length) {
      await db
        .delete(planRecommendations)
        .where(inArray(planRecommendations.planId, planIds));
    }

    // Step 5) Delete all Plans associated with the portfolio
    await db.delete(plan).where(eq(plan.portfolioId, BigInt(portfolioId)));

    // Step 6) Delete all Scenarios associated with the portfolio
    await db
      .delete(scenario)
      .where(eq(scenario.portfolioId, BigInt(portfolioId)));

    // Step 7) Delete all Recommendations associated with the properties
    if (propertyIds.length) {
      await db
        .delete(recommendation)
        .where(inArray(recommendation.propertyId, propertyIds));
    }

    // Step 8) Delete PropertyTargets, PropertyDetailsEpc, and Property
    await db
      .delete(propertyTargets)
      .where(eq(propertyTargets.portfolioId, BigInt(portfolioId)));

    await db
      .delete(propertyDetailsEpc)
      .where(eq(propertyDetailsEpc.portfolioId, BigInt(portfolioId)));

    await db
      .delete(property)
      .where(eq(property.portfolioId, BigInt(portfolioId)));

    await db
      .delete(portfolioUsers)
      .where(eq(portfolioUsers.portfolioId, BigInt(portfolioId)));

    await db.delete(portfolio).where(eq(portfolio.id, BigInt(portfolioId)));

    // Return success response
    return new NextResponse(
      JSON.stringify({ message: "Portfolio successfully deleted" }),
      { status: 200 }
    );
  } catch (error) {
    console.error("Error deleting portfolio:", error);
    return new NextResponse(
      JSON.stringify({ error: "Your API has Failed to delete the portfolio" }),
      { status: 500 }
    );
  }
}


