import { Injectable, BadRequestException, Logger } from "@nestjs/common";
import { DbService } from "../db/db.service";
import { InstancesService } from "../instances/instances.service";
import { MessagesService } from "../messages/messages.service";

/** Linha típica: 29/07/2026 10:15 - Nome: texto  |  [29/07/2026, 10:15:30] Nome: texto */
const LINE_RE =
  /^\[?(\d{1,2}[\/.]\d{1,2}[\/.]\d{2,4}),?\s+(\d{1,2}:\d{2}(?::\d{2})?)\]?\s*(?:-\s*)?([^:]+):\s([\s\S]+)$/;

@Injectable()
export class TxtImportService {
  private readonly logger = new Logger(TxtImportService.name);

  constructor(
    private readonly db: DbService,
    private readonly instances: InstancesService,
    private readonly messages: MessagesService,
  ) {}

  parseLines(content: string): Array<{
    sentAt: Date;
    author: string;
    body: string;
  }> {
    const lines = content.replace(/^\uFEFF/, "").split(/\r?\n/);
    const out: Array<{ sentAt: Date; author: string; body: string }> = [];
    let current: { sentAt: Date; author: string; body: string } | null = null;

    for (const raw of lines) {
      const line = raw.trimEnd();
      if (!line.trim()) continue;
      const m = line.match(LINE_RE);
      if (m) {
        if (current) out.push(current);
        const sentAt = this.parseDate(m[1], m[2]);
        current = {
          sentAt,
          author: m[3].trim(),
          body: m[4].trim(),
        };
      } else if (current) {
        current.body += `\n${line}`;
      }
    }
    if (current) out.push(current);
    return out;
  }

  private parseDate(datePart: string, timePart: string): Date {
    const sep = datePart.includes(".") ? "." : "/";
    const [d, mo, yRaw] = datePart.split(sep).map((x) => parseInt(x, 10));
    let y = yRaw;
    if (y < 100) y += 2000;
    const t = timePart.split(":").map((x) => parseInt(x, 10));
    const hh = t[0] || 0;
    const mm = t[1] || 0;
    const ss = t[2] || 0;
    return new Date(y, mo - 1, d, hh, mm, ss);
  }

  async importTxt(opts: {
    usuarioId: string;
    filename?: string;
    content: string;
    chatRemote?: string;
    ownerNames?: string[];
  }) {
    if (!opts.usuarioId) throw new BadRequestException("usuarioId required");
    let instance = await this.instances.findByUsuario(opts.usuarioId);
    if (!instance) {
      const created = await this.instances.createOrConnect(opts.usuarioId);
      instance = created.instance;
    }
    if (!instance) throw new BadRequestException("Could not ensure instance");

    const instanceId = instance.id as string;
    const remoteJid =
      opts.chatRemote ||
      `txt:${(opts.filename || "export").replace(/\s+/g, "_").toLowerCase()}`;
    const ownerSet = new Set(
      (opts.ownerNames || []).map((n) => n.trim().toLowerCase()),
    );

    const parsed = this.parseLines(opts.content);
    let imported = 0;
    let skippedDuplicates = 0;
    let errorCount = 0;

    for (const row of parsed) {
      try {
        const fromMe =
          ownerSet.size > 0
            ? ownerSet.has(row.author.toLowerCase())
            : false;
        const result = await this.messages.upsertMessage({
          instanceId,
          remoteJid,
          contactName: fromMe ? null : row.author,
          fromMe,
          body: row.body,
          messageType: "conversation",
          sentAt: row.sentAt,
          source: "txt_import",
          rawJson: { author: row.author, filename: opts.filename },
        });
        if (result === "inserted") imported++;
        else skippedDuplicates++;
      } catch (err) {
        errorCount++;
        this.logger.warn(`txt line failed: ${err}`);
      }
    }

    await this.db.query(
      `INSERT INTO hubee_wpp.import_batches
         (instance_id, hubee_usuario_id, filename, imported_count, skipped_duplicates, error_count)
       VALUES ($1, $2, $3, $4, $5, $6)`,
      [
        instanceId,
        opts.usuarioId,
        opts.filename || null,
        imported,
        skippedDuplicates,
        errorCount,
      ],
    );

    return {
      imported,
      skippedDuplicates,
      errorCount,
      parsedLines: parsed.length,
      chatRemote: remoteJid,
    };
  }
}
