import { createBoxState, createGatewayState } from "../sim/model.mjs";
import { createPatchPanelState, createWiringConfig } from "./model.mjs";

export const MVP_BOX_IDS = Object.freeze(["boxsim_alpha", "boxsim_beta"]);
export const MVP_GATEWAY_IDS = Object.freeze(["gwsimu_east", "gwsimu_west"]);
export const M3_BOX_IDS = Object.freeze(["boxsimu_1", "boxsimu_2"]);
export const M3_GATEWAY_IDS = Object.freeze(["gwsimu_1", "gwsimu_2"]);
export const M3_BOX_RESOURCES = Object.freeze(["res_boxsimu_1", "res_boxsimu_2"]);

function createGatewaySessionIds(gatewayIds) {
  return gatewayIds.map((gatewayId) => `gws_${gatewayId}`);
}

export function createMvpTopology({ now = "2026-01-01T00:00:00.000Z" } = {}) {
  const gatewaySessionIds = createGatewaySessionIds(MVP_GATEWAY_IDS);
  const boxes = MVP_BOX_IDS.map((boxId, index) =>
    createBoxState({
      boxId,
      gatewaySessionId: gatewaySessionIds[index],
      ports: ["uart0", "eth0", "gpio0"],
      includePortDefinitions: false,
      now
    })
  );

  const gateways = MVP_GATEWAY_IDS.map((gatewayId, index) =>
    createGatewayState({
      gatewayId,
      endpoint: `http://127.0.0.1:${7101 + index}`,
      boxes: [boxes[index].resource.resourceId],
      now
    })
  );

  const wiringConfig = createWiringConfig({
    gatewaySessionId: gatewaySessionIds[0],
    connections: [
      {
        from: {
          resourceId: boxes[0].resource.resourceId,
          port: "uart0"
        },
        to: {
          resourceId: boxes[1].resource.resourceId,
          port: "uart0"
        },
        mode: "exclusive"
      },
      {
        from: {
          resourceId: boxes[0].resource.resourceId,
          port: "gpio0"
        },
        to: {
          resourceId: boxes[1].resource.resourceId,
          port: "gpio0"
        },
        mode: "monitor"
      }
    ],
    now
  });

  const patchPanel = createPatchPanelState({
    gatewaySessionId: gatewaySessionIds[0],
    wiringConfig,
    now
  });

  return {
    topologyId: "top_mvp_l2_l3_sim_patch",
    projectId: "prj_mvp_topology",
    environment: "dev",
    services: {
      boxes,
      gateways,
      patchPanel
    },
    wiringConfig,
    constraints: {
      patchPanelIsOnlyCrossDeviceChannel: true,
      boxSimuLocalLoopbackForCrossDeviceSync: false
    },
    dryRunHints: {
      cliTarget: "fixtures/mvp-topology/topology.json",
      expectedServices: ["hwlab-box-simu", "hwlab-gateway-simu", "hwlab-patch-panel"]
    }
  };
}

export function createM3Topology({ now = "2026-05-21T00:00:00.000Z" } = {}) {
  const projectId = "prj_m3_hardware_loop";
  const gatewaySessionIds = createGatewaySessionIds(M3_GATEWAY_IDS);
  const boxes = M3_BOX_IDS.map((boxId, index) =>
    withProjectId(createBoxState({
      boxId,
      gatewaySessionId: gatewaySessionIds[index],
      ports: ["DO1", "DI1"],
      now
    }), projectId)
  );

  const gateways = M3_GATEWAY_IDS.map((gatewayId, index) =>
    withProjectId(createGatewayState({
      gatewayId,
      endpoint: `http://127.0.0.1:${7101 + index}`,
      boxes: [M3_BOX_RESOURCES[index]],
      now
    }), projectId)
  );

  const wiringConfig = createWiringConfig({
    wiringConfigId: "wir_m3_do1_di1",
    projectId,
    gatewaySessionId: gatewaySessionIds[0],
    name: "M3 simulated DO1 to DI1 patch wiring",
    connections: [
      {
        from: {
          resourceId: M3_BOX_RESOURCES[0],
          port: "DO1"
        },
        to: {
          resourceId: M3_BOX_RESOURCES[1],
          port: "DI1"
        },
        mode: "exclusive"
      }
    ],
    now
  });

  const patchPanel = createPatchPanelState({
    patchPanelStatusId: "pps_m3_hardware_loop",
    gatewaySessionId: gatewaySessionIds[0],
    wiringConfig,
    metadata: {
      signal: "res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1"
    },
    now
  });

  return {
    topologyId: "top_m3_hardware_loop",
    projectId,
    environment: "dev",
    services: {
      boxes,
      gateways,
      patchPanel
    },
    wiringConfig,
    constraints: {
      patchPanelIsOnlyCrossDeviceChannel: true,
      boxSimuLocalLoopbackForCrossDeviceSync: false
    },
    dryRunHints: {
      cliTarget: "fixtures/mvp/m3-hardware-loop/topology.json",
      expectedServices: ["hwlab-box-simu", "hwlab-gateway-simu", "hwlab-patch-panel"]
    }
  };
}

function withProjectId(record, projectId) {
  return {
    ...record,
    projectId,
    ...(record.resource
      ? {
          resource: {
            ...record.resource,
            projectId
          }
        }
      : {}),
    ...(record.capabilities
      ? {
          capabilities: record.capabilities.map((capability) => ({
            ...capability,
            projectId
          }))
        }
      : {}),
    ...(record.session
      ? {
          session: {
            ...record.session,
            projectId
          }
        }
      : {})
  };
}
