import type { ResultSetHeader, RowDataPacket } from "mysql2/promise";
import { pool } from "../db/mysql.js";
import type { ChatMsg } from "../exchange/types.js";

/** Mensagens de chat espelhadas + mapa da ponte Telegram (`chat_messages`). */

export interface ChatMessageRow extends RowDataPacket {
  id: number;
  order_id: number | null;
  order_no: string;
  exchange_msg_id: string | null;
  direction: "in" | "out";
  msg_type: string;
  content: string | null;
  sent_by_automation: number;
  telegram_message_id: number | null;
  telegram_replied: number;
  created_at: Date;
}

/**
 * Insere uma mensagem espelhada. Idempotente pela chave
 * (order_no, exchange_msg_id). Devolve o id e se foi recém-inserida.
 */
export async function insertMessage(
  msg: ChatMsg,
  orderId: number | null,
  sentByAutomation = false,
): Promise<{ id: number; isNew: boolean }> {
  const [res] = await pool.query<ResultSetHeader>(
    `INSERT INTO chat_messages
       (order_id, order_no, exchange_msg_id, direction, msg_type, content, sent_by_automation)
     VALUES (:orderId, :orderNo, :exchangeMsgId, :direction, :msgType, :content, :auto)
     ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id)`,
    {
      orderId,
      orderNo: msg.orderNo,
      exchangeMsgId: msg.id,
      direction: msg.direction,
      msgType: msg.type,
      content: msg.content,
      auto: sentByAutomation ? 1 : 0,
    },
  );
  // affectedRows === 1 => insert novo; === 2 => duplicata atualizada.
  return { id: res.insertId, isNew: res.affectedRows === 1 };
}

/** Insere uma mensagem nossa (saída) já enviada — sem id da exchange ainda. */
export async function insertOutgoing(
  orderNo: string,
  orderId: number | null,
  content: string,
  sentByAutomation: boolean,
): Promise<number> {
  const [res] = await pool.query<ResultSetHeader>(
    `INSERT INTO chat_messages
       (order_id, order_no, direction, msg_type, content, sent_by_automation)
     VALUES (:orderId, :orderNo, 'out', 'text', :content, :auto)`,
    { orderId, orderNo, content, auto: sentByAutomation ? 1 : 0 },
  );
  return res.insertId;
}

export async function listByOrder(orderNo: string): Promise<ChatMessageRow[]> {
  const [rows] = await pool.query<ChatMessageRow[]>(
    `SELECT * FROM chat_messages WHERE order_no = :orderNo ORDER BY id`,
    { orderNo },
  );
  return rows;
}

export async function setTelegramMessageId(id: number, telegramMessageId: number): Promise<void> {
  await pool.query(
    `UPDATE chat_messages SET telegram_message_id = :tg WHERE id = :id`,
    { id, tg: telegramMessageId },
  );
}

export async function findByTelegramMessageId(
  telegramMessageId: number,
): Promise<ChatMessageRow | null> {
  const [rows] = await pool.query<ChatMessageRow[]>(
    `SELECT * FROM chat_messages WHERE telegram_message_id = :tg LIMIT 1`,
    { tg: telegramMessageId },
  );
  return rows[0] ?? null;
}

export async function markTelegramReplied(id: number): Promise<void> {
  await pool.query(`UPDATE chat_messages SET telegram_replied = 1 WHERE id = :id`, { id });
}
