'use strict';

const ctmContextClient = require('./ctm-context-client');

const CTM_RE = /\b(?:ctm|claude task manager|task manager|wall-?e|walle)\b/i;
const REMOTE_RE = /\b(?:mobile|phone|remote|url|link|primary|dev\s*tunnel|devtunnel|devtunnels\.ms|tunnel|tailscale|cloudflare|pair(?:ing)?|\/m\/|setup\/network)\b/i;
const SESSION_MEMORY_RE = /\b(?:ctm\s+session\s+memory|session\s+memory|session\s+logs?|coding\s+sessions?|agent\s+sessions?)\b/i;

function classifyCtmOperationalQuery(query, opts = {}) {
  const text = `${query || ''}\n${opts.context || ''}`;
  const matched = [];
  const add = (name, re) => {
    const hit = re.test(text);
    if (hit) matched.push(name);
    return hit;
  };
  const hasCtm = add('ctm', CTM_RE);
  const hasRemote = add('remote_access', REMOTE_RE);
  const hasSessionMemory = add('session_memory', SESSION_MEMORY_RE);
  const required = (hasCtm && hasRemote) || (hasCtm && hasSessionMemory);
  return {
    required,
    matched,
    reason: required
      ? 'The request asks for CTM operational or session-memory context and should not be answered from generic long-term memory.'
      : 'No strong CTM operational-context signal.',
  };
}

function buildSessionSearchQuery(query) {
  const base = String(query || '').trim();
  const boosters = 'CTM primary mobile phone URL mobile_url devtunnels.ms /m/ Microsoft dev tunnel current working phone URL';
  return base ? `${base} ${boosters}` : boosters;
}

function firstString(...values) {
  for (const value of values) {
    const text = String(value || '').trim();
    if (text) return text;
  }
  return '';
}

function summarizeRemoteAccess(status = {}) {
  const microsoft = status.microsoft_dev_tunnel || {};
  const managed = microsoft.managed_tunnel || {};
  const tailscale = status.tailscale || {};
  const cloudflare = status.cloudflare_automation || {};
  const bestMobileUrl = firstString(
    managed.running ? managed.mobile_url : '',
    microsoft.mobile_url,
    tailscale.mobile_url,
    cloudflare.mobile_url
  );
  return {
    ok: Boolean(status && typeof status === 'object' && !status.reason),
    port: status.port || '',
    current_origin: status.current_origin || '',
    allowed_origins: Array.isArray(status.allowed_origins) ? status.allowed_origins.slice(-5) : [],
    best_mobile_url: bestMobileUrl,
    microsoft_dev_tunnel: {
      available: Boolean(microsoft.available),
      signed_in: Boolean(microsoft.signed_in),
      origin: microsoft.origin || managed.origin || '',
      mobile_url: microsoft.mobile_url || managed.mobile_url || '',
      tunnel_id: microsoft.tunnel_id || managed.tunnel_id || '',
      running: Boolean(managed.running),
      access_mode: managed.access_mode || managed.access?.mode || '',
      anonymous_connect: Boolean(managed.access?.anonymous_connect),
      checked_at: managed.last_access_check_at || managed.access?.checked_at || '',
    },
    tailscale: {
      available: Boolean(tailscale.available),
      origin: tailscale.origin || '',
      mobile_url: tailscale.mobile_url || '',
    },
    cloudflare: {
      available: Boolean(cloudflare.available),
      configured: Boolean(cloudflare.managed_tunnel?.configured),
      running: Boolean(cloudflare.managed_tunnel?.running),
      mobile_url: cloudflare.mobile_url || cloudflare.managed_tunnel?.mobile_url || '',
    },
  };
}

function summarizeSessionResult(item = {}) {
  return {
    session_id: item.session_id || item.ctm_session_id || '',
    agent_session_id: item.agent_session_id || '',
    title: item.title || '',
    provider: item.provider || '',
    model: item.model || '',
    branch: item.branch || '',
    timestamp: item.timestamp || item.created_at || '',
    message_index: item.message_index,
    snippet: String(item.snippet || item.content || '').slice(0, 1200),
  };
}

function sourceOk(result) {
  return Boolean(result && (result.ok || result.api_transport?.ok || result.port || result.current_origin || Array.isArray(result.results)));
}

