/**
 * TASKMATE - Git Route
 * =====================
 * API-Endpoints für Git-Operationen
 */

const express = require('express');
const router = express.Router();
const { getDb } = require('../database');
const logger = require('../utils/logger');
const gitService = require('../services/gitService');
const giteaService = require('../services/giteaService');

/**
 * Hilfsfunktion: Anwendung für Projekt abrufen
 */
function getApplicationForProject(projectId) {
  const db = getDb();
  return db.prepare('SELECT * FROM applications WHERE project_id = ?').get(projectId);
}

/**
 * POST /api/git/clone
 * Repository klonen
 */
router.post('/clone', async (req, res) => {
  try {
    const { projectId, repoUrl, localPath, branch } = req.body;

    if (!localPath) {
      return res.status(400).json({ error: 'localPath ist erforderlich' });
    }

    if (!repoUrl) {
      return res.status(400).json({ error: 'repoUrl ist erforderlich' });
    }

    // Clone ausführen
    const result = await gitService.cloneRepository(repoUrl, localPath, { branch });

    if (result.success && projectId) {
      // Anwendung aktualisieren
      const db = getDb();
      db.prepare('UPDATE applications SET last_sync = CURRENT_TIMESTAMP WHERE project_id = ?').run(projectId);
    }

    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Klonen:', error);
    res.status(500).json({ error: 'Serverfehler', details: error.message });
  }
});

/**
 * GET /api/git/status/:projectId
 * Git-Status für ein Projekt abrufen
 */
