import { createRoute } from "../../../../modules/api-utils/createRoute";
import { opportunities } from "../../../../managers/opportunities";
import { apiResponse } from "../../../../modules/api-utils/apiResponse";
import { ContentfulStatusCode } from "hono/utils/http-status";
import { authMiddleware } from "../../../middleware/authorization";
import { processObjectValuePerms } from "../../../../modules/permission-utils/processObjectPermissions";
import GenericError from "../../../../Errors/GenericError";
import { generatedQuotes } from "../../../../managers/generatedQuotes";

/* GET /v1/sales/opportunities/opportunity/:identifier?include=notes,contacts,products,quotes */
export default createRoute(
  "get",
  ["/opportunities/opportunity/:identifier"],
  async (c) => {
    const identifier = c.req.param("identifier");
    const includeParam = c.req.query("include") ?? "";
    const includes = new Set(
      includeParam
        .split(",")
        .map((s) => s.trim().toLowerCase())
        .filter(Boolean)
    );

    // Fetch the opportunity from local DB
    const item = await opportunities.fetchItem(identifier);

    console.log("Fetched opportunity:", item ? item.toJson() : null);

    // Fetch sub-resources as requested
    const subResourcePromises: Record<string, Promise<any>> = {
      _site: item.fetchSite(),
    };
    if (includes.has("notes")) {
      subResourcePromises.notes = item.fetchNotes();
    }
    if (includes.has("contacts")) {
      subResourcePromises.contacts = item.fetchContacts();
    }
    if (includes.has("products")) {
      subResourcePromises.products = item
        .fetchProducts()
        .then((products) => {
          const json = products.map((p) => p.toJson());
          console.log(`[PRODUCTS_DEBUG] cwOpportunityId=${item.cwOpportunityId} count=${json.length}`, JSON.stringify(json, null, 2));
          return json;
        });
    }
    if (includes.has("quotes")) {
      const includeRegenData = c.req.query("includeRegenData") === "true";
      const includeRegenParams = c.req.query("includeRegenParams") === "true";
      subResourcePromises.quotes = generatedQuotes
        .fetchByOpportunity(item.id)
        .then((quotes) =>
          quotes.map((q) => q.toJson({ includeRegenData, includeRegenParams }))
        );
    }

    const keys = Object.keys(subResourcePromises);
    const results = await Promise.all(keys.map((k) => subResourcePromises[k]));

    // Apply toJson after site is hydrated (side-effect from fetchSite)
    const gatedData = await processObjectValuePerms(
      item.toJson(),
      "obj.opportunity",
      c.get("user")
    );

    const originalOpportunityNoteText = (gatedData as any).notes;

    // Attach sub-resources (skip the internal _site key)
    keys.forEach((k, i) => {
      if (k !== "_site") {
        (gatedData as any)[k] = results[i];
      }
    });

    if (includes.has("notes")) {
      (gatedData as any).opportunityNoteText =
        typeof originalOpportunityNoteText === "string"
          ? originalOpportunityNoteText
          : null;
    }

    const response = apiResponse.successful(
      "Opportunity fetched successfully!",
      gatedData
    );
    return c.json(response, response.status as ContentfulStatusCode);
  },
  authMiddleware({ permissions: ["sales.opportunity.fetch"] })
);
