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 GenericError from "../../../Errors/GenericError";
import { z } from "zod";
import { cwMembers } from "../../../managers/cwMembers";
import { prisma } from "../../../constants";
import {
  createWorkflowActivity,
  OptimaType,
} from "../../../workflows/wf.opportunity";
import { resolveCwProbabilityId } from "../../../modules/cw-utils/opportunities/cwProbabilityCache";

const createSchema = z.object({
  name: z.string().min(1),
  expectedCloseDate: z
    .string()
    .min(1)
    .transform((v) => new Date(v).toISOString().replace(/\.\d{3}Z$/, "Z")),
  notes: z.string().optional(),
  interest: z.enum(["HOT", "WARM", "COLD"]).nullable().optional(),
  rating: z.object({ id: z.number() }).optional(),
  type: z.object({ id: z.number() }).optional(),
  stage: z.object({ id: z.number() }).optional(),
  status: z.object({ id: z.number() }).optional(),
  priority: z.object({ id: z.number() }).optional(),
  campaign: z.object({ id: z.number() }).optional(),
  primarySalesRep: z.object({ id: z.number() }),
  secondarySalesRep: z.object({ id: z.number() }).nullable().optional(),
  company: z.object({ id: z.number() }),
  contact: z.object({ id: z.number() }),
  site: z.object({ id: z.number() }).nullable().optional(),
  source: z.string().nullable().optional(),
  customerPO: z.string().nullable().optional(),
  locationId: z.number().optional(),
  businessUnitId: z.number().optional(),
});

/* POST /v1/sales/opportunities */
export default createRoute(
  "post",
  ["/opportunities"],
  async (c) => {
    const body = await c.req.json();
    const data = createSchema.parse(body);
    const { interest, ...cwCreateData } = data;

    // Resolve the CW probability reference ID for 50% (the default)
    const defaultProbabilityId = await resolveCwProbabilityId(50);

    try {
      const item = await opportunities.createItem({
        ...cwCreateData,
        ...(defaultProbabilityId != null
          ? { probability: { id: defaultProbabilityId } }
          : {}),
      });

      // Apply defaults: "HOT" interest and 50% probability if not explicitly provided.
      const effectiveInterest = interest !== undefined ? interest : "HOT";
      await prisma.opportunity.update({
        where: { uid: item.id },
        data: { interest: effectiveInterest, probability: 50 },
      });
      item.interest = effectiveInterest;
      item.probability = 50;

      // Create a workflow activity for the new opportunity
      try {
        const user = c.get("user");
        let cwMemberId: number | null = null;

        if (user.cwIdentifier) {
          const cwMember = await cwMembers.fetch(user.cwIdentifier);
          cwMemberId = cwMember.cwMemberId;
        }

        if (cwMemberId) {
          await createWorkflowActivity({
            name: `[Workflow] Opportunity created — ${item.name}`,
            opportunityCwId: item.cwOpportunityId,
            companyCwId: item.companyCwId,
            assignToCwMemberId: cwMemberId,
            notes: "Opportunity created.",
            optimaType: OptimaType.OpportunityCreated,
          });
        }
      } catch (activityErr) {
        console.error(
          "[Opportunity Create] Failed to create workflow activity:",
          activityErr
        );
        // Don't fail the opportunity creation if the activity fails
      }

      const response = apiResponse.created(
        "Opportunity created successfully!",
        item.toJson()
      );

      return c.json(response, response.status as ContentfulStatusCode);
    } catch (err) {
      const isAxios =
        err != null && typeof err === "object" && "isAxiosError" in err;

      if (isAxios) {
        const axiosErr = err as any;
        const cwStatus: number = axiosErr.response?.status ?? 502;
        const cwData = axiosErr.response?.data;
        const cwMessage: string =
          cwData?.message ?? "Failed to create the opportunity in ConnectWise";
        const cwErrors: unknown[] | undefined = Array.isArray(cwData?.errors)
          ? cwData.errors
          : undefined;

        return c.json(
          {
            status: cwStatus,
            message: cwMessage,
            error: "ConnectWiseCreateError",
            successful: false,
            errors: cwErrors,
            meta: { timestamp: Date.now() },
          },
          cwStatus as ContentfulStatusCode
        );
      }

      console.error("[Opportunity Create] DB write failed after CW create:", err);
      throw new GenericError({
        status: 500,
        name: "OpportunityCreateError",
        message: "Failed to create opportunity",
        cause: err instanceof Error ? err.message : String(err),
      });
    }
  },
  authMiddleware({ permissions: ["sales.opportunity.create"] })
);
