#!/usr/bin/env node

const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

const DUMP_PATH = path.join(__dirname, '..', 'memory', 'tasks.json');

const NUDGE_INTERVALS = {
  now: 24 * 60 * 60 * 1000,       // 1 day
  soon: 3 * 24 * 60 * 60 * 1000,  // 3 days
  someday: 7 * 24 * 60 * 60 * 1000 // 7 days
};

function load() {
  try {
    return JSON.parse(fs.readFileSync(DUMP_PATH, 'utf8'));
  } catch {
    return { description: "Task tracking", recurring: [], tasks: [] };
  }
}

function save(data) {
  fs.writeFileSync(DUMP_PATH, JSON.stringify(data, null, 2) + '\n');
}

function shortId() {
  return crypto.randomBytes(4).toString('hex');
}

function isDue(task) {
  const interval = NUDGE_INTERVALS[task.priority] || NUDGE_INTERVALS.someday;
  const last = task.lastNudged ? new Date(task.lastNudged).getTime() : 0;
  return Date.now() - last >= interval;
}

function formatTask(t) {
  let line = `${t.id}\t${t.priority}\t${t.text}`;
  if (t.context) line += `\t${t.context}`;
  if (t.lastNudged) line += `\tnudged:${t.lastNudged}`;
  return line;
}

function formatRecurring(r) {
  let line = `${r.id}\t${r.frequency}\t${r.when || '-'}\t${r.text}`;
  if (r.context) line += `\t${r.context}`;
  return line;
}

// --- Commands ---

function cmdList(args) {
  const data = load();
  let tasks = data.tasks || [];

  const prioArg = getFlag(args, '--priority');
  if (prioArg) {
    const prios = prioArg.split(',').map(s => s.trim());
    tasks = tasks.filter(t => prios.includes(t.priority));
  }

  if (args.includes('--due')) {
    tasks = tasks.filter(isDue);
  }

  const prioOrder = { now: 0, soon: 1, someday: 2 };
  tasks.sort((a, b) => (prioOrder[a.priority] ?? 3) - (prioOrder[b.priority] ?? 3));

  const limitArg = getFlag(args, '--limit');
  if (limitArg) {
    tasks = tasks.slice(0, parseInt(limitArg, 10));
  }

  if (tasks.length === 0) {
    console.log('No tasks found.');
    return;
  }

  for (const t of tasks) {
    console.log(formatTask(t));
  }
}

function cmdAdd(args) {
  const isRecurring = args.includes('--recurring');
  const text = getFlag(args, '--text');
  if (!text) { console.error('--text required'); process.exit(1); }
  const context = getFlag(args, '--context') || undefined;

  const data = load();

  if (isRecurring) {
    const frequency = getFlag(args, '--frequency') || 'daily';
    const when = getFlag(args, '--when') || undefined;
    const item = { id: shortId(), text, frequency };
    if (when) item.when = when;
    if (context) item.context = context;
    data.recurring = data.recurring || [];
    data.recurring.push(item);
    save(data);
    console.log(`Added recurring: ${formatRecurring(item)}`);
  } else {
    const priority = getFlag(args, '--priority') || 'soon';
    const task = { id: shortId(), added: new Date().toISOString().slice(0, 10), text, priority };
    if (context) task.context = context;
    data.tasks = data.tasks || [];
    data.tasks.push(task);
    save(data);
    console.log(`Added: ${task.id}\t${priority}\t${text}`);
  }
}

function cmdEdit(args) {
  const id = args[0];
  if (!id) { console.error('Usage: tasks edit <id> [--text ...] [--priority ...] [--context ...] [--frequency ...] [--when ...]'); process.exit(1); }

  const data = load();

  // Check tasks first, then recurring
  let item = (data.tasks || []).find(t => t.id === id);
  let isRecurring = false;
  if (!item) {
    item = (data.recurring || []).find(r => r.id === id);
    isRecurring = true;
  }
  if (!item) { console.error(`Item ${id} not found.`); process.exit(1); }

  const text = getFlag(args, '--text');
  const context = getFlag(args, '--context');
  if (text) item.text = text;
  if (context !== null && context !== undefined) item.context = context;

  if (isRecurring) {
    const frequency = getFlag(args, '--frequency');
    const when = getFlag(args, '--when');
    if (frequency) item.frequency = frequency;
    if (when) item.when = when;
    save(data);
    console.log(`Updated recurring: ${formatRecurring(item)}`);
  } else {
    const priority = getFlag(args, '--priority');
    if (priority) item.priority = priority;
    save(data);
    console.log(`Updated: ${formatTask(item)}`);
  }
}

function cmdDone(args) {
  const id = args[0];
  if (!id) { console.error('Usage: tasks done <id>'); process.exit(1); }

  const data = load();

  // Check tasks
  let idx = (data.tasks || []).findIndex(t => t.id === id);
  if (idx !== -1) {
    const removed = data.tasks.splice(idx, 1)[0];
    save(data);
    console.log(`Done: ${removed.text}`);
    return;
  }

  // Check recurring
  idx = (data.recurring || []).findIndex(r => r.id === id);
  if (idx !== -1) {
    const removed = data.recurring.splice(idx, 1)[0];
    save(data);
    console.log(`Removed recurring: ${removed.text}`);
    return;
  }

  console.error(`Item ${id} not found.`);
  process.exit(1);
}

function cmdShow(args) {
  const id = args[0];
  if (!id) { console.error('Usage: tasks show <id>'); process.exit(1); }

  const data = load();
  const item = (data.tasks || []).find(t => t.id === id)
    || (data.recurring || []).find(r => r.id === id);
  if (!item) { console.error(`Item ${id} not found.`); process.exit(1); }

  console.log(JSON.stringify(item, null, 2));
}

function cmdNudged(args) {
  const ids = (args[0] || '').split(',').map(s => s.trim()).filter(Boolean);
  if (ids.length === 0) { console.error('Usage: tasks nudged <id1>,<id2>,...'); process.exit(1); }

  const data = load();
  const now = new Date().toISOString();
  let count = 0;
  for (const id of ids) {
    const task = (data.tasks || []).find(t => t.id === id);
    if (task) {
      task.lastNudged = now;
      count++;
    }
  }
  save(data);
  console.log(`Marked ${count} task(s) as nudged.`);
}

function cmdRecurring() {
  const data = load();
  const items = data.recurring || [];
  if (items.length === 0) {
    console.log('No recurring items.');
    return;
  }
  for (const r of items) {
    console.log(formatRecurring(r));
  }
}

// --- 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);

switch (cmd) {
  case 'list': cmdList(args); break;
  case 'add': cmdAdd(args); break;
  case 'edit': cmdEdit(args); break;
  case 'done': cmdDone(args); break;
  case 'show': cmdShow(args); break;
  case 'nudged': cmdNudged(args); break;
  case 'recurring': cmdRecurring(); break;
  default:
    console.log(`Usage: tasks <command>

Commands:
  list [--priority now,soon] [--due] [--limit N]
  add --text "..." --priority soon [--context "..."]
  add --recurring --text "..." --frequency daily [--when evening] [--context "..."]
  edit <id> [--text "..."] [--priority|--frequency|--when|--context "..."]
  done <id>
  show <id>
  nudged <id1>,<id2>,...
  recurring`);
}
