#!/usr/bin/env node
// DocFast Support CLI — FreeScout API client for support ticket management
// Env vars (in .credentials/docfast.env):
//   FREESCOUT_URL        — FreeScout instance URL (e.g. https://support.cloonar.com)
//   FREESCOUT_API_KEY    — API key (FreeScout → Manage → API Keys)
//   FREESCOUT_MAILBOX_ID — Mailbox ID for support@docfast.dev

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

const credFile = process.env.CRED_FILE || path.join(__dirname, '..', '.credentials', 'docfast.env');
const env = {};
if (fs.existsSync(credFile)) {
  fs.readFileSync(credFile, 'utf8').split('\n').forEach(l => {
    const m = l.match(/^([A-Z_]+)=(.+)$/);
    if (m) env[m[1]] = m[2].trim();
  });
}

const BASE_URL = env.FREESCOUT_URL;
const API_KEY = env.FREESCOUT_API_KEY;
const MAILBOX_ID = env.FREESCOUT_MAILBOX_ID;

if (!BASE_URL || !API_KEY) {
  console.error('Missing FREESCOUT_URL or FREESCOUT_API_KEY in credentials.');
  process.exit(1);
}

// --- HTTP helper ---
function apiRequest(method, endpoint, body = null) {
  return new Promise((resolve, reject) => {
    const url = new URL(`/api${endpoint}`, BASE_URL);
    const mod = url.protocol === 'https:' ? https : http;
    const opts = {
      method,
      hostname: url.hostname,
      port: url.port,
      path: url.pathname + url.search,
      headers: {
        'X-FreeScout-API-Key': API_KEY,
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
    };
    const req = mod.request(opts, res => {
      let data = '';
      res.on('data', c => data += c);
      res.on('end', () => {
        try { resolve({ status: res.statusCode, data: JSON.parse(data) }); }
        catch { resolve({ status: res.statusCode, data }); }
      });
    });
    req.on('error', reject);
    if (body) req.write(JSON.stringify(body));
    req.end();
  });
}

// --- Commands ---

async function cmdTickets(args) {
  const status = getFlag(args, '--status') || 'active'; // active|pending|closed|spam
  const page = getFlag(args, '--page') || '1';
  let endpoint = `/conversations?page=${page}`;
  if (MAILBOX_ID) endpoint += `&mailboxId=${MAILBOX_ID}`;
  if (status) endpoint += `&status=${status}`;

  const res = await apiRequest('GET', endpoint);
  if (res.status !== 200) { console.error('Error:', res.status, JSON.stringify(res.data)); process.exit(1); }

  const conversations = res.data._embedded?.conversations || [];
  if (conversations.length === 0) { console.log('No tickets found.'); return; }

  console.log('ID\tSTATUS\tSUBJECT\tCUSTOMER\tCREATED\tTHREADS');
  for (const c of conversations) {
    const customer = c.customer?.email || c.customer?.firstName || 'unknown';
    const created = c.createdAt?.split('T')[0] || '-';
    console.log(`${c.id}\t${c.status}\t${c.subject}\t${customer}\t${created}\t${c.threads || '-'}`);
  }
  if (res.data.page?.totalPages > 1) {
    console.log(`\nPage ${res.data.page.current}/${res.data.page.totalPages} (${res.data.page.total} total)`);
  }
}

async function cmdView(args) {
  const id = args[0];
  if (!id) { console.error('Usage: docfast-support view <ticket-id>'); process.exit(1); }

  const res = await apiRequest('GET', `/conversations/${id}`);
  if (res.status !== 200) { console.error('Error:', res.status, JSON.stringify(res.data)); process.exit(1); }

  const c = res.data;
  console.log(`Ticket #${c.id}: ${c.subject}`);
  console.log(`Status: ${c.status} | Customer: ${c.customer?.email || 'unknown'} | Created: ${c.createdAt}`);
  console.log('---');

  // Get threads (messages) — must use embed=threads on conversation endpoint
  const tRes = await apiRequest('GET', `/conversations/${id}?embed=threads`);
  if (tRes.status === 200) {
    const threads = tRes.data._embedded?.threads || [];
    for (const t of threads) {
      const from = t.createdBy?.email || t.customer?.email || 'system';
      const type = t.type || 'message'; // customer|message|note
      const date = t.createdAt?.replace('T', ' ').slice(0, 16) || '-';
      console.log(`\n[${date}] ${type.toUpperCase()} from ${from}:`);
      // Strip HTML tags for readability
      const body = (t.body || '').replace(/<[^>]+>/g, '').replace(/&nbsp;/g, ' ').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').trim();
      console.log(body);
    }
  }
}

async function cmdReply(args) {
  const id = getFlag(args, '--ticket');
  const message = getFlag(args, '--message');
  const draft = args.includes('--draft');
  const status = getFlag(args, '--status'); // active|pending|closed

  if (!id || !message) {
    console.error('Usage: docfast-support reply --ticket <id> --message "..." [--draft] [--status active|pending|closed]');
    process.exit(1);
  }

  // FreeScout API text field: convert plain text to HTML so emails render with line breaks
  const htmlText = message
    .split(/\n{2,}/)
    .map(para => `<p>${para.replace(/\n/g, '<br>')}</p>`)
    .join('');
  const body = {
    type: draft ? 'note' : 'message',
    text: htmlText,
    user: 6,
    status: status || (draft ? undefined : 'active'),
  };

  // If draft, create as internal note (visible to agents only)
  if (draft) {
    body.type = 'note';
  }

  const res = await apiRequest('POST', `/conversations/${id}/threads`, body);
  if (res.status === 201 || res.status === 200) {
    console.log(draft ? `Draft note added to ticket #${id}` : `Reply sent to ticket #${id}`);
    if (status) console.log(`Status set to: ${status}`);
  } else {
    console.error('Error:', res.status, JSON.stringify(res.data));
    process.exit(1);
  }
}

async function cmdNeedsReply(args) {
  // Show only tickets assigned to the AI agent (franz.hubert@docfast.dev) where the last non-note thread is from a customer
  const AI_AGENT_EMAIL = 'franz.hubert@docfast.dev';
  const page = getFlag(args, '--page') || '1';
  let endpoint = `/conversations?page=${page}&status=active`;
  if (MAILBOX_ID) endpoint += `&mailboxId=${MAILBOX_ID}`;

  const res = await apiRequest('GET', endpoint);
  if (res.status !== 200) { console.error('Error:', res.status, JSON.stringify(res.data)); process.exit(1); }

  const conversations = res.data._embedded?.conversations || [];
  if (conversations.length === 0) { console.log('No tickets need a reply.'); return; }

  const needsReply = [];
  for (const c of conversations) {
    // Only tickets assigned to the AI agent or unassigned
    const assignee = c.assignee?.email || '';
    if (assignee && assignee.toLowerCase() !== AI_AGENT_EMAIL.toLowerCase()) continue;

    const tRes = await apiRequest('GET', `/conversations/${c.id}?embed=threads`);
    if (tRes.status !== 200) { console.error(`  Ticket ${c.id}: API returned ${tRes.status}`); continue; }
    const threads = (tRes.data._embedded?.threads || [])
      .filter(t => t.type !== 'note' && t.type !== 'lineitem');
    if (threads.length === 0) { continue; }
    const lastThread = threads[0]; // FreeScout returns threads in reverse chronological order (newest first)
    // type 'customer' = from customer, 'message' = from agent
    if (lastThread.type === 'customer') {
      needsReply.push(c);
    }
  }

  if (needsReply.length === 0) { console.log('No tickets need a reply.'); return; }

  console.log('ID\tSUBJECT\tCUSTOMER\tCREATED');
  for (const c of needsReply) {
    const customer = c.customer?.email || c.customer?.firstName || 'unknown';
    const created = c.createdAt?.split('T')[0] || '-';
    console.log(`${c.id}\t${c.subject}\t${customer}\t${created}`);
  }
  console.log(`\n${needsReply.length} ticket(s) need a reply.`);
}

async function cmdClose(args) {
  const id = args[0];
  if (!id) { console.error('Usage: docfast-support close <ticket-id>'); process.exit(1); }

  const res = await apiRequest('PUT', `/conversations/${id}`, { status: 'closed' });
  if (res.status === 200 || res.status === 204) {
    console.log(`Ticket #${id} closed.`);
  } else {
    console.error('Error:', res.status, JSON.stringify(res.data));
    process.exit(1);
  }
}

async function cmdStats() {
  const statuses = ['active', 'pending', 'closed'];
  console.log('STATUS\tCOUNT');
  for (const s of statuses) {
    let endpoint = `/conversations?status=${s}&page=1`;
    if (MAILBOX_ID) endpoint += `&mailboxId=${MAILBOX_ID}`;
    const res = await apiRequest('GET', endpoint);
    const total = res.data?.page?.total || 0;
    console.log(`${s}\t${total}`);
  }
}

async function cmdMailboxes() {
  const res = await apiRequest('GET', '/mailboxes');
  if (res.status !== 200) { console.error('Error:', res.status, JSON.stringify(res.data)); process.exit(1); }
  const mailboxes = res.data._embedded?.mailboxes || [];
  console.log('ID\tNAME\tEMAIL');
  for (const m of mailboxes) {
    console.log(`${m.id}\t${m.name}\t${m.email || '-'}`);
  }
}

// --- Helpers ---

function getFlag(args, flag) {
  const idx = args.indexOf(flag);
  if (idx === -1) return null;
  return args[idx + 1] || null;
}

// --- Main ---

const [cmd, ...args] = process.argv.slice(2);

const commands = {
  tickets: cmdTickets,
  'needs-reply': cmdNeedsReply,
  view: cmdView,
  reply: cmdReply,
  close: cmdClose,
  stats: cmdStats,
  mailboxes: cmdMailboxes,
};

if (!cmd || !commands[cmd]) {
  console.log(`DocFast Support — FreeScout ticket management

Usage: docfast-support <command> [args]

Commands:
  tickets [--status active|pending|closed|spam]   List tickets (default: active)
  needs-reply                                      Tickets waiting for agent reply
  view <ticket-id>                                 View ticket with all messages
  reply --ticket <id> --message "..."              Send reply to customer
    [--draft]                                      Save as internal note instead
    [--status active|pending|closed]               Set ticket status after reply
  close <ticket-id>                                Close a ticket
  stats                                            Ticket counts by status
  mailboxes                                        List mailboxes (find your mailbox ID)

Env vars (in .credentials/docfast.env):
  FREESCOUT_URL         FreeScout instance URL
  FREESCOUT_API_KEY     API key
  FREESCOUT_MAILBOX_ID  Mailbox ID for filtering (optional)`);
  process.exit(0);
}

commands[cmd](args).catch(e => { console.error(e.message); process.exit(1); });
