import { promises as fs } from 'fs';
import path from 'path';
import { spawn } from 'child_process';
import { getUserPaths, getPublicPaths } from './user-directories.js';

const SYSTEM_REPO_URL = 'git@git.amberweather.com:mcp-server/hupoer-skills.git';
const SYSTEM_REPO_OWNER = 'mcp-server';
const SYSTEM_REPO_NAME = 'hupoer-skills';

function runGit(args, cwd) {
  return new Promise((resolve, reject) => {
    const gitProcess = spawn('git', args, {
      cwd,
      stdio: ['ignore', 'pipe', 'pipe'],
      env: { ...process.env, GIT_TERMINAL_PROMPT: '0' }
    });
    let stderr = '';
    gitProcess.stderr.on('data', (data) => { stderr += data.toString(); });
    gitProcess.on('close', (code) => {
      if (code === 0) resolve();
      else reject(new Error(stderr || `Git ${args[0]} failed with code ${code}`));
    });
    gitProcess.on('error', (err) => { reject(err); });
  });
}

async function updateRepository(repoPath) {
  try {
    await runGit(['pull', '--ff-only'], repoPath);
  } catch (err) {
    if (err.message.includes('overwritten by merge') || err.message.includes('overwritten by checkout') || err.message.includes('local changes')) {
      console.log('[SystemRepo] git pull failed due to local changes, discarding and retrying:', err.message);
      await runGit(['checkout', '--', '.'], repoPath);
      await runGit(['pull', '--ff-only'], repoPath);
    } else {
      throw err;
    }
  }
}

/**
 * Ensure the system repo is cloned to the shared public directory.
 * If already cloned, attempts to pull latest changes.
 * Returns the path to the public clone.
 */
export async function ensureSystemRepo() {
  const publicPaths = getPublicPaths();
  const publicRepoPath = path.join(publicPaths.skillsRepoDir, SYSTEM_REPO_OWNER, SYSTEM_REPO_NAME);

  try {
    await fs.access(publicRepoPath);
    // Already cloned — try to update
    try {
      await updateRepository(publicRepoPath);
    } catch (err) {
      console.log('[SystemRepo] Failed to pull system repo, using existing clone:', err.message);
    }
  } catch {
    // Not yet cloned
    await fs.mkdir(path.dirname(publicRepoPath), { recursive: true });
    try {
      await runGit(['clone', '--depth', '1', SYSTEM_REPO_URL, publicRepoPath], undefined);
      console.log('[SystemRepo] Cloned system repo to', publicRepoPath);
    } catch (err) {
      console.error('[SystemRepo] Failed to clone system repo:', err.message);
      throw err;
    }
  }

  return publicRepoPath;
}

/**
 * Initialize the system repo for a user.
 * Idempotent: if the user already has the symlink, skip.
 */
export async function initSystemRepoForUser(userUuid) {
  const userPaths = getUserPaths(userUuid);
  const userRepoPath = path.join(userPaths.skillsRepoDir, SYSTEM_REPO_OWNER, SYSTEM_REPO_NAME);

  // If symlink/dir already exists, skip
  try {
    await fs.lstat(userRepoPath);
    // Already set up — nothing to do
    return;
  } catch {
    // Doesn't exist — proceed with setup
  }

  let publicRepoPath;
  try {
    publicRepoPath = await ensureSystemRepo();
  } catch (err) {
    console.error('[SystemRepo] Could not ensure system repo, skipping user init:', err.message);
    return;
  }

  // Create user symlink
  await fs.mkdir(path.dirname(userRepoPath), { recursive: true });
  try {
    await fs.symlink(publicRepoPath, userRepoPath);
    console.log(`[SystemRepo] Linked system repo for user ${userUuid}`);
  } catch (err) {
    console.error(`[SystemRepo] Failed to create symlink for user ${userUuid}:`, err.message);
  }
}

export { SYSTEM_REPO_OWNER, SYSTEM_REPO_NAME, SYSTEM_REPO_URL };
