// routes/git.js
const express    = require('express');
const router     = express.Router();
const { exec }   = require('child_process');
const fs         = require('fs');
const path       = require('path');
//const simpleGit  = require('simple-git');

const REPOS_DIR = path.join(__dirname, '..', 'repos');

// Ensure repos dir exists
if (!fs.existsSync(REPOS_DIR)) fs.mkdirSync(REPOS_DIR, { recursive: true });

function repoPath(name) {
  if (!name || name.includes('..') || name.includes('/')) throw new Error('Invalid repo name');
  return path.join(REPOS_DIR, name);
}

// ── Safe simple-git loader ────────────────────────────────
function getSimpleGit(path) {
  try {
    const simpleGit = require('simple-git');
    return path ? simpleGit(path) : simpleGit();
  } catch(e) {
    return null;
  }
}

// ── Check if simple-git is installed ─────────────────────
router.get('/check', (req, res) => {
  try {
    require('simple-git');
    res.json({ ok: true });
  } catch(e) {
    res.json({ ok: false, error: "Cannot find module 'simple-git'" });
  }
});

// ── List repositories ────────────────────────────────────
router.get('/repos', async (req, res) => {
  try {
    const simpleGit = require('simple-git'); // ← moved inside try
    const entries = fs.readdirSync(REPOS_DIR, { withFileTypes: true })
      .filter(e => e.isDirectory());

    const repos = await Promise.all(entries.map(async e => {
      const rp = path.join(REPOS_DIR, e.name);
      const gitDir = path.join(rp, '.git');
      if (!fs.existsSync(gitDir)) return null;

      try {
        const git = simpleGit(rp);
        const [status, log, branches] = await Promise.allSettled([
          git.status(),
          git.log(['--max-count=1']),
          git.branch()
        ]);

        const lastCommit = log.status === 'fulfilled' && log.value.latest
          ? { message: log.value.latest.message, date: log.value.latest.date, author: log.value.latest.author_name }
          : null;

        return {
          name       : e.name,
          path       : rp,
          branch     : branches.status === 'fulfilled' ? (branches.value.current || 'main') : 'unknown',
          allBranches: branches.status === 'fulfilled' ? branches.value.all : [],
          dirty      : status.status === 'fulfilled' ? !status.value.isClean() : false,
          files      : status.status === 'fulfilled' ? status.value.files.length : 0,
          lastCommit
        };
      } catch {
        return { name: e.name, path: rp, branch: '?', dirty: false, files: 0, lastCommit: null };
      }
    }));

    res.json({ ok: true, repos: repos.filter(Boolean), dir: REPOS_DIR });
  } catch(e) {
    res.json({ ok: false, error: e.message }); // ← if simple-git missing, this catches it
  }
});

// ── Init new repo ────────────────────────────────────────
router.post('/init', async (req, res) => {
  try {
    const simpleGit  = require('simple-git');
    const { name, description, branch } = req.body;
    if (!name) return res.json({ ok: false, error: 'Repo name required' });

    const rp = repoPath(name);
    if (fs.existsSync(rp)) return res.json({ ok: false, error: 'Repository already exists' });

    fs.mkdirSync(rp, { recursive: true });
    const git = simpleGit(rp);
    await git.init();

    // Set default branch name
    const defaultBranch = branch || 'main';
    await git.raw(['checkout', '-b', defaultBranch]).catch(() => {});

    // Create README
    const readme = `# ${name}\n\n${description || 'Created with ServerPanel'}\n\nCreated: ${new Date().toLocaleString()}\n`;
    fs.writeFileSync(path.join(rp, 'README.md'), readme);

    await git.add('README.md');
    await git.commit('Initial commit');

    res.json({ ok: true, path: rp });
  } catch(e) {
    res.json({ ok: false, error: e.message });
  }
});

// ── Clone repo ───────────────────────────────────────────
router.post('/clone', async (req, res) => {
  try {
    const { url, name } = req.body;
    if (!url) return res.json({ ok: false, error: 'URL required' });

    const repoName = name || path.basename(url, '.git');
    const rp = path.join(REPOS_DIR, repoName);

    if (fs.existsSync(rp)) return res.json({ ok: false, error: 'Destination already exists' });

    const git = simpleGit();
    await git.clone(url, rp);
    res.json({ ok: true, name: repoName, path: rp });
  } catch(e) {
    res.json({ ok: false, error: e.message });
  }
});

