import { mkdir, readdir, stat, writeFile } from 'fs/promises';
import { basename, extname, join, resolve } from 'path';
import { getConfig, getAgentRoot } from './config.mjs';

const AGENT_ROOT = getAgentRoot();

// Lazy-load workspace-manager to avoid circular dependency issues
let _getWorkspacePath = null;
let _wsManagerLoaded = false;

async function loadWorkspaceManager() {
  if (_wsManagerLoaded) return;
  _wsManagerLoaded = true;
  try {
    const mod = await import('./workspace-manager.mjs');
    _getWorkspacePath = mod.getWorkspacePath;
  } catch {
    _getWorkspacePath = () => null;
  }
}

/**
 * Eagerly initialize workspace module (call during agent startup).
 * Ensures getWorkspaceRoot() resolves to the active workspace synchronously.
 */
export async function initWorkspaceModule() {
  await loadWorkspaceManager();
}

function resolveWorkspaceRoot(workspaceId) {
  // If explicit workspaceId given, look it up
  if (workspaceId && _getWorkspacePath) {
    const path = _getWorkspacePath(workspaceId);
    if (path) return resolve(path);
  }
  // No explicit ID — try active workspace via workspace-manager
  if (!workspaceId && _getWorkspacePath) {
    const config = getConfig();
    const activeId = config.activeWorkspace || 'default';
    const activePath = _getWorkspacePath(activeId);
    if (activePath) return resolve(activePath);
  }
  // Fallback: config workspaceRoot (DATA_DIR-based in packaged mode)
  const { workspaceRoot } = getConfig();
  const root = workspaceRoot || join(AGENT_ROOT, 'workspaces');
  return resolve(root);
}

export function getWorkspaceRoot() {
  return resolveWorkspaceRoot();
}

export async function ensureWorkspaceRoot(workspaceId) {
  const root = resolveWorkspaceRoot(workspaceId);
  await mkdir(root, { recursive: true });
  return root;
}

function sanitizeFileName(filename) {
  return basename(filename || '').replace(/[^a-zA-Z0-9._-]/g, '_') || `file-${Date.now()}`;
}

async function nextAvailablePath(root, filename) {
  const safe = sanitizeFileName(filename);
  const ext = extname(safe);
  const stem = ext ? safe.slice(0, -ext.length) : safe;
  let attempt = 0;
  while (attempt < 1000) {
    const candidate = attempt === 0 ? safe : `${stem}-${attempt}${ext}`;
    const full = join(root, candidate);
    try {
      await stat(full);
      attempt++;
    } catch {
      return { full, name: candidate };
    }
  }
  throw new Error('Could not allocate filename in workspace');
}

export async function writeWorkspaceFile(filename, content, workspaceId) {
  await loadWorkspaceManager();
  const root = await ensureWorkspaceRoot(workspaceId);
  const { full, name } = await nextAvailablePath(root, filename);
  await writeFile(full, content, 'utf-8');
  return {
    absolutePath: full,
    name,
    publicPath: `/workspace-files/${encodeURIComponent(name)}`
  };
}

export async function writeWorkspaceBuffer(filename, buffer, workspaceId) {
  await loadWorkspaceManager();
  const root = await ensureWorkspaceRoot(workspaceId);
  const { full, name } = await nextAvailablePath(root, filename);
  await writeFile(full, buffer);
  return {
    absolutePath: full,
    name,
    publicPath: `/workspace-files/${encodeURIComponent(name)}`
  };
}

export async function listWorkspaceFiles(workspaceId) {
  await loadWorkspaceManager();
  const root = resolveWorkspaceRoot(workspaceId);
  await mkdir(root, { recursive: true });
  let files = [];
  try {
    files = await readdir(root);
  } catch {
    return [];
  }

  const result = [];
  for (const name of files) {
    if (name.startsWith('.')) continue;
    try {
      const s = await stat(join(root, name));
      if (!s.isFile()) continue;
      result.push({
        name,
        size: s.size,
        modified: s.mtime.toISOString()
      });
    } catch {}
  }

  return result.sort((a, b) => b.modified.localeCompare(a.modified));
}