async function lookupCtmOperationalContext(args = {}, options = {}) {
  const query = String(args.query || '').trim();
  const classification = classifyCtmOperationalQuery(query, { context: args.context });
  if (!classification.required && !args.force) {
    return {
      required: false,
      ok: true,
      classification,
      query,
      remote_access: null,
      session_results: [],
      sources: {
        remote_access: { searched: false, ok: true, reason: 'not_required' },
        ctm_sessions: { searched: false, ok: true, reason: 'not_required' },
      },
      context_text: '',
    };
  }

  const timeoutMs = options.timeoutMs ?? args.timeout_ms ?? 6000;
  const cooldownMs = options.cooldownMs ?? args.cooldown_ms ?? 0;
  const limit = Math.max(1, Math.min(Number(args.limit || 5), 10));
  const clientOptions = {
    ...options,
    timeoutMs,
    cooldownMs,
  };

  const [remoteStatus, sessionSearch] = await Promise.all([
    ctmContextClient.getRemoteAccessStatus({}, clientOptions).catch((err) => ({
      ok: false,
      source: 'ctm-api',
      reason: err.message,
    })),
    ctmContextClient.searchSessions({
      query: buildSessionSearchQuery(query),
      limit,
      prefer_api: args.prefer_api,
    }, clientOptions).catch((err) => ({
      ok: false,
      source: 'ctm-api',
      results: [],
      reason: err.message,
    })),
  ]);

  const remoteOk = sourceOk(remoteStatus) && !remoteStatus.reason;
  const sessionOk = Boolean(sessionSearch?.ok);
  const sessionResults = (sessionSearch?.results || []).slice(0, limit).map(summarizeSessionResult);
  const remoteAccess = remoteOk ? summarizeRemoteAccess(remoteStatus) : null;
  const ok = Boolean(remoteAccess?.best_mobile_url || sessionResults.length > 0);
  const result = {
    required: true,
    ok,
    classification,
    query,
    remote_access: remoteAccess,
    session_results: sessionResults,
    sources: {
      remote_access: {
        searched: true,
        ok: remoteOk,
        source: remoteStatus?.source || 'ctm-api',
        reason: remoteStatus?.reason || '',
        api_transport: remoteStatus?.api_transport || null,
      },
      ctm_sessions: {
        searched: true,
        ok: sessionOk,
        source: sessionSearch?.source || '',
        backend_source: sessionSearch?.backend_source || '',
        reason: sessionSearch?.reason || '',
        api_transport: sessionSearch?.api_transport || null,
        count: sessionResults.length,
      },
    },
    must_not_guess: !ok,
  };
  result.context_text = renderCtmOperationalContext(result);
  return result;
}

function renderCtmOperationalContext(context = {}) {
  if (!context.required) return '';
  const lines = [
    'CTM operational context (authoritative for CTM/mobile/session-memory questions):',
  ];
  const remote = context.remote_access || {};
  if (remote.best_mobile_url) {
    lines.push(`- Current best phone URL: ${remote.best_mobile_url}`);
  }
  if (remote.current_origin) {
    lines.push(`- Current CTM origin: ${remote.current_origin}`);
  }
  if (remote.microsoft_dev_tunnel?.mobile_url) {
    const ms = remote.microsoft_dev_tunnel;
    const state = ms.running ? 'running' : 'not running';
    const access = ms.access_mode ? `, access=${ms.access_mode}` : '';
    lines.push(`- Microsoft Dev Tunnel: ${ms.mobile_url} (${state}${access})`);
  }
  if (remote.tailscale?.mobile_url) {
    lines.push(`- Tailscale phone URL: ${remote.tailscale.mobile_url}`);
  }
  if (Array.isArray(remote.allowed_origins) && remote.allowed_origins.length) {
    lines.push(`- Allowed remote origins: ${remote.allowed_origins.join(', ')}`);
  }

  const sessionResults = context.session_results || [];
  if (sessionResults.length) {
    lines.push('- CTM session-memory evidence:');
    sessionResults.forEach((item, index) => {
      const label = [item.timestamp, item.title, item.session_id].filter(Boolean).join(' | ');
      lines.push(`  ${index + 1}. ${label}`);
      if (item.snippet) lines.push(`     ${item.snippet}`);
    });
  }

  if (!remote.best_mobile_url && sessionResults.length === 0) {
    lines.push('- No verified CTM remote URL or session-memory evidence was found.');
    lines.push('- Do not guess from generic project memories, DDEV hosts, localhost, or local IP heuristics.');
  } else {
    lines.push('- Prefer current CTM setup/network status over older session-memory snippets. Use snippets only as last-known history.');
    lines.push('- Do not use unrelated DDEV/project memories as CTM primary remote-access answers.');
  }
  return lines.join('\n');
}

module.exports = {
  classifyCtmOperationalQuery,
  buildSessionSearchQuery,
  lookupCtmOperationalContext,
  renderCtmOperationalContext,
  summarizeRemoteAccess,
};
