import { randomUUID } from "node:crypto";
import { getPool } from "../db/pool";

export interface MqttMessageEntity {
  id: string;
  direction: "uplink" | "downlink";
  device_id: string;
  topic: string;
  message_type: string;
  correlation_id?: string;
  payload_json: Record<string, unknown>;
  publish_status: "recorded" | "sent" | "failed";
  reason?: string;
  created_at: string;
}

function nowIso() {
  return new Date().toISOString();
}

function mapMessage(row: any): MqttMessageEntity {
  return {
    id: row.id,
    direction: row.direction,
    device_id: row.device_id,
    topic: row.topic,
    message_type: row.message_type,
    correlation_id: row.correlation_id || undefined,
    payload_json: row.payload_json || {},
    publish_status: row.publish_status,
    reason: row.reason || undefined,
    created_at: row.created_at
  };
}

export async function createMqttMessage(payload: {
  direction: MqttMessageEntity["direction"];
  device_id: string;
  topic: string;
  message_type: string;
  correlation_id?: string;
  payload_json?: Record<string, unknown>;
  publish_status?: MqttMessageEntity["publish_status"];
  reason?: string;
}): Promise<MqttMessageEntity> {
  const { rows } = await getPool().query(
    `INSERT INTO mqtt_messages (
      id,
      direction,
      device_id,
      topic,
      message_type,
      correlation_id,
      payload_json,
      publish_status,
      reason,
      created_at
    ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)
    RETURNING *`,
    [
      `mqtt_${randomUUID()}`,
      payload.direction,
      payload.device_id,
      payload.topic,
      payload.message_type,
      payload.correlation_id || null,
      payload.payload_json || {},
      payload.publish_status || "recorded",
      payload.reason || null,
      nowIso()
    ]
  );

  return mapMessage(rows[0]);
}

export async function listMqttMessages(filter?: {
  device_id?: string;
  direction?: MqttMessageEntity["direction"];
  message_type?: string;
  correlation_id?: string;
  limit?: number;
}): Promise<MqttMessageEntity[]> {
  const clauses: string[] = [];
  const params: unknown[] = [];
  let i = 1;

  if (filter?.device_id) {
    clauses.push(`device_id = $${i++}`);
    params.push(filter.device_id);
  }

  if (filter?.direction) {
    clauses.push(`direction = $${i++}`);
    params.push(filter.direction);
  }

  if (filter?.message_type) {
    clauses.push(`message_type = $${i++}`);
    params.push(filter.message_type);
  }

  if (filter?.correlation_id) {
    clauses.push(`correlation_id = $${i++}`);
    params.push(filter.correlation_id);
  }

  const limit = Math.min(Math.max(filter?.limit || 100, 1), 500);
  const where = clauses.length ? `WHERE ${clauses.join(" AND ")}` : "";
  const { rows } = await getPool().query(
    `SELECT * FROM mqtt_messages ${where} ORDER BY created_at DESC LIMIT ${limit}`,
    params
  );

  return rows.map(mapMessage);
}

export function toMqttMessagePayload(message: MqttMessageEntity) {
  return { ...message };
}
