#!/usr/bin/env node

/* eslint-disable no-console */

const https = require('https');
const http = require('http');
const fs = require('fs');
const path = require('path');

// --- DEPRECATION WARNING ---
// In v4, live-status CLI is deprecated. The status-watcher daemon handles
// all updates automatically by tailing JSONL transcripts. You do not need
// to call this tool manually. It remains available for backward compatibility.
if (process.stderr.isTTY) {
  console.error('NOTE: live-status CLI is deprecated as of v4. Status updates are now automatic.');
}

// --- PARSE ARGS ---
const args = process.argv.slice(2);
let command = null;
const options = {};
const otherArgs = [];

for (let i = 0; i < args.length; i++) {
  const arg = args[i]; // eslint-disable-line security/detect-object-injection
  const next = args[i + 1]; // eslint-disable-line security/detect-object-injection
  if (arg === '--channel' && next) {
    options.channel = next;
    i++;
  } else if (arg === '--reply-to' && next) {
    options.replyTo = next;
    i++;
  } else if (arg === '--agent' && next) {
    options.agent = next;
    i++;
  } else if (arg === '--token' && next) {
    options.token = next;
    i++;
  } else if (arg === '--host' && next) {
    options.host = next;
    i++;
  } else if (arg === '--rich') {
    options.rich = true;
  } else if (
    !command &&
    ['create', 'update', 'complete', 'error', 'delete', 'start-watcher', 'stop-watcher'].includes(
      arg,
    )
  ) {
    command = arg;
  } else {
    otherArgs.push(arg);
  }
}

// --- LOAD CONFIG ---
function loadConfig() {
  const searchPaths = [
    process.env.OPENCLAW_CONFIG_DIR && path.join(process.env.OPENCLAW_CONFIG_DIR, 'openclaw.json'),
    process.env.XDG_CONFIG_HOME && path.join(process.env.XDG_CONFIG_HOME, 'openclaw.json'),
    path.join(process.env.HOME || '/root', '.openclaw', 'openclaw.json'),
    '/home/node/.openclaw/openclaw.json',
  ].filter(Boolean);

  for (const p of searchPaths) {
    try {
      // eslint-disable-next-line security/detect-non-literal-fs-filename
      return JSON.parse(fs.readFileSync(p, 'utf8'));
    } catch (_e) {
      /* file not found or invalid JSON — try next path */
    }
  }
  return null;
}

function resolveToken(config) {
  if (options.token) return options.token;
  if (process.env.MM_BOT_TOKEN) return process.env.MM_BOT_TOKEN;
  if (!config) return null;

  const mm = config.mattermost || (config.channels && config.channels.mattermost) || {};
  const accounts = mm.accounts || {};

  if (options.agent) {
    try {
      const mapPath = path.join(__dirname, 'agent-accounts.json');
      const agentMap = JSON.parse(fs.readFileSync(mapPath, 'utf8'));
      // eslint-disable-next-line security/detect-object-injection
      const accName = agentMap[options.agent];
      // eslint-disable-next-line security/detect-object-injection
      if (accName && accounts[accName] && accounts[accName].botToken) {
        // eslint-disable-next-line security/detect-object-injection
        return accounts[accName].botToken;
      }
    } catch (_e) {
      /* agent-accounts.json not found or agent not mapped */
    }
  }

  if (accounts.default && accounts.default.botToken) return accounts.default.botToken;
  for (const acc of Object.values(accounts)) {
    if (acc.botToken) return acc.botToken;
  }
  return null;
}

function resolveHost(config) {
  if (options.host) return options.host;
  if (process.env.MM_HOST) return process.env.MM_HOST;
  if (config) {
    const mm = config.mattermost || (config.channels && config.channels.mattermost) || {};
    const baseUrl = mm.baseUrl || '';
    if (baseUrl) {
      try {
        return new URL(baseUrl).hostname;
      } catch (_e) {
        /* invalid URL */
      }
    }
  }
  return 'localhost';
}

function resolvePort(config) {
  if (process.env.MM_PORT) return parseInt(process.env.MM_PORT, 10);
  if (config) {
    const mm = config.mattermost || (config.channels && config.channels.mattermost) || {};
    const baseUrl = mm.baseUrl || '';
    if (baseUrl) {
      try {
        const url = new URL(baseUrl);
        return url.port ? parseInt(url.port, 10) : url.protocol === 'https:' ? 443 : 80;
      } catch (_e) {
        /* invalid URL — use default port */
      }
    }
  }
  return 443;
}

function resolveProtocol(config) {
  if (config) {
    const mm = config.mattermost || (config.channels && config.channels.mattermost) || {};
    if ((mm.baseUrl || '').startsWith('http://')) return 'http';
  }
  return 'https';
}

// --- BUILD CONFIG ---
const ocConfig = loadConfig();
const CONFIG = {
  host: resolveHost(ocConfig),
  port: resolvePort(ocConfig),
  protocol: resolveProtocol(ocConfig),
  token: resolveToken(ocConfig),
  channel_id: options.channel || process.env.MM_CHANNEL_ID || process.env.CHANNEL_ID,
};

if (!CONFIG.token) {
  console.error('Error: No bot token found.');
  console.error('  Set MM_BOT_TOKEN, use --token, or configure openclaw.json');
  process.exit(1);
}

