import { ImapFlow } from 'imapflow';
import { simpleParser } from 'mailparser';
import db from '../db.js';
import { generateToken } from '../middleware/auth.js';
import { v4 as uuidv4 } from 'uuid';

let imapClient = null;
let pollInterval = null;

function getConfig() {
  return db.prepare('SELECT * FROM email_config WHERE id = 1').get();
}

function getBoardByPrefix(prefix) {
  const boards = db.prepare('SELECT id, title FROM boards WHERE is_archived = 0').all();
  return boards.find(b => b.title.toLowerCase().replace(/\s+/g, '-').startsWith(prefix.toLowerCase()));
}

function getCardByToken(token) {
  const record = db.prepare(`
    SELECT et.*, c.title as card_title, l.board_id, b.title as board_title, u.name as user_name
    FROM email_tokens et
    JOIN cards c ON c.id = et.card_id
    JOIN lists l ON l.id = c.list_id
    JOIN boards b ON b.id = l.board_id
    LEFT JOIN users u ON u.id = et.user_id
    WHERE et.token = ? AND et.expires_at > datetime('now')
  `).get(token);
  return record;
}

async function processMessage(msg) {
  const config = getConfig();
  if (!config || !config.inbound_enabled) return;

  const parsed = await simpleParser(msg.source);

  const fromAddr = parsed.from?.value?.[0]?.address || '';
  const subject = parsed.subject || '(no subject)';
  const bodyText = parsed.text || '';
  const bodyHtml = parsed.html || '';
  const messageId = parsed.messageId || '';
  const references = parsed.references || '';
  const inReplyTo = parsed.inReplyTo || '';

  const sender = db.prepare('SELECT id, name, email FROM users WHERE email = ? AND is_active = 1').get(fromAddr);
  if (!sender) return;

  // Check if this is a reply to an existing card
  if (inReplyTo || references) {
    const refStr = (inReplyTo + ' ' + references).toLowerCase();
    const tokens = db.prepare('SELECT * FROM email_tokens').all();
    for (const t of tokens) {
      if (refStr.includes(t.token.toLowerCase())) {
        const card = getCardByToken(t.token);
        if (card) {
          db.prepare(`INSERT INTO card_comments (card_id, user_id, content, is_email_reply) VALUES (?, ?, ?, 1)`)
            .run(card.card_id, sender.id, `📧 ${bodyText.trim()}`);
          db.prepare(`INSERT INTO card_activity (card_id, user_id, action, details) VALUES (?, ?, 'email_reply', ?)`)
            .run(card.card_id, sender.id, `Replied via email`);
          return;
        }
      }
    }
  }

  // Check if subject matches board prefix pattern (e.g., [tf-board-name] Card title)
  const prefixMatch = subject.match(/^\[(.+?)\]\s*(.+)/);
  if (prefixMatch) {
    const board = getBoardByPrefix(prefixMatch[1]);
    if (board) {
      const firstList = db.prepare('SELECT id FROM lists WHERE board_id = ? AND is_archived = 0 ORDER BY position LIMIT 1').get(board.id);
      if (firstList) {
        const result = db.prepare(`INSERT INTO cards (list_id, title, description, position, created_by) VALUES (?, ?, ?, ?, ?)`)
          .run(firstList.id, prefixMatch[2].trim(), bodyText.substring(0, 2000), Date.now(), sender.id);
        db.prepare(`INSERT INTO card_activity (card_id, user_id, action, details) VALUES (?, ?, 'created_via_email', ?)`)
          .run(result.lastInsertRowid, sender.id, `Created via email from ${fromAddr}`);
        db.prepare(`INSERT INTO email_log (from_email, subject, card_id, direction, status) VALUES (?, ?, ?, 'received', 'processed')`)
          .run(fromAddr, subject, result.lastInsertRowid);
        return;
      }
    }
  }
}

async function pollInbox() {
  const config = getConfig();
  if (!config || !config.inbound_enabled) {
    return;
  }

  try {
    if (!imapClient) {
      imapClient = new ImapFlow({
        host: config.imap_host,
        port: config.imap_port,
        secure: true,
        auth: {
          user: config.email,
          pass: config.app_password,
        },
        logger: false,
      });
      await imapClient.connect();
    }

    const lock = await imapClient.getMailboxLock(config.inbound_folder);
    try {
      const lastPoll = db.prepare("SELECT value FROM app_state WHERE key = 'last_imap_poll'").get();
      let since = new Date(Date.now() - 24 * 60 * 60 * 1000);
      if (lastPoll) {
        const d = new Date(lastPoll.value);
        if (!isNaN(d)) since = d;
      }

      for await (const msg of imapClient.fetch({ since }, { source: true })) {
        try {
          await processMessage(msg);
        } catch (err) {
          console.error('Error processing email:', err.message);
        }
      }

      db.prepare("INSERT OR REPLACE INTO app_state (key, value) VALUES ('last_imap_poll', ?)")
        .run(new Date().toISOString());
    } finally {
      lock.release();
    }
  } catch (err) {
    console.error('IMAP poll error:', err.message);
    imapClient = null;
  }
}

export function startImapPolling() {
  if (pollInterval) clearInterval(pollInterval);
  const config = getConfig();
  if (config?.inbound_enabled) {
    pollInterval = setInterval(pollInbox, 60000);
    pollInbox();
  }
}

export function stopImapPolling() {
  if (pollInterval) {
    clearInterval(pollInterval);
    pollInterval = null;
  }
  if (imapClient) {
    imapClient.logout().catch(() => {});
    imapClient = null;
  }
}

export { pollInbox };