router.get('/status/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    const result = gitService.getStatus(application.local_path);
    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Abrufen des Status:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * POST /api/git/pull/:projectId
 * Pull für ein Projekt ausführen
 */
router.post('/pull/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const { branch } = req.body;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    // Fetch zuerst
    gitService.fetchRemote(application.local_path);

    // Dann Pull
    const result = gitService.pullChanges(application.local_path, { branch });

    if (result.success) {
      // Sync-Zeitpunkt aktualisieren
      const db = getDb();
      db.prepare('UPDATE applications SET last_sync = CURRENT_TIMESTAMP WHERE project_id = ?').run(projectId);
    }

    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Pull:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * POST /api/git/push/:projectId
 * Push für ein Projekt ausführen
 */
router.post('/push/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const { branch } = req.body;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    // Prüfe ob Remote existiert
    if (!gitService.hasRemote(application.local_path)) {
      return res.json({
        success: false,
        error: 'Kein Remote konfiguriert. Bitte Repository zuerst vorbereiten.'
      });
    }

    // Versuche normalen Push, falls das fehlschlägt wegen fehlendem Upstream, push mit -u
    let result = gitService.pushChanges(application.local_path, { branch });

    // Falls Push wegen fehlendem Upstream fehlschlägt, versuche mit -u
    if (!result.success && result.error && result.error.includes('no upstream')) {
      const currentBranch = branch || 'main';
      result = gitService.pushWithUpstream(application.local_path, currentBranch);
    }

    if (result.success) {
      // Sync-Zeitpunkt aktualisieren
      const db = getDb();
      db.prepare('UPDATE applications SET last_sync = CURRENT_TIMESTAMP WHERE project_id = ?').run(projectId);
    }

    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Push:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * POST /api/git/commit/:projectId
 * Commit für ein Projekt erstellen
 */
router.post('/commit/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const { message, stageAll } = req.body;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    if (!message) {
      return res.status(400).json({ error: 'Commit-Nachricht ist erforderlich' });
    }

    // Optional: Alle Änderungen stagen
    if (stageAll !== false) {
      const stageResult = gitService.stageAll(application.local_path);
      if (!stageResult.success) {
        return res.json(stageResult);
      }
    }

    // Commit erstellen
    const result = gitService.commit(application.local_path, message);
    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Commit:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * GET /api/git/commits/:projectId
 * Commit-Historie für ein Projekt abrufen
 */
router.get('/commits/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const limit = parseInt(req.query.limit) || 20;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    const result = gitService.getCommitHistory(application.local_path, limit);
    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Abrufen der Commits:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * GET /api/git/branches/:projectId
 * Branches für ein Projekt abrufen
 */
router.get('/branches/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    const result = gitService.getBranches(application.local_path);
    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Abrufen der Branches:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * POST /api/git/checkout/:projectId
 * Branch wechseln
 */
router.post('/checkout/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const { branch } = req.body;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    if (!branch) {
      return res.status(400).json({ error: 'Branch ist erforderlich' });
    }

    const result = gitService.checkoutBranch(application.local_path, branch);
    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Branch-Wechsel:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * POST /api/git/fetch/:projectId
 * Fetch von Remote ausführen
 */
router.post('/fetch/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    const result = gitService.fetchRemote(application.local_path);
    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Fetch:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * POST /api/git/stage/:projectId
 * Alle Änderungen stagen
 */
router.post('/stage/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    const result = gitService.stageAll(application.local_path);
    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Stagen:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * GET /api/git/remote/:projectId
 * Remote-URL abrufen
 */
router.get('/remote/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    const result = gitService.getRemoteUrl(application.local_path);
    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Abrufen der Remote-URL:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * POST /api/git/validate-path
 * Pfad validieren
 */
router.post('/validate-path', (req, res) => {
  try {
    const { path } = req.body;

    if (!path) {
      return res.status(400).json({ error: 'Pfad ist erforderlich' });
    }

    const isAccessible = gitService.isPathAccessible(path);
    const isRepo = isAccessible ? gitService.isGitRepository(path) : false;
    const hasRemote = isRepo ? gitService.hasRemote(path) : false;

    res.json({
      valid: isAccessible,
      isRepository: isRepo,
      hasRemote: hasRemote,
      containerPath: gitService.windowsToContainerPath(path)
    });
  } catch (error) {
    logger.error('Fehler bei der Pfad-Validierung:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * POST /api/git/prepare/:projectId
 * Repository für Gitea vorbereiten (init, remote hinzufügen)
 */
router.post('/prepare/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const { repoUrl, branch } = req.body;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    if (!repoUrl) {
      return res.status(400).json({ error: 'repoUrl ist erforderlich' });
    }

    const result = gitService.prepareForGitea(application.local_path, repoUrl, { branch });

    if (result.success) {
      logger.info(`Repository vorbereitet für Projekt ${projectId}: ${repoUrl}`);
    }

    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Vorbereiten des Repositories:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * POST /api/git/set-remote/:projectId
 * Remote für ein Projekt setzen/aktualisieren
 */
router.post('/set-remote/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const { repoUrl } = req.body;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    if (!repoUrl) {
      return res.status(400).json({ error: 'repoUrl ist erforderlich' });
    }

    // Prüfe ob Git-Repo existiert
    if (!gitService.isGitRepository(application.local_path)) {
      // Initialisiere Repository
      const initResult = gitService.initRepository(application.local_path);
      if (!initResult.success) {
        return res.json(initResult);
      }
    }

    // Remote setzen
    const result = gitService.setRemote(application.local_path, repoUrl);
    res.json(result);
  } catch (error) {
    logger.error('Fehler beim Setzen des Remotes:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

/**
 * POST /api/git/init-push/:projectId
 * Initialen Push mit Upstream-Tracking
 */
router.post('/init-push/:projectId', (req, res) => {
  try {
    const { projectId } = req.params;
    const { branch } = req.body;
    const application = getApplicationForProject(projectId);

    if (!application) {
      return res.status(404).json({ error: 'Keine Anwendung für dieses Projekt konfiguriert' });
    }

    const currentBranch = branch || 'main';
    const result = gitService.pushWithUpstream(application.local_path, currentBranch);

    if (result.success) {
      // Sync-Zeitpunkt aktualisieren
      const db = getDb();
      db.prepare('UPDATE applications SET last_sync = CURRENT_TIMESTAMP WHERE project_id = ?').run(projectId);
    }

    res.json(result);
  } catch (error) {
    logger.error('Fehler beim initialen Push:', error);
    res.status(500).json({ error: 'Serverfehler' });
  }
});

module.exports = router;