// ── Get repo status ──────────────────────────────────────
router.get('/status/:name', async (req, res) => {
  try {
    const rp  = repoPath(req.params.name);
    const git = simpleGit(rp);
    const status = await git.status();
    res.json({ ok: true, status });
  } catch(e) {
    res.json({ ok: false, error: e.message });
  }
});

// ── Get commit log ───────────────────────────────────────
router.get('/log/:name', async (req, res) => {
  try {
    const rp    = repoPath(req.params.name);
    const git   = simpleGit(rp);
    const limit = parseInt(req.query.limit) || 20;
    const log   = await git.log(['--max-count=' + limit]);
    res.json({ ok: true, commits: log.all });
  } catch(e) {
    res.json({ ok: false, error: e.message });
  }
});

// ── Stage + Commit ───────────────────────────────────────
router.post('/commit/:name', async (req, res) => {
  try {
    const { message, author } = req.body;
    if (!message) return res.json({ ok: false, error: 'Commit message required' });

    const rp  = repoPath(req.params.name);
    const git = simpleGit(rp);

    if (author) {
      await git.addConfig('user.name', author.split('<')[0].trim());
      const emailMatch = author.match(/<(.+)>/);
      if (emailMatch) await git.addConfig('user.email', emailMatch[1]);
    }

    await git.add('.');
    const result = await git.commit(message);
    res.json({ ok: true, commit: result.commit, summary: result.summary });
  } catch(e) {
    res.json({ ok: false, error: e.message });
  }
});

// ── List branches ────────────────────────────────────────
router.get('/branches/:name', async (req, res) => {
  try {
    const rp      = repoPath(req.params.name);
    const git     = simpleGit(rp);
    const branches = await git.branch(['-a']);
    res.json({ ok: true, current: branches.current, all: branches.all });
  } catch(e) {
    res.json({ ok: false, error: e.message });
  }
});

// ── Create branch ─────────────────────────────────────────
router.post('/branch/:name', async (req, res) => {
  try {
    const { branch, from } = req.body;
    if (!branch) return res.json({ ok: false, error: 'Branch name required' });

    const rp  = repoPath(req.params.name);
    const git = simpleGit(rp);
    if (from) await git.checkoutBranch(branch, from);
    else      await git.checkoutLocalBranch(branch);
    res.json({ ok: true, branch });
  } catch(e) {
    res.json({ ok: false, error: e.message });
  }
});

// ── Checkout branch ──────────────────────────────────────
router.post('/checkout/:name', async (req, res) => {
  try {
    const { branch } = req.body;
    const rp  = repoPath(req.params.name);
    const git = simpleGit(rp);
    await git.checkout(branch);
    res.json({ ok: true, branch });
  } catch(e) {
    res.json({ ok: false, error: e.message });
  }
});

// ── Pull ─────────────────────────────────────────────────
router.post('/pull/:name', async (req, res) => {
  try {
    const rp     = repoPath(req.params.name);
    const git    = simpleGit(rp);
    const result = await git.pull();
    res.json({ ok: true, summary: result.summary, files: result.files });
  } catch(e) {
    res.json({ ok: false, error: e.message });
  }
});

// ── Add remote ───────────────────────────────────────────
router.post('/remote/:name', async (req, res) => {
  try {
    const { remoteName, url } = req.body;
    const rp  = repoPath(req.params.name);
    const git = simpleGit(rp);
    await git.addRemote(remoteName || 'origin', url);
    res.json({ ok: true });
  } catch(e) {
    res.json({ ok: false, error: e.message });
  }
});

// ── Get remotes ──────────────────────────────────────────
router.get('/remotes/:name', async (req, res) => {
  try {
    const rp      = repoPath(req.params.name);
    const git     = simpleGit(rp);
    const remotes = await git.getRemotes(true);
    res.json({ ok: true, remotes });
  } catch(e) {
    res.json({ ok: false, error: e.message });
  }
});

// ── Delete repo ──────────────────────────────────────────
router.delete('/repo/:name', (req, res) => {
  try {
    const rp = repoPath(req.params.name);
    if (!fs.existsSync(rp)) return res.json({ ok: false, error: 'Not found' });
    fs.rmSync(rp, { recursive: true, force: true });
    res.json({ ok: true });
  } catch(e) {
    res.json({ ok: false, error: e.message });
  }
});

module.exports = router;