import { Router, Request, Response, NextFunction } from "express";
import { env } from "../config/env";
import { createDeviceHeartbeat } from "../shared/store/heartbeatStore";
import { getDeviceBySerialNumber, patchDevice } from "../shared/store/deviceStore";

const router = Router();

type Qf100ConfigRequest = {
  "dev-model"?: string;
  "item-number"?: string;
  "dev-sn"?: string;
  "fw-version"?: string;
  "fw-build"?: number;
  "app-config-version"?: number;
  imei?: string;
  imsi?: string;
  iccid?: string;
};

function parseBrokerUrl() {
  if (!env.MQTT_BROKER_URL) {
    return { host: "", port: 0 };
  }

  try {
    const parsed = new URL(env.MQTT_BROKER_URL);
    return {
      host: parsed.hostname,
      port: parsed.port ? Number(parsed.port) : parsed.protocol === "mqtts:" ? 8883 : 1883
    };
  } catch (_error) {
    return { host: "", port: 0 };
  }
}

function getRequestPayload(req: Request): Qf100ConfigRequest {
  return {
    ...((req.query || {}) as Qf100ConfigRequest),
    ...((req.body || {}) as Qf100ConfigRequest)
  };
}

function vendorError(res: Response, code: number, message: string) {
  res.status(200).json({
    "error-code": code,
    message
  });
}

router.get("/dev-config", async (req: Request, res: Response, next: NextFunction) => {
  try {
    const payload = getRequestPayload(req);
    const serialNumber = String(payload["dev-sn"] || "").trim();

    if (!serialNumber) {
      return vendorError(res, 1001, "dev-sn is required");
    }

    const device = await getDeviceBySerialNumber(serialNumber);
    if (!device || device.status !== "active") {
      return vendorError(res, 1002, "device not registered or inactive");
    }

    const now = new Date();
    const firmwareVersion = payload["fw-version"] ? String(payload["fw-version"]) : device.firmware_version;
    await patchDevice(device.id, {
      vendor: device.vendor || "QF",
      model: payload["dev-model"] ? String(payload["dev-model"]) : device.model || "QF100",
      communication_mode: "mqtt",
      last_seen_at: now.toISOString(),
      firmware_version: firmwareVersion
    });

    await createDeviceHeartbeat({
      device_id: device.id,
      timestamp: now.toISOString(),
      firmware_version: firmwareVersion,
      state: "config_pull",
      payload_json: {
        source: "qf100_dev_config",
        dev_model: payload["dev-model"],
        item_number: payload["item-number"],
        dev_sn: serialNumber,
        fw_build: payload["fw-build"],
        app_config_version: payload["app-config-version"],
        imei: payload.imei,
        imsi: payload.imsi,
        iccid: payload.iccid
      }
    });

    const brokerFromUrl = parseBrokerUrl();
    const brokerHost = env.QF100_MQTT_BROKER_HOST || brokerFromUrl.host;
    const brokerPort = env.QF100_MQTT_BROKER_PORT || brokerFromUrl.port;
    const username = env.QF100_MQTT_USERNAME || device.mqtt_username || device.id;
    const password = env.QF100_MQTT_PASSWORD || env.MQTT_PASSWORD;

    if (!brokerHost || !brokerPort) {
      return vendorError(res, 1003, "mqtt broker is not configured");
    }

    res.json({
      "error-code": 0,
      "bind-state": 1,
      "app-config-version": 1,
      "time-stamp": Math.floor(now.getTime() / 1000),
      "date-time": now.toISOString().replace(/[-:TZ.]/g, "").slice(0, 14),
      mqtt: {
        "broker-ip": brokerHost,
        "broker-port": brokerPort,
        "client-id": device.id,
        "user-name": username,
        password,
        "subscribe-topic": `devices/${device.id}/downlink/qf100`,
        "publish-topic": `devices/${device.id}/uplink/qf100`,
        "keep-alive": env.QF100_MQTT_KEEP_ALIVE_SECONDS,
        "cert-update": 0
      }
    });
  } catch (error) {
    next(error);
  }
});

export default router;
