'use strict';
const { execFile } = require('child_process');
const { promisify } = require('util');
const ChannelBase = require('./channel-base');
const eventBus = require('../events/event-bus');

const execFileAsync = promisify(execFile);

class IMessageChannel extends ChannelBase {
  constructor(opts = {}) {
    super('imessage');
    this.buddyId = opts.buddyId || null; // phone number or email to listen for
    this.pollInterval = opts.pollInterval || 10000; // 10s
    this.lastMessageId = null;
    this._pollTimer = null;
    this._onMessage = opts.onMessage || null; // callback: async (text, sender) => response
  }

  async start() {
    if (!this.buddyId) {
      console.log('[imessage] No buddyId configured, skipping');
      return;
    }
    this.running = true;
    console.log(`[imessage] Listening for messages from ${this.buddyId}`);
    this._poll();
  }

  async stop() {
    this.running = false;
    if (this._pollTimer) clearTimeout(this._pollTimer);
  }

  _poll() {
    if (!this.running) return;
    this._checkMessages().catch(err => {
      console.error('[imessage] Poll error:', err.message);
    }).finally(() => {
      if (this.running) {
        this._pollTimer = setTimeout(() => this._poll(), this.pollInterval);
      }
    });
  }

  async _checkMessages() {
    // Use AppleScript to get the latest message from the buddy
    const sanitizedBuddy = String(this.buddyId).replace(/\\/g, '\\\\').replace(/"/g, '\\"');
    const script = `
      tell application "Messages"
        set targetBuddy to "${sanitizedBuddy}"
        set latestMsg to ""
        set latestId to ""
        repeat with svc in services
          try
            set b to buddy targetBuddy of svc
            set msgs to messages of chat id (id of (chats whose participants contains b)'s item 1)
            if (count of msgs) > 0 then
              set lastMsg to item 1 of msgs
              set latestMsg to (text of lastMsg) as text
              set latestId to (id of lastMsg) as text
            end if
          end try
        end repeat
        return latestId & "|" & latestMsg
      end tell
    `;

    try {
      const { stdout } = await execFileAsync('osascript', ['-e', script], { timeout: 10000 });
      const result = stdout.trim();
      const sepIdx = result.indexOf('|');
      if (sepIdx < 0) return;

      const msgId = result.slice(0, sepIdx);
      const msgText = result.slice(sepIdx + 1);

      if (!msgText || msgId === this.lastMessageId) return;
      this.lastMessageId = msgId;

      console.log(`[imessage] New message from ${this.buddyId}: ${msgText.slice(0, 50)}...`);
      eventBus.emitMessage('imessage', msgText, this.buddyId);

      if (this._onMessage) {
        const response = await this._onMessage(msgText, this.buddyId);
        if (response) await this.send(this.buddyId, response);
      }
    } catch (err) {
      // Messages app may not be running or buddy not found — that's ok
      if (!err.message.includes('execution error')) {
        console.error('[imessage] AppleScript error:', err.message);
      }
    }
  }

  async send(target, message) {
    const sanitizedTarget = String(target).replace(/"/g, '\\"');
    const sanitizedMessage = String(message).replace(/\\/g, '\\\\').replace(/"/g, '\\"');

    const script = `
      tell application "Messages"
        set targetService to 1st service whose service type = iMessage
        set targetBuddy to buddy "${sanitizedTarget}" of targetService
        send "${sanitizedMessage}" to targetBuddy
      end tell
    `;

    try {
      await execFileAsync('osascript', ['-e', script], { timeout: 10000 });
      console.log(`[imessage] Sent reply to ${target}`);
    } catch (err) {
      console.error('[imessage] Send error:', err.message);
    }
  }
}

module.exports = IMessageChannel;