// --- HTTP REQUEST ---
function request(method, apiPath, data) {
  const transport = CONFIG.protocol === 'https' ? https : http;
  return new Promise((resolve, reject) => {
    const req = transport.request(
      {
        hostname: CONFIG.host,
        port: CONFIG.port,
        path: '/api/v4' + apiPath,
        method,
        headers: { Authorization: `Bearer ${CONFIG.token}`, 'Content-Type': 'application/json' },
      },
      (res) => {
        let body = '';
        res.on('data', (chunk) => (body += chunk));
        res.on('end', () => {
          if (res.statusCode >= 200 && res.statusCode < 300) {
            try {
              resolve(JSON.parse(body));
            } catch (_e) {
              resolve(body);
            }
          } else {
            let msg = `HTTP ${res.statusCode}`;
            try {
              msg = JSON.parse(body).message || msg;
            } catch (_e) {
              /* use default msg */
            }
            reject(new Error(msg));
          }
        });
      },
    );
    req.on('error', (e) => reject(e));
    if (data) req.write(JSON.stringify(data));
    req.end();
  });
}

// --- RICH ATTACHMENT HELPERS ---
const RICH_STYLES = {
  create: { color: '#FFA500', prefix: '⏳', status: '🔄 Running' },
  update: { color: '#FFA500', prefix: '🔄', status: '🔄 Running' },
  complete: { color: '#36A64F', prefix: '✅', status: '✅ Complete' },
  error: { color: '#DC3545', prefix: '❌', status: '❌ Error' },
};

function buildAttachment(cmd, text) {
  const style = RICH_STYLES[cmd] || RICH_STYLES.update; // eslint-disable-line security/detect-object-injection
  const agentName = options.agent || 'unknown';

  // Split text: first line = title, rest = log body
  const lines = text.split('\n');
  const title = `${style.prefix} ${lines[0]}`;
  const body = lines.length > 1 ? lines.slice(1).join('\n') : '';

  return {
    color: style.color,
    title: title,
    text: body || undefined,
    fields: [
      { short: true, title: 'Agent', value: agentName },
      { short: true, title: 'Status', value: style.status },
    ],
  };
}

// --- COMMANDS ---

async function createPost(text, cmd) {
  if (!CONFIG.channel_id) {
    console.error('Error: Channel ID required. Use --channel <id> or set MM_CHANNEL_ID.');
    process.exit(1);
  }
  if (!text || !text.trim()) {
    console.error('Error: Message text is required for create.');
    process.exit(1);
  }
  try {
    let payload;
    if (options.rich) {
      payload = {
        channel_id: CONFIG.channel_id,
        message: '',
        props: { attachments: [buildAttachment(cmd || 'create', text)] },
      };
    } else {
      payload = { channel_id: CONFIG.channel_id, message: text };
    }
    if (options.replyTo) payload.root_id = options.replyTo;
    const result = await request('POST', '/posts', payload);
    console.log(result.id);
  } catch (e) {
    console.error('Error (create):', e.message);
    process.exit(1);
  }
}

async function updatePost(postId, text, cmd) {
  if (!postId) {
    console.error('Error: Post ID is required for update.');
    process.exit(1);
  }
  if (!text || !text.trim()) {
    console.error('Error: Message text is required for update.');
    process.exit(1);
  }
  try {
    if (options.rich) {
      await request('PUT', `/posts/${postId}`, {
        id: postId,
        message: '',
        props: { attachments: [buildAttachment(cmd || 'update', text)] },
      });
    } else {
      const current = await request('GET', `/posts/${postId}`);
      await request('PUT', `/posts/${postId}`, {
        id: postId,
        message: text,
        props: current.props,
      });
    }
    console.log('updated');
  } catch (e) {
    console.error('Error (update):', e.message);
    process.exit(1);
  }
}

async function deletePost(postId) {
  if (!postId) {
    console.error('Error: Post ID is required for delete.');
    process.exit(1);
  }
  try {
    await request('DELETE', `/posts/${postId}`);
    console.log('deleted');
  } catch (e) {
    console.error('Error (delete):', e.message);
    process.exit(1);
  }
}

// --- CLI ROUTER ---
if (command === 'start-watcher' || command === 'stop-watcher') {
  // Pass-through to watcher-manager.js
  const { spawnSync } = require('child_process');
  const watcherPath = path.join(__dirname, 'watcher-manager.js');
  const subCmd = command === 'start-watcher' ? 'start' : 'stop';
  const result = spawnSync(process.execPath, [watcherPath, subCmd], {
    stdio: 'inherit',
    env: process.env,
  });
  process.exit(result.status || 0);
} else if (command === 'create') {
  createPost(otherArgs.join(' '), 'create');
} else if (command === 'update') {
  updatePost(otherArgs[0], otherArgs.slice(1).join(' '), 'update');
} else if (command === 'complete') {
  updatePost(otherArgs[0], otherArgs.slice(1).join(' '), 'complete');
} else if (command === 'error') {
  updatePost(otherArgs[0], otherArgs.slice(1).join(' '), 'error');
} else if (command === 'delete') {
  deletePost(otherArgs[0]);
} else {
  console.log('Usage:');
  console.log('  live-status [options] create <text>');
  console.log('  live-status [options] update <id> <text>');
  console.log('  live-status [options] complete <id> <text>');
  console.log('  live-status [options] error <id> <text>');
  console.log('  live-status [options] delete <id>');
  console.log('  live-status start-watcher   (pass-through to watcher-manager start)');
  console.log('  live-status stop-watcher    (pass-through to watcher-manager stop)');
  console.log('');
  console.log('Options:');
  console.log('  --rich             Use rich message attachments (colored cards)');
  console.log('  --channel ID       Target channel');
  console.log('  --reply-to ID      Post as thread reply');
  console.log('  --agent NAME       Use bot token mapped to this agent');
  console.log('  --token TOKEN      Explicit bot token (overrides all)');
  console.log('  --host HOST        Mattermost hostname');
  console.log('');
  console.log('Rich mode colors:');
  console.log('  create/update  → Orange (running)');
  console.log('  complete       → Green (done)');
  console.log('  error          → Red (failed)');
  process.exit(1);
}
