import { createRoute } from "../../../../modules/api-utils/createRoute";
import { unifiSites } from "../../../../managers/unifiSites";
import { apiResponse } from "../../../../modules/api-utils/apiResponse";
import { ContentfulStatusCode } from "hono/utils/http-status";
import { authMiddleware } from "../../../middleware/authorization";
import { toWlanConfUpdate } from "../../../../modules/unifi-api/unifiTypes";
import { z } from "zod";

/* PATCH /v1/unifi/site/:id/wifi/:wlanId */
export default createRoute(
  "patch",
  ["/site/:id/wifi/:wlanId"],
  async (c) => {
    const site = await unifiSites.fetch(c.req.param("id"));
    const wlanId = c.req.param("wlanId");

    const body = await c.req.json();
    const schema = z
      .object({
        name: z.string().optional(),
        passphrase: z.string().optional(),
        enabled: z.boolean().optional(),
        security: z.enum(["wpapsk", "wpaeap", "open", "osen"]).optional(),
        wpaMode: z.enum(["wpa2", "wpa3", "wpa2wpa3"]).optional(),
        wpaEnc: z.enum(["ccmp", "gcmp", "ccmp-gcmp"]).optional(),
        hideSSID: z.boolean().optional(),
        macFilterEnabled: z.boolean().optional(),
        macFilterPolicy: z.enum(["allow", "deny"]).optional(),
        isGuest: z.boolean().optional(),
        l2Isolation: z.boolean().optional(),
        fastRoamingEnabled: z.boolean().optional(),
        bssTransition: z.boolean().optional(),
        uapsdEnabled: z.boolean().optional(),
        groupRekey: z.number().optional(),
        dtimMode: z.enum(["default", "custom"]).optional(),
        dtimNg: z.number().optional(),
        dtimNa: z.number().optional(),
        minrateNgEnabled: z.boolean().optional(),
        minrateNaEnabled: z.boolean().optional(),
        radiusDasEnabled: z.boolean().optional(),
        radiusMacAuthEnabled: z.boolean().optional(),
        pmfMode: z.enum(["disabled", "optional", "required"]).optional(),
        band: z.enum(["both", "2g", "5g"]).optional(),
        usergroupId: z.string().optional(),
        proxyArp: z.boolean().optional(),
        mcastenhanceEnabled: z.boolean().optional(),
        macFilterList: z.array(z.string()).optional(),
        no2ghzOui: z.boolean().optional(),
        apGroupIds: z.array(z.string()).optional(),
        apGroupMode: z.enum(["all", "groups", "devices"]).optional(),
        deviceMacs: z.array(z.string()).optional(),
      })
      .strict();

    const parsed = schema.parse(body);

    // If deviceMacs is provided, manage the devices_ap_group:
    // - If already in devices mode with a for_wlanconf group, update that group
    // - Otherwise create a new for_wlanconf group and switch to devices mode
    if (parsed.deviceMacs && parsed.deviceMacs.length > 0) {
      const wlans = await unifiSites.getWlanConf(site.siteId);
      const currentWlan = wlans.find((w) => w.id === wlanId);

      let existingGroupId: string | undefined;
      if (
        currentWlan?.apGroupMode === "devices" &&
        currentWlan.apGroupIds.length > 0
      ) {
        // Check if the current group is a for_wlanconf group we can update
        const apGroups = await unifiSites.getApGroups(site.siteId);
        const currentGroup = apGroups.find(
          (g) => g.id === currentWlan.apGroupIds[0] && g.forWlanconf,
        );
        if (currentGroup) existingGroupId = currentGroup.id;
      }

      if (existingGroupId) {
        // Update the existing for_wlanconf group's device list
        await unifiSites.updateApGroup(
          site.siteId,
          existingGroupId,
          parsed.deviceMacs,
        );
        parsed.apGroupMode = "devices";
        parsed.apGroupIds = [existingGroupId];
      } else {
        // Create a new for_wlanconf group
        const apGroup = await unifiSites.createApGroup(
          site.siteId,
          "devices_ap_group",
          parsed.deviceMacs,
          true, // for_wlanconf must be true for devices mode
        );
        parsed.apGroupMode = "devices";
        parsed.apGroupIds = [apGroup.id];
      }
    }

    // Remove deviceMacs before converting — it's not a UniFi field
    const { deviceMacs: _, ...updateInput } = parsed;
    const updates = toWlanConfUpdate(updateInput);

    const result = await unifiSites.updateWlanConf(
      site.siteId,
      wlanId,
      updates,
    );
    const response = apiResponse.successful(
      "UniFi WiFi Network Updated Successfully!",
      result,
    );
    return c.json(response, response.status as ContentfulStatusCode);
  },
  authMiddleware({
    permissions: ["unifi.access", "unifi.site.wifi", "unifi.site.wifi.update"],
  }),
);
