/**
 * TASKMATE - Gitea Manager
 * ========================
 * Git-Repository-Verwaltung pro Projekt
 */

import api from './api.js';
import { $, $$, escapeHtml } from './utils.js';
import store from './store.js';

class GiteaManager {
  constructor() {
    // Gemeinsame Eigenschaften
    this.initialized = false;
    this.refreshInterval = null;
    this.isLoading = false;
    this.currentMode = 'server'; // 'server' oder 'project'

    // Projekt-Modus Eigenschaften
    this.application = null;
    this.gitStatus = null;
    this.branches = [];
    this.commits = [];
    this.giteaRepos = [];
    this.giteaConnected = false;
    this.hiddenCommits = new Set();

    // Server-Modus Eigenschaften
    this.serverInfo = null;
    this.serverStatus = null;
    this.serverBranches = [];
    this.serverCommits = [];
    this.hiddenServerCommits = new Set();

    // Browser-Upload Eigenschaften
    this.browserUploadFiles = [];
    this.browserUploadSessionId = null;
    this.supportsDirectoryPicker = 'showDirectoryPicker' in window;

    // Zu ignorierende Ordner/Dateien
    this.ignorePatterns = [
      '.git',
      'node_modules',
      '__pycache__',
      '.env',
      '.env.local',
      '.env.production',
      '.DS_Store',
      'Thumbs.db',
      '.idea',
      '.vscode',
      'dist',
      'build',
      '.cache',
      'coverage'
    ];
  }

  async init() {
    if (this.initialized) {
      return;
    }

    // DOM Elements - Gemeinsam
    this.giteaView = $('#view-gitea');
    this.modeSwitch = $('#gitea-mode-switch');

    // DOM Elements - Server-Modus
    this.serverModeSection = $('#gitea-server-mode');

    // DOM Elements - Projekt-Modus
    this.noProjectSection = $('#gitea-no-project');
    this.configSection = $('#gitea-config-section');
    this.mainSection = $('#gitea-main-section');
    this.connectionStatus = $('#gitea-connection-status');

    // DOM Elements - Browser-Upload
    this.browserUploadSection = $('#gitea-browser-upload');

    this.bindEvents();
    this.bindServerEvents();
    this.bindBrowserUploadEvents();
    this.subscribeToStore();
    this.initialized = true;
  }

  bindEvents() {
    // Modus-Schalter
    $$('.gitea-mode-btn').forEach(btn => {
      btn.addEventListener('click', (e) => this.handleModeSwitch(e));
    });

    // Konfiguration speichern
    $('#gitea-config-form')?.addEventListener('submit', (e) => this.handleConfigSave(e));

    // Repository auswählen
    $('#gitea-repo-select')?.addEventListener('change', (e) => this.handleRepoSelect(e));

    // Repositories aktualisieren
    $('#btn-refresh-repos')?.addEventListener('click', () => this.loadGiteaRepos());

    // Neues Repository erstellen
    $('#btn-create-repo')?.addEventListener('click', () => this.openCreateRepoModal());

    // Git-Operationen
    $('#btn-git-fetch')?.addEventListener('click', () => this.handleFetch());
    $('#btn-git-pull')?.addEventListener('click', () => this.handlePull());
    $('#btn-git-push')?.addEventListener('click', () => this.handlePush());
    $('#btn-git-commit')?.addEventListener('click', () => this.openCommitModal());

    // Branch wechseln
    $('#branch-select')?.addEventListener('change', (e) => this.handleBranchChange(e));

    // Pfad validieren
    $('#local-path-input')?.addEventListener('blur', (e) => this.validateLocalPath(e.target.value));

    // Konfiguration bearbeiten/entfernen
    $('#btn-edit-config')?.addEventListener('click', () => this.showConfigSection());
    $('#btn-remove-config')?.addEventListener('click', () => this.handleRemoveConfig());

    // Create Repo Modal
    $('#create-repo-form')?.addEventListener('submit', (e) => this.handleCreateRepo(e));

    // Commit Modal
    $('#git-commit-form')?.addEventListener('submit', (e) => this.handleCommit(e));

    // Push Modal
    $('#git-push-form')?.addEventListener('submit', (e) => this.executePush(e));

    // Branch umbenennen
    $('#btn-rename-branch')?.addEventListener('click', () => this.openRenameBranchModal());
    $('#git-rename-branch-form')?.addEventListener('submit', (e) => this.executeRenameBranch(e));

    // Commits ausblenden
    $('#btn-clear-commits')?.addEventListener('click', () => this.clearAllCommits());
    $('#git-commits-list')?.addEventListener('click', (e) => this.handleCommitListClick(e));
  }

  bindServerEvents() {
    // Server Git-Operationen
    $('#btn-server-fetch')?.addEventListener('click', () => this.handleServerFetch());
    $('#btn-server-pull')?.addEventListener('click', () => this.handleServerPull());
    $('#btn-server-push')?.addEventListener('click', () => this.openServerPushModal());
    $('#btn-server-commit')?.addEventListener('click', () => this.openServerCommitModal());

    // Server Branch wechseln
    $('#server-branch-select')?.addEventListener('change', (e) => this.handleServerBranchChange(e));

    // Server Commits ausblenden
    $('#btn-server-clear-commits')?.addEventListener('click', () => this.clearAllServerCommits());
    $('#server-commits-list')?.addEventListener('click', (e) => this.handleServerCommitListClick(e));
  }

  // Modus-Wechsel Handler
  handleModeSwitch(e) {
    const btn = e.currentTarget;
    const newMode = btn.dataset.mode;

    if (newMode === this.currentMode) return;

    // Button-Status aktualisieren
    $$('.gitea-mode-btn').forEach(b => b.classList.remove('active'));
    btn.classList.add('active');

    this.currentMode = newMode;
    this.updateModeView();
  }

  updateModeView() {
    if (this.currentMode === 'server') {
      // Server-Modus
      this.serverModeSection?.classList.remove('hidden');
      this.browserUploadSection?.classList.add('hidden');
      this.noProjectSection?.classList.add('hidden');
      this.configSection?.classList.add('hidden');
      this.mainSection?.classList.add('hidden');
      this.loadServerData();
    } else {
      // Projekt-Modus (Browser-Upload)
      this.serverModeSection?.classList.add('hidden');
      this.browserUploadSection?.classList.remove('hidden');
      this.noProjectSection?.classList.add('hidden');
      this.configSection?.classList.add('hidden');
      this.mainSection?.classList.add('hidden');
      this.initBrowserUpload();
    }
  }

  // =====================
  // SERVER-MODUS METHODEN
  // =====================

  async loadServerData() {
    this.showLoading();

    try {
      // Server-Info laden
      const infoResult = await api.getServerGitInfo();
      this.serverInfo = infoResult;

      if (infoResult.accessible && infoResult.isRepository) {
        // Remote-URL anzeigen
        if (infoResult.remoteUrl) {
          const repoUrl = $('#server-repo-url');
          if (repoUrl) {
            // Gitea HTML URL generieren (ohne .git)
            const htmlUrl = infoResult.remoteUrl.replace(/\.git$/, '');
            repoUrl.href = htmlUrl;
            repoUrl.textContent = htmlUrl;
            repoUrl.classList.remove('hidden');
          }
        }

        // Git-Daten laden
        await this.loadServerGitData();
      } else {
        this.showToast('Server-Verzeichnis ist kein Git-Repository', 'error');
      }
    } catch (error) {
      console.error('[Gitea Server] Fehler beim Laden:', error);
      this.showToast('Fehler beim Laden der Server-Daten', 'error');
    }
  }

  async loadServerGitData() {
    try {
      const [statusResult, branchesResult, commitsResult] = await Promise.allSettled([
        api.getServerGitStatus(),
        api.getServerGitBranches(),
        api.getServerGitCommits(10)
      ]);

      if (statusResult.status === 'fulfilled') {
        this.serverStatus = statusResult.value;
      } else {
        this.serverStatus = null;
        console.error('[Gitea Server] Status-Fehler:', statusResult.reason);
      }

      if (branchesResult.status === 'fulfilled') {
        this.serverBranches = branchesResult.value.branches || [];
      } else {
        this.serverBranches = [];
      }

      if (commitsResult.status === 'fulfilled') {
        this.serverCommits = commitsResult.value.commits || [];
      } else {
        this.serverCommits = [];
      }

      this.renderServerStatus();
      this.renderServerBranches();
      this.renderServerCommits();
      this.renderServerChanges();
    } catch (error) {
      console.error('[Gitea Server] Git-Daten laden fehlgeschlagen:', error);
    }
  }

  renderServerStatus() {
    const statusBadge = $('#server-status-indicator');
    const changesCount = $('#server-changes-count');

    if (!this.serverStatus) {
      if (statusBadge) {
        statusBadge.textContent = 'Fehler';
        statusBadge.className = 'status-badge error';
      }
      if (changesCount) changesCount.textContent = '-';
      return;
    }

    if (statusBadge) {
      if (!this.serverStatus.success) {
        statusBadge.textContent = 'Fehler';
        statusBadge.className = 'status-badge error';
      } else if (this.serverStatus.isClean) {
        statusBadge.textContent = 'Sauber';
        statusBadge.className = 'status-badge clean';
      } else if (this.serverStatus.hasChanges) {
        statusBadge.textContent = 'Geändert';
        statusBadge.className = 'status-badge dirty';
      } else {
        statusBadge.textContent = 'OK';
        statusBadge.className = 'status-badge clean';
      }
    }

    const changes = this.serverStatus.changes || [];
    if (changesCount) changesCount.textContent = changes.length;
  }

  renderServerBranches() {
    const select = $('#server-branch-select');
    if (!select) return;

    const currentBranch = this.serverStatus?.branch || 'main';

    select.innerHTML = '';

    const localBranches = this.serverBranches.filter(b => !b.isRemote);
    localBranches.forEach(branch => {
      const option = document.createElement('option');
      option.value = branch.name;
      option.textContent = branch.name;
      if (branch.name === currentBranch) {
        option.selected = true;
      }
      select.appendChild(option);
    });
  }

  renderServerCommits() {
    const listEl = $('#server-commits-list');
    const clearBtn = $('#btn-server-clear-commits');
    if (!listEl) return;

    const visibleCommits = this.serverCommits.filter(commit => {
      const hash = commit.hash || commit.sha || commit.shortHash;
      return !this.hiddenServerCommits.has(hash);
    });

    if (clearBtn) {
      clearBtn.style.display = visibleCommits.length > 0 ? '' : 'none';
    }

    if (visibleCommits.length === 0) {
      const message = this.serverCommits.length > 0
        ? 'Alle Commits ausgeblendet'
        : 'Keine Commits gefunden';
      listEl.innerHTML = `<div class="gitea-empty-state" style="padding: var(--spacing-4);"><p>${message}</p></div>`;
      return;
    }

    listEl.innerHTML = visibleCommits.map(commit => {
      const hash = commit.hash || commit.sha || '';
      const shortHash = commit.shortHash || hash.substring(0, 7);
      return `
      <div class="commit-item" data-hash="${escapeHtml(hash)}">
        <span class="commit-hash">${escapeHtml(shortHash)}</span>
        <div class="commit-info">
          <div class="commit-message">${escapeHtml(commit.message?.split('\n')[0] || '')}</div>
          <div class="commit-meta">
            <span class="author">${escapeHtml(commit.author)}</span> · ${this.formatDate(commit.date)}
          </div>
        </div>
        <button class="commit-delete" title="Ausblenden" data-hash="${escapeHtml(hash)}">
          <svg viewBox="0 0 24 24" width="16" height="16"><path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
        </button>
      </div>
    `}).join('');
  }

  renderServerChanges() {
    const changesSection = $('#server-changes-section');
    const listEl = $('#server-changes-list');

    if (!changesSection || !listEl) return;

    const changes = this.serverStatus?.changes || [];

    if (changes.length === 0) {
      changesSection.classList.add('hidden');
      return;
    }

    changesSection.classList.remove('hidden');

    listEl.innerHTML = changes.map(change => {
      const statusClass = this.getChangeStatusClass(change.status);
      const statusLabel = this.getChangeStatusLabel(change.status);

      return `
        <div class="change-item">
          <span class="change-status ${statusClass}" title="${statusLabel}">${change.status}</span>
          <span class="change-file">${escapeHtml(change.file)}</span>
        </div>
      `;
    }).join('');
  }

  // Server Git-Operationen
  async handleServerFetch() {
    this.setServerOperationLoading('fetch', true);

    try {
      const result = await api.serverGitFetch();
      if (result.success) {
        this.showToast('Fetch erfolgreich', 'success');
        await this.loadServerGitData();
      } else {
        this.showToast(result.error || 'Fetch fehlgeschlagen', 'error');
      }
    } catch (error) {
      this.showToast(error.message || 'Fetch fehlgeschlagen', 'error');
    } finally {
      this.setServerOperationLoading('fetch', false);
    }
  }

  async handleServerPull() {
    this.setServerOperationLoading('pull', true);

    try {
      const branch = $('#server-branch-select')?.value || null;
      const result = await api.serverGitPull(branch);

      if (result.success) {
        this.showToast('Pull erfolgreich', 'success');
        await this.loadServerGitData();
      } else {
        this.showToast(result.error || 'Pull fehlgeschlagen', 'error');
      }
    } catch (error) {
      this.showToast(error.message || 'Pull fehlgeschlagen', 'error');
    } finally {
      this.setServerOperationLoading('pull', false);
    }
  }

  openServerPushModal() {
    const modal = $('#git-push-modal');
    if (!modal) return;

    const currentBranch = $('#server-branch-select')?.value || this.serverStatus?.branch || 'main';
    $('#push-local-branch').textContent = currentBranch;
    $('#push-target-branch').value = '';
    $('#push-force').checked = false;

    // Temporär Attribut setzen um Server-Modus zu markieren
    modal.dataset.serverMode = 'true';

    modal.classList.remove('hidden');
    modal.classList.add('visible');
    $('#modal-overlay')?.classList.remove('hidden');

    store.openModal('git-push-modal');
  }

  async executeServerPush(force = false) {
    this.setServerOperationLoading('push', true);

    try {
      const targetBranch = $('#push-target-branch')?.value || null;
      const localBranch = $('#server-branch-select')?.value || this.serverStatus?.branch || 'main';

      const result = await api.serverGitPush(targetBranch || localBranch, force);

      if (result.success) {
        const pushedBranch = result.branch || targetBranch || localBranch;
        this.showToast(`Push erfolgreich nach Branch "${pushedBranch}"`, 'success');
        await this.loadServerGitData();
      } else {
        this.showToast(result.error || 'Push fehlgeschlagen', 'error');
      }
    } catch (error) {
      this.showToast(error.message || 'Push fehlgeschlagen', 'error');
    } finally {
      this.setServerOperationLoading('push', false);
    }
  }

  openServerCommitModal() {
    const modal = $('#git-commit-modal');
    if (!modal) return;

    $('#commit-message').value = '';
    $('#commit-stage-all').checked = true;

    // Temporär Attribut setzen um Server-Modus zu markieren
    modal.dataset.serverMode = 'true';

    modal.classList.remove('hidden');
    modal.classList.add('visible');
    $('#modal-overlay')?.classList.remove('hidden');

    store.openModal('git-commit-modal');
  }

  async executeServerCommit(message, stageAll = true) {
    try {
      const result = await api.serverGitCommit(message, stageAll);

      if (result.success) {
        this.showToast('Commit erstellt', 'success');
        await this.loadServerGitData();
        return true;
      } else {
        this.showToast(result.error || 'Commit fehlgeschlagen', 'error');
        return false;
      }
    } catch (error) {
      this.showToast(error.message || 'Commit fehlgeschlagen', 'error');
      return false;
    }
  }

  async handleServerBranchChange(e) {
    const branch = e.target.value;
    if (!branch) return;

    try {
      const result = await api.serverGitCheckout(branch);

      if (result.success) {
        this.showToast(`Gewechselt zu ${branch}`, 'success');
        await this.loadServerGitData();
      } else {
        this.showToast(result.error || 'Branch-Wechsel fehlgeschlagen', 'error');
        await this.loadServerGitData();
      }
    } catch (error) {
      this.showToast(error.message || 'Branch-Wechsel fehlgeschlagen', 'error');
      await this.loadServerGitData();
    }
  }

  handleServerCommitListClick(e) {
    const deleteBtn = e.target.closest('.commit-delete');
    if (deleteBtn) {
      const hash = deleteBtn.dataset.hash;
      if (hash) {
        this.hideServerCommit(hash);
      }
    }
  }

  hideServerCommit(hash) {
    this.hiddenServerCommits.add(hash);
    this.renderServerCommits();
    this.showToast('Commit ausgeblendet', 'info');
  }

  clearAllServerCommits() {
    this.serverCommits.forEach(commit => {
      const hash = commit.hash || commit.sha || commit.shortHash;
      if (hash) {
        this.hiddenServerCommits.add(hash);
      }
    });
    this.renderServerCommits();
    this.showToast('Alle Commits ausgeblendet', 'info');
  }

  setServerOperationLoading(operation, loading) {
    const buttonId = `btn-server-${operation}`;
    const button = $(`#${buttonId}`);
    if (button) {
      button.disabled = loading;
      if (loading) {
        button.classList.add('loading');
      } else {
        button.classList.remove('loading');
      }
    }
  }

  // =====================
  // BROWSER-UPLOAD METHODEN
  // =====================

  bindBrowserUploadEvents() {
    // Verzeichnis auswählen
    $('#btn-select-directory')?.addEventListener('click', () => this.handleSelectDirectory());

    // Repository für Upload aktualisieren
    $('#btn-refresh-upload-repos')?.addEventListener('click', () => this.loadBrowserUploadRepos());

    // Upload abbrechen
    $('#btn-cancel-upload')?.addEventListener('click', () => this.cancelBrowserUpload());

    // Upload ausführen
    $('#btn-execute-upload')?.addEventListener('click', () => this.executeBrowserUpload());

    // Drop Zone Events
    const dropZone = $('#drop-zone');
    if (dropZone) {
      dropZone.addEventListener('dragover', (e) => {
        e.preventDefault();
        dropZone.classList.add('drag-over');
      });

      dropZone.addEventListener('dragleave', () => {
        dropZone.classList.remove('drag-over');
      });

      dropZone.addEventListener('drop', (e) => {
        e.preventDefault();
        dropZone.classList.remove('drag-over');
        this.handleDroppedFiles(e.dataTransfer);
      });
    }
  }

  async initBrowserUpload() {
    // Browser-Kompatibilität prüfen
    const compatNotice = $('#browser-upload-compat');
    if (compatNotice) {
      if (!this.supportsDirectoryPicker) {
        compatNotice.classList.remove('hidden');
        // Drop-Zone anzeigen als Alternative
        $('#drop-zone')?.classList.remove('hidden');
      } else {
        compatNotice.classList.add('hidden');
      }
    }

    // Upload-Zustand zurücksetzen
    this.browserUploadFiles = [];
    this.browserUploadSessionId = null;
    this.resetBrowserUploadUI();

    // Repositories laden
    await this.loadBrowserUploadRepos();
  }

  async loadBrowserUploadRepos() {
    const select = $('#browser-upload-repo-select');
    if (!select) return;

    try {
      const result = await api.getGiteaRepositories();
      // API gibt { success, repositories } zurück
      this.giteaRepos = result.repositories || [];

      select.innerHTML = '<option value="">-- Repository wählen --</option>';

      this.giteaRepos.forEach(repo => {
        const option = document.createElement('option');
        // API-Felder: cloneUrl, fullName, owner, name
        option.value = repo.cloneUrl;
        option.textContent = repo.fullName;
        option.dataset.owner = repo.owner || '';
        option.dataset.name = repo.name;
        select.appendChild(option);
      });

      if (this.giteaRepos.length === 0) {
        this.showToast('Keine Repositories gefunden', 'info');
      }
    } catch (error) {
      console.error('[Browser-Upload] Repositories laden fehlgeschlagen:', error);
      this.showToast('Repositories konnten nicht geladen werden', 'error');
    }
  }

  async handleSelectDirectory() {
    if (!this.supportsDirectoryPicker) {
      this.showToast('Verzeichnis-Auswahl wird in diesem Browser nicht unterstützt', 'error');
      return;
    }

    try {
      // File System Access API verwenden
      const dirHandle = await window.showDirectoryPicker({
        mode: 'read'
      });

      this.showToast('Lese Verzeichnis...', 'info');

      // Dateien rekursiv lesen
      const files = await this.readDirectoryRecursive(dirHandle, '');

      if (files.length === 0) {
        this.showToast('Keine Dateien gefunden oder alle wurden ignoriert', 'warning');
        return;
      }

      this.browserUploadFiles = files;
      this.renderUploadPreview();

      this.showToast(`${files.length} Dateien ausgewählt`, 'success');
    } catch (error) {
      if (error.name === 'AbortError') {
        // Benutzer hat abgebrochen
        return;
      }
      console.error('[Browser-Upload] Verzeichnis lesen fehlgeschlagen:', error);
      this.showToast('Verzeichnis konnte nicht gelesen werden', 'error');
    }
  }

  async readDirectoryRecursive(dirHandle, basePath) {
    const files = [];

    for await (const entry of dirHandle.values()) {
      const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;

      // Ignorierte Muster prüfen
      if (this.shouldIgnore(entry.name, relativePath)) {
        continue;
      }

      if (entry.kind === 'file') {
        try {
          const file = await entry.getFile();
          files.push({
            file: file,
            relativePath: relativePath,
            size: file.size
          });
        } catch (err) {
          console.warn(`Datei konnte nicht gelesen werden: ${relativePath}`, err);
        }
      } else if (entry.kind === 'directory') {
        const subFiles = await this.readDirectoryRecursive(entry, relativePath);
        files.push(...subFiles);
      }
    }

    return files;
  }

  shouldIgnore(name, path) {
    // Einfache Muster prüfen
    for (const pattern of this.ignorePatterns) {
      if (pattern.startsWith('*.')) {
        // Wildcard-Muster (z.B. *.log)
        const ext = pattern.substring(1);
        if (name.endsWith(ext)) {
          return true;
        }
      } else if (name === pattern || path.includes(`/${pattern}/`) || path.startsWith(`${pattern}/`)) {
        return true;
      }
    }
    return false;
  }

  async handleDroppedFiles(dataTransfer) {
    const items = dataTransfer.items;
    if (!items || items.length === 0) return;

    const files = [];

    for (const item of items) {
      if (item.kind === 'file') {
        // webkitGetAsEntry für Verzeichnis-Support
        const entry = item.webkitGetAsEntry?.();
        if (entry) {
          const entryFiles = await this.readEntry(entry, '');
          files.push(...entryFiles);
        } else {
          // Fallback: Einzelne Datei
          const file = item.getAsFile();
          if (file && !this.shouldIgnore(file.name, file.name)) {
            files.push({
              file: file,
              relativePath: file.name,
              size: file.size
            });
          }
        }
      }
    }

    if (files.length === 0) {
      this.showToast('Keine Dateien gefunden oder alle wurden ignoriert', 'warning');
      return;
    }

    this.browserUploadFiles = files;
    this.renderUploadPreview();
    this.showToast(`${files.length} Dateien ausgewählt`, 'success');
  }

  async readEntry(entry, basePath) {
    const files = [];
    const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;

    if (this.shouldIgnore(entry.name, relativePath)) {
      return files;
    }

    if (entry.isFile) {
      return new Promise((resolve) => {
        entry.file((file) => {
          resolve([{
            file: file,
            relativePath: relativePath,
            size: file.size
          }]);
        }, () => resolve([]));
      });
    } else if (entry.isDirectory) {
      const reader = entry.createReader();
      return new Promise((resolve) => {
        reader.readEntries(async (entries) => {
          for (const subEntry of entries) {
            const subFiles = await this.readEntry(subEntry, relativePath);
            files.push(...subFiles);
          }
          resolve(files);
        }, () => resolve([]));
      });
    }

    return files;
  }

  renderUploadPreview() {
    const previewSection = $('#upload-preview-section');
    const commitSection = $('#upload-commit-section');
    const filesList = $('#upload-files-list');
    const fileCount = $('#upload-file-count');

    if (!previewSection || !filesList) return;

    // Sektionen anzeigen
    previewSection.classList.remove('hidden');
    commitSection?.classList.remove('hidden');

    // Dateianzahl
    if (fileCount) {
      fileCount.textContent = `${this.browserUploadFiles.length} Dateien`;
    }

    // Dateiliste rendern (max 100 anzeigen)
    const displayFiles = this.browserUploadFiles.slice(0, 100);
    filesList.innerHTML = displayFiles.map(f => `
      <div class="upload-file-item">
        <span class="file-icon">
          <svg viewBox="0 0 24 24" width="16" height="16"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke="currentColor" stroke-width="2" fill="none"/><polyline points="14 2 14 8 20 8" stroke="currentColor" stroke-width="2" fill="none"/></svg>
        </span>
        <span class="file-path">${escapeHtml(f.relativePath)}</span>
        <span class="file-size">${this.formatFileSizeUpload(f.size)}</span>
      </div>
    `).join('');

    if (this.browserUploadFiles.length > 100) {
      filesList.innerHTML += `
        <div class="upload-file-item" style="justify-content: center; color: var(--text-tertiary);">
          ... und ${this.browserUploadFiles.length - 100} weitere Dateien
        </div>
      `;
    }
  }

  formatFileSizeUpload(bytes) {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
  }

  resetBrowserUploadUI() {
    // Vorschau und Commit-Sektion verstecken
    $('#upload-preview-section')?.classList.add('hidden');
    $('#upload-commit-section')?.classList.add('hidden');
    $('#upload-progress-container')?.classList.add('hidden');

    // Felder zurücksetzen
    const commitMessage = $('#browser-upload-commit-message');
    if (commitMessage) commitMessage.value = '';

    const filesList = $('#upload-files-list');
    if (filesList) filesList.innerHTML = '';

    // Progress zurücksetzen
    const progressBar = $('#upload-progress-bar');
    if (progressBar) progressBar.style.width = '0%';

    const progressText = $('#upload-progress-text');
    if (progressText) progressText.textContent = '0%';
  }

  cancelBrowserUpload() {
    this.browserUploadFiles = [];
    this.resetBrowserUploadUI();
    this.showToast('Upload abgebrochen', 'info');
  }

  async executeBrowserUpload() {
    // Validierung
    const repoSelect = $('#browser-upload-repo-select');
    const repoUrl = repoSelect?.value;

    if (!repoUrl) {
      this.showToast('Bitte wählen Sie ein Repository aus', 'error');
      return;
    }

    if (this.browserUploadFiles.length === 0) {
      this.showToast('Keine Dateien ausgewählt', 'error');
      return;
    }

    const commitMessage = $('#browser-upload-commit-message')?.value.trim();
    if (!commitMessage) {
      this.showToast('Bitte geben Sie eine Commit-Nachricht ein', 'error');
      return;
    }

    const branch = $('#browser-upload-branch')?.value || 'main';

    // UI aktualisieren
    const executeBtn = $('#btn-execute-upload');
    const cancelBtn = $('#btn-cancel-upload');
    const progressContainer = $('#upload-progress-container');

    if (executeBtn) {
      executeBtn.disabled = true;
      executeBtn.innerHTML = '<span class="spinner"></span> Lädt hoch...';
    }
    if (cancelBtn) cancelBtn.disabled = true;
    progressContainer?.classList.remove('hidden');

    try {
      // Session vorbereiten
      const prepareResult = await api.prepareBrowserUpload();
      this.browserUploadSessionId = prepareResult.sessionId;

      // Upload durchführen
      const result = await api.browserUploadAndPush({
        files: this.browserUploadFiles,
        repoUrl: repoUrl,
        branch: branch,
        commitMessage: commitMessage,
        sessionId: this.browserUploadSessionId,
        onProgress: (percent) => {
          const progressBar = $('#upload-progress-bar');
          const progressText = $('#upload-progress-text');
          if (progressBar) progressBar.style.width = `${percent}%`;
          if (progressText) progressText.textContent = `${percent}%`;
        }
      });

      if (result.success) {
        this.showToast(`Erfolgreich gepusht: ${result.filesCount} Dateien`, 'success');
        this.cancelBrowserUpload(); // UI zurücksetzen
      } else {
        throw new Error(result.error || 'Upload fehlgeschlagen');
      }
    } catch (error) {
      console.error('[Browser-Upload] Fehler:', error);
      this.showToast(error.message || 'Upload fehlgeschlagen', 'error');
    } finally {
      // UI wiederherstellen
      if (executeBtn) {
        executeBtn.disabled = false;
        executeBtn.innerHTML = `
          <svg viewBox="0 0 24 24" width="18" height="18"><path d="M12 19V5M5 12l7-7 7 7" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
          Commit & Push
        `;
      }
      if (cancelBtn) cancelBtn.disabled = false;
      progressContainer?.classList.add('hidden');

      this.browserUploadSessionId = null;
    }
  }

  // =====================
  // PROJEKT-MODUS METHODEN
  // =====================

  subscribeToStore() {
    // Bei Projektwechsel neu laden
    store.subscribe('currentProjectId', async (projectId) => {
      if (projectId && store.get('currentView') === 'gitea') {
        await this.loadApplication();
      }
    });
  }

  async loadApplication() {
    const projectId = store.get('currentProjectId');

    if (!projectId) {
      this.showNoProjectMessage();
      return;
    }

    this.showLoading();

    try {
      const result = await api.getProjectApplication(projectId);
      this.application = result;

      if (result.configured) {
        await this.loadGitData();
        this.renderConfiguredView();
      } else {
        await this.loadGiteaRepos();
        this.renderConfigurationView();
      }
    } catch (error) {
      console.error('[Gitea] Fehler beim Laden:', error);
      this.showError('Fehler beim Laden der Konfiguration');
    }
  }

  async loadGitData() {
    const projectId = store.get('currentProjectId');

    try {
      const [statusResult, branchesResult, commitsResult] = await Promise.allSettled([
        api.getGitStatus(projectId),
        api.getGitBranches(projectId),
        api.getGitCommits(projectId, 10)
      ]);

      if (statusResult.status === 'fulfilled') {
        this.gitStatus = statusResult.value;
      } else {
        this.gitStatus = null;
        console.error('[Gitea] Status-Fehler:', statusResult.reason);
      }

      if (branchesResult.status === 'fulfilled') {
        this.branches = branchesResult.value.branches || [];
      } else {
        this.branches = [];
      }

      if (commitsResult.status === 'fulfilled') {
        this.commits = commitsResult.value.commits || [];
      } else {
        this.commits = [];
      }

      this.renderStatus();
      this.renderBranches();
      this.renderCommits();
      this.renderChanges();
    } catch (error) {
      console.error('[Gitea] Git-Daten laden fehlgeschlagen:', error);
    }
  }

  async loadGiteaRepos() {
    try {
      const result = await api.testGiteaConnection();
      this.giteaConnected = result.connected;
      this.updateConnectionStatus(result);

      if (this.giteaConnected) {
        const reposResult = await api.getGiteaRepositories();
        this.giteaRepos = reposResult.repositories || [];
        this.populateRepoSelect();
      }
    } catch (error) {
      this.giteaConnected = false;
      this.updateConnectionStatus({ connected: false, error: error.message });
      console.error('[Gitea] Verbindung fehlgeschlagen:', error);
    }
  }

  updateConnectionStatus(result) {
    const statusEl = this.connectionStatus;
    if (!statusEl) return;

    statusEl.classList.remove('connected', 'disconnected');

    if (result.connected) {
      statusEl.classList.add('connected');
      statusEl.querySelector('.status-text').textContent =
        `Verbunden als ${result.user?.login || 'Benutzer'}`;
    } else {
      statusEl.classList.add('disconnected');
      statusEl.querySelector('.status-text').textContent =
        result.error || 'Verbindung fehlgeschlagen';
    }
  }

  populateRepoSelect() {
    const select = $('#gitea-repo-select');
    if (!select) return;

    select.innerHTML = '<option value="">-- Repository wählen --</option>';

    this.giteaRepos.forEach(repo => {
      const option = document.createElement('option');
      option.value = JSON.stringify({
        url: repo.cloneUrl,
        owner: repo.owner,
        name: repo.name,
        fullName: repo.fullName,
        htmlUrl: repo.htmlUrl,
        defaultBranch: repo.defaultBranch
      });
      option.textContent = repo.fullName;
      select.appendChild(option);
    });
  }

  handleRepoSelect(e) {
    const value = e.target.value;
    if (!value) return;

    try {
      const repo = JSON.parse(value);
      $('#default-branch-input').value = repo.defaultBranch || 'main';
    } catch (error) {
      console.error('[Gitea] Fehler beim Parsen des Repository:', error);
    }
  }

  async validateLocalPath(path) {
    const resultEl = $('#path-validation-result');
    if (!resultEl || !path) {
      if (resultEl) {
        resultEl.textContent = '';
        resultEl.className = 'form-hint';
      }
      return;
    }

    try {
      const result = await api.validatePath(path);

      if (result.valid) {
        if (result.isRepository) {
          resultEl.textContent = 'Pfad ist ein Git-Repository';
          resultEl.className = 'form-hint success';
        } else {
          resultEl.textContent = 'Pfad ist erreichbar (kein Git-Repository)';
          resultEl.className = 'form-hint';
        }
      } else {
        resultEl.textContent = 'Pfad nicht erreichbar';
        resultEl.className = 'form-hint error';
      }
    } catch (error) {
      resultEl.textContent = 'Fehler bei der Validierung';
      resultEl.className = 'form-hint error';
    }
  }

  async handleConfigSave(e) {
    e.preventDefault();

    const projectId = store.get('currentProjectId');
    if (!projectId) return;

    const repoSelectValue = $('#gitea-repo-select').value;
    const localPath = $('#local-path-input').value.trim();
    const defaultBranch = $('#default-branch-input').value.trim() || 'main';

    if (!localPath) {
      this.showToast('Bitte geben Sie einen lokalen Pfad an', 'error');
      return;
    }

    let giteaRepoUrl = null;
    let giteaRepoOwner = null;
    let giteaRepoName = null;
    let cloneUrl = null;

    if (repoSelectValue) {
      try {
        const repo = JSON.parse(repoSelectValue);
        giteaRepoUrl = repo.htmlUrl;
        giteaRepoOwner = repo.owner;
        giteaRepoName = repo.name;
        cloneUrl = repo.url; // Clone URL für git remote
      } catch (error) {
        console.error('[Gitea] Fehler beim Parsen des Repository:', error);
      }
    }

    try {
      // 1. Konfiguration speichern
      const result = await api.saveProjectApplication({
        projectId,
        localPath,
        giteaRepoUrl,
        giteaRepoOwner,
        giteaRepoName,
        defaultBranch
      });

      if (result.success) {
        // 2. Repository für Gitea vorbereiten (init, remote setzen)
        if (cloneUrl) {
          this.showToast('Repository wird vorbereitet...', 'info');
          const prepareResult = await api.prepareRepository(projectId, cloneUrl, defaultBranch);

          if (prepareResult.success) {
            this.showToast('Konfiguration gespeichert und Repository vorbereitet', 'success');
          } else {
            this.showToast('Konfiguration gespeichert, aber Repository-Vorbereitung fehlgeschlagen: ' + (prepareResult.error || 'Unbekannter Fehler'), 'warning');
          }
        } else {
          this.showToast('Konfiguration gespeichert', 'success');
        }

        await this.loadApplication();
      } else {
        this.showToast(result.error || 'Fehler beim Speichern', 'error');
      }
    } catch (error) {
      this.showToast(error.message || 'Fehler beim Speichern', 'error');
    }
  }

  async handleRemoveConfig() {
    const projectId = store.get('currentProjectId');
    if (!projectId) return;

    if (!confirm('Möchten Sie die Repository-Konfiguration wirklich entfernen?')) {
      return;
    }

    try {
      await api.deleteProjectApplication(projectId);
      this.showToast('Konfiguration entfernt', 'success');
      await this.loadApplication();
    } catch (error) {
      this.showToast(error.message || 'Fehler beim Entfernen', 'error');
    }
  }

  showConfigSection() {
    this.hideAllSections();
    this.configSection?.classList.remove('hidden');

    // Formular mit aktuellen Werten füllen
    if (this.application?.configured) {
      $('#local-path-input').value = this.application.local_path || '';
      $('#default-branch-input').value = this.application.default_branch || 'main';

      // Repository im Dropdown auswählen falls vorhanden
      if (this.application.gitea_repo_url) {
        const select = $('#gitea-repo-select');
        const options = select?.querySelectorAll('option');
        options?.forEach(option => {
          if (option.value) {
            try {
              const repo = JSON.parse(option.value);
              if (repo.owner === this.application.gitea_repo_owner &&
                  repo.name === this.application.gitea_repo_name) {
                select.value = option.value;
              }
            } catch (e) {}
          }
        });
      }
    }

    this.loadGiteaRepos();
  }

  // Git Operations
  async handleFetch() {
    const projectId = store.get('currentProjectId');
    if (!projectId) return;

    this.setOperationLoading('fetch', true);

    try {
      const result = await api.gitFetch(projectId);
      if (result.success) {
        this.showToast('Fetch erfolgreich', 'success');
        await this.loadGitData();
      } else {
        this.showToast(result.error || 'Fetch fehlgeschlagen', 'error');
      }
    } catch (error) {
      this.showToast(error.message || 'Fetch fehlgeschlagen', 'error');
    } finally {
      this.setOperationLoading('fetch', false);
    }
  }

  async handlePull() {
    const projectId = store.get('currentProjectId');
    if (!projectId) return;

    this.setOperationLoading('pull', true);

    try {
      const branch = $('#branch-select')?.value || null;
      const result = await api.gitPull(projectId, branch);

      if (result.success) {
        this.showToast('Pull erfolgreich', 'success');
        await this.loadGitData();
      } else {
        this.showToast(result.error || 'Pull fehlgeschlagen', 'error');
      }
    } catch (error) {
      this.showToast(error.message || 'Pull fehlgeschlagen', 'error');
    } finally {
      this.setOperationLoading('pull', false);
    }
  }

  handlePush() {
    // Öffne das Push-Modal zur Branch-Auswahl
    this.openPushModal();
  }

  openPushModal() {
    const modal = $('#git-push-modal');
    if (!modal) return;

    // Aktuellen lokalen Branch anzeigen
    const currentBranch = $('#branch-select')?.value || this.gitStatus?.branch || 'unbekannt';
    $('#push-local-branch').textContent = currentBranch;

    // Ziel-Branch zurücksetzen (Standard: gleicher Name wie lokal)
    $('#push-target-branch').value = '';

    modal.classList.remove('hidden');
    modal.classList.add('visible');
    $('#modal-overlay')?.classList.remove('hidden');

    store.openModal('git-push-modal');
  }

  async executePush(e) {
    e.preventDefault();

    const modal = $('#git-push-modal');
    const isServerMode = modal?.dataset.serverMode === 'true';

    // Modal schließen
    modal?.classList.add('hidden');
    modal?.classList.remove('visible');
    $('#modal-overlay')?.classList.add('hidden');
    store.closeModal();

    if (isServerMode) {
      // Server-Modus: Push für Server-Dateien
      delete modal.dataset.serverMode;
      const forcePush = $('#push-force')?.checked || false;
      await this.executeServerPush(forcePush);
    } else {
      // Projekt-Modus: Push für Projekt-Repository
      const projectId = store.get('currentProjectId');
      if (!projectId) return;

      this.setOperationLoading('push', true);

      try {
        const targetBranch = $('#push-target-branch')?.value || null;
        const forcePush = $('#push-force')?.checked || false;
        const localBranch = $('#branch-select')?.value || this.gitStatus?.branch || 'master';

        let result;

        // Wenn ein anderer Target-Branch ausgewählt wurde oder Force-Push, verwende init-push
        if ((targetBranch && targetBranch !== localBranch) || forcePush) {
          const forceText = forcePush ? ' (Force)' : '';
          const branchText = targetBranch && targetBranch !== localBranch
            ? `Push von "${localBranch}" nach "${targetBranch}"${forceText}...`
            : `Push nach "${localBranch}"${forceText}...`;
          this.showToast(branchText, 'info');
          result = await api.gitInitPush(projectId, targetBranch, forcePush);
        } else {
          // Normaler Push (gleicher Branch-Name)
          result = await api.gitPush(projectId, localBranch);

          // Falls Push wegen fehlendem Upstream/Remote fehlschlägt, versuche init-push
          if (!result.success && result.error &&
              (result.error.includes('No configured push destination') ||
               result.error.includes('no upstream') ||
               result.error.includes('Kein Remote'))) {
            this.showToast('Kein Upstream konfiguriert, führe initialen Push durch...', 'info');
            result = await api.gitInitPush(projectId, targetBranch, false);
          }
        }

        if (result.success) {
          const pushedBranch = result.branch || targetBranch || localBranch;
          this.showToast(`Push erfolgreich nach Branch "${pushedBranch}"`, 'success');
          await this.loadGitData();
        } else {
          this.showToast(result.error || 'Push fehlgeschlagen', 'error');
        }
      } catch (error) {
        this.showToast(error.message || 'Push fehlgeschlagen', 'error');
      } finally {
        this.setOperationLoading('push', false);
      }
    }
  }

  openRenameBranchModal() {
    const modal = $('#git-rename-branch-modal');
    if (!modal) return;

    const currentBranch = $('#branch-select')?.value || this.gitStatus?.branch || 'master';
    $('#rename-current-branch').textContent = currentBranch;
    $('#rename-new-branch').value = '';

    modal.classList.remove('hidden');
    modal.classList.add('visible');
    $('#modal-overlay')?.classList.remove('hidden');

    store.openModal('git-rename-branch-modal');

    // Focus auf das Eingabefeld
    setTimeout(() => $('#rename-new-branch')?.focus(), 100);
  }

  async executeRenameBranch(e) {
    e.preventDefault();

    const projectId = store.get('currentProjectId');
    if (!projectId) return;

    const oldName = $('#rename-current-branch')?.textContent;
    const newName = $('#rename-new-branch')?.value.trim();

    if (!newName) {
      this.showToast('Bitte geben Sie einen neuen Branch-Namen ein', 'error');
      return;
    }

    if (oldName === newName) {
      this.showToast('Der neue Name ist identisch mit dem aktuellen', 'error');
      return;
    }

    // Modal schließen
    const modal = $('#git-rename-branch-modal');
    modal?.classList.add('hidden');
    modal?.classList.remove('visible');
    $('#modal-overlay')?.classList.add('hidden');
    store.closeModal();

    try {
      const result = await api.gitRenameBranch(projectId, oldName, newName);

      if (result.success) {
        this.showToast(`Branch umbenannt: "${oldName}" → "${newName}"`, 'success');
        await this.loadGitData();
      } else {
        this.showToast(result.error || 'Umbenennen fehlgeschlagen', 'error');
      }
    } catch (error) {
      this.showToast(error.message || 'Umbenennen fehlgeschlagen', 'error');
    }
  }

  openCommitModal() {
    const modal = $('#git-commit-modal');
    if (!modal) return;

    $('#commit-message').value = '';
    $('#commit-stage-all').checked = true;

    modal.classList.remove('hidden');
    modal.classList.add('visible');
    $('#modal-overlay')?.classList.remove('hidden');

    store.openModal('git-commit-modal');
  }

  async handleCommit(e) {
    e.preventDefault();

    const modal = $('#git-commit-modal');
    const isServerMode = modal?.dataset.serverMode === 'true';

    const message = $('#commit-message')?.value.trim();
    const stageAll = $('#commit-stage-all')?.checked ?? true;

    if (!message) {
      this.showToast('Bitte geben Sie eine Commit-Nachricht ein', 'error');
      return;
    }

    if (isServerMode) {
      // Server-Modus: Commit für Server-Dateien
      const success = await this.executeServerCommit(message, stageAll);
      if (success) {
        this.closeModal('git-commit-modal');
        delete modal.dataset.serverMode;
      }
    } else {
      // Projekt-Modus: Commit für Projekt-Repository
      const projectId = store.get('currentProjectId');
      if (!projectId) return;

      try {
        const result = await api.gitCommit(projectId, message, stageAll);

        if (result.success) {
          this.showToast('Commit erstellt', 'success');
          this.closeModal('git-commit-modal');
          await this.loadGitData();
        } else {
          this.showToast(result.error || 'Commit fehlgeschlagen', 'error');
        }
      } catch (error) {
        this.showToast(error.message || 'Commit fehlgeschlagen', 'error');
      }
    }
  }

  async handleBranchChange(e) {
    const projectId = store.get('currentProjectId');
    const branch = e.target.value;

    if (!projectId || !branch) return;

    try {
      const result = await api.gitCheckout(projectId, branch);

      if (result.success) {
        this.showToast(`Gewechselt zu ${branch}`, 'success');
        await this.loadGitData();
      } else {
        this.showToast(result.error || 'Branch-Wechsel fehlgeschlagen', 'error');
        // Zurück zum vorherigen Branch
        await this.loadGitData();
      }
    } catch (error) {
      this.showToast(error.message || 'Branch-Wechsel fehlgeschlagen', 'error');
      await this.loadGitData();
    }
  }

  openCreateRepoModal() {
    const modal = $('#create-repo-modal');
    if (!modal) return;

    $('#new-repo-name').value = '';
    $('#new-repo-description').value = '';
    $('#new-repo-private').checked = true;

    modal.classList.remove('hidden');
    modal.classList.add('visible');
    $('#modal-overlay')?.classList.remove('hidden');

    store.openModal('create-repo-modal');
  }

  async handleCreateRepo(e) {
    e.preventDefault();

    const name = $('#new-repo-name')?.value.trim();
    const description = $('#new-repo-description')?.value.trim();
    const isPrivate = $('#new-repo-private')?.checked ?? true;

    if (!name) {
      this.showToast('Bitte geben Sie einen Repository-Namen ein', 'error');
      return;
    }

    try {
      const result = await api.createGiteaRepository({
        name,
        description,
        private: isPrivate
      });

      if (result.success) {
        this.showToast('Repository erstellt', 'success');
        this.closeModal('create-repo-modal');
        await this.loadGiteaRepos();

        // Neues Repository im Dropdown auswählen
        const select = $('#gitea-repo-select');
        if (select && result.repository) {
          const option = document.createElement('option');
          option.value = JSON.stringify({
            url: result.repository.cloneUrl,
            owner: result.repository.owner,
            name: result.repository.name,
            fullName: result.repository.fullName,
            htmlUrl: result.repository.htmlUrl,
            defaultBranch: result.repository.defaultBranch
          });
          option.textContent = result.repository.fullName;
          select.appendChild(option);
          select.value = option.value;
        }
      } else {
        this.showToast(result.error || 'Repository-Erstellung fehlgeschlagen', 'error');
      }
    } catch (error) {
      this.showToast(error.message || 'Repository-Erstellung fehlgeschlagen', 'error');
    }
  }

  // Rendering
  renderConfigurationView() {
    this.hideAllSections();
    this.configSection?.classList.remove('hidden');

    // Formular zurücksetzen
    $('#gitea-repo-select').value = '';
    $('#local-path-input').value = '';
    $('#default-branch-input').value = 'main';
    $('#path-validation-result').textContent = '';
  }

  renderConfiguredView() {
    this.hideAllSections();
    this.mainSection?.classList.remove('hidden');

    // Repository-Info
    const repoNameEl = $('#gitea-repo-name span');
    const repoUrlEl = $('#gitea-repo-url');
    const localPathEl = $('#gitea-local-path-display');

    if (this.application) {
      if (this.application.gitea_repo_owner && this.application.gitea_repo_name) {
        repoNameEl.textContent = `${this.application.gitea_repo_owner}/${this.application.gitea_repo_name}`;
      } else {
        repoNameEl.textContent = 'Lokales Repository';
      }

      if (this.application.gitea_repo_url) {
        repoUrlEl.href = this.application.gitea_repo_url;
        repoUrlEl.textContent = this.application.gitea_repo_url;
        repoUrlEl.classList.remove('hidden');
      } else {
        repoUrlEl.classList.add('hidden');
      }

      localPathEl.textContent = this.application.local_path || '-';
    }
  }

  renderStatus() {
    const statusBadge = $('#git-status-indicator');
    const changesCount = $('#git-changes-count');

    if (!this.gitStatus) {
      statusBadge.textContent = 'Fehler';
      statusBadge.className = 'status-badge error';
      changesCount.textContent = '-';
      return;
    }

    // Status Badge
    if (!this.gitStatus.success) {
      statusBadge.textContent = 'Fehler';
      statusBadge.className = 'status-badge error';
    } else if (this.gitStatus.isClean) {
      statusBadge.textContent = 'Sauber';
      statusBadge.className = 'status-badge clean';
    } else if (this.gitStatus.hasChanges) {
      statusBadge.textContent = 'Geändert';
      statusBadge.className = 'status-badge dirty';
    } else {
      statusBadge.textContent = 'OK';
      statusBadge.className = 'status-badge clean';
    }

    // Änderungen
    const changes = this.gitStatus.changes || [];
    changesCount.textContent = changes.length;
  }

  renderBranches() {
    const select = $('#branch-select');
    if (!select) return;

    const currentBranch = this.gitStatus?.branch || 'main';

    select.innerHTML = '';

    // Lokale Branches zuerst
    const localBranches = this.branches.filter(b => !b.isRemote);
    localBranches.forEach(branch => {
      const option = document.createElement('option');
      option.value = branch.name;
      option.textContent = branch.name;
      if (branch.name === currentBranch) {
        option.selected = true;
      }
      select.appendChild(option);
    });
  }

  renderCommits() {
    const listEl = $('#git-commits-list');
    const clearBtn = $('#btn-clear-commits');
    if (!listEl) return;

    // Filtern: Ausgeblendete Commits nicht anzeigen
    const visibleCommits = this.commits.filter(commit => {
      const hash = commit.hash || commit.sha || commit.shortHash;
      return !this.hiddenCommits.has(hash);
    });

    // Button-Text anpassen
    if (clearBtn) {
      clearBtn.style.display = visibleCommits.length > 0 ? '' : 'none';
    }

    if (visibleCommits.length === 0) {
      const message = this.commits.length > 0
        ? 'Alle Commits ausgeblendet'
        : 'Keine Commits gefunden';
      listEl.innerHTML = `<div class="gitea-empty-state" style="padding: var(--spacing-4);"><p>${message}</p></div>`;
      return;
    }

    listEl.innerHTML = visibleCommits.map(commit => {
      const hash = commit.hash || commit.sha || '';
      const shortHash = commit.shortHash || hash.substring(0, 7);
      return `
      <div class="commit-item" data-hash="${escapeHtml(hash)}">
        <span class="commit-hash">${escapeHtml(shortHash)}</span>
        <div class="commit-info">
          <div class="commit-message">${escapeHtml(commit.message?.split('\n')[0] || '')}</div>
          <div class="commit-meta">
            <span class="author">${escapeHtml(commit.author)}</span> · ${this.formatDate(commit.date)}
          </div>
        </div>
        <button class="commit-delete" title="Ausblenden" data-hash="${escapeHtml(hash)}">
          <svg viewBox="0 0 24 24" width="16" height="16"><path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
        </button>
      </div>
    `}).join('');
  }

  handleCommitListClick(e) {
    const deleteBtn = e.target.closest('.commit-delete');
    if (deleteBtn) {
      const hash = deleteBtn.dataset.hash;
      if (hash) {
        this.hideCommit(hash);
      }
    }
  }

  hideCommit(hash) {
    this.hiddenCommits.add(hash);
    this.renderCommits();
    this.showToast('Commit ausgeblendet', 'info');
  }

  clearAllCommits() {
    // Alle sichtbaren Commits ausblenden
    this.commits.forEach(commit => {
      const hash = commit.hash || commit.sha || commit.shortHash;
      if (hash) {
        this.hiddenCommits.add(hash);
      }
    });
    this.renderCommits();
    this.showToast('Alle Commits ausgeblendet', 'info');
  }

  renderChanges() {
    const changesSection = $('#gitea-changes-section');
    const listEl = $('#git-changes-list');

    if (!changesSection || !listEl) return;

    const changes = this.gitStatus?.changes || [];

    if (changes.length === 0) {
      changesSection.classList.add('hidden');
      return;
    }

    changesSection.classList.remove('hidden');

    listEl.innerHTML = changes.map(change => {
      const statusClass = this.getChangeStatusClass(change.status);
      const statusLabel = this.getChangeStatusLabel(change.status);

      return `
        <div class="change-item">
          <span class="change-status ${statusClass}" title="${statusLabel}">${change.status}</span>
          <span class="change-file">${escapeHtml(change.file)}</span>
        </div>
      `;
    }).join('');
  }

  getChangeStatusClass(status) {
    const first = status.charAt(0);
    const second = status.charAt(1);

    if (first === 'M' || second === 'M') return 'modified';
    if (first === 'A' || second === 'A') return 'added';
    if (first === 'D' || second === 'D') return 'deleted';
    if (first === 'R' || second === 'R') return 'renamed';
    if (first === '?' || second === '?') return 'untracked';
    return '';
  }

  getChangeStatusLabel(status) {
    const first = status.charAt(0);
    const second = status.charAt(1);

    if (first === 'M' || second === 'M') return 'Geändert';
    if (first === 'A' || second === 'A') return 'Hinzugefügt';
    if (first === 'D' || second === 'D') return 'Gelöscht';
    if (first === 'R' || second === 'R') return 'Umbenannt';
    if (first === '?' || second === '?') return 'Nicht verfolgt';
    return status;
  }

  formatDate(dateStr) {
    if (!dateStr) return '';

    const date = new Date(dateStr);
    const now = new Date();
    const diffMs = now - date;
    const diffMins = Math.floor(diffMs / 60000);
    const diffHours = Math.floor(diffMs / 3600000);
    const diffDays = Math.floor(diffMs / 86400000);

    if (diffMins < 1) return 'gerade eben';
    if (diffMins < 60) return `vor ${diffMins} Minute${diffMins !== 1 ? 'n' : ''}`;
    if (diffHours < 24) return `vor ${diffHours} Stunde${diffHours !== 1 ? 'n' : ''}`;
    if (diffDays < 7) return `vor ${diffDays} Tag${diffDays !== 1 ? 'en' : ''}`;

    // Lokale Formatierung
    const day = String(date.getDate()).padStart(2, '0');
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const year = date.getFullYear();
    return `${day}.${month}.${year}`;
  }

  // UI Helpers
  hideAllSections() {
    this.noProjectSection?.classList.add('hidden');
    this.configSection?.classList.add('hidden');
    this.mainSection?.classList.add('hidden');
  }

  showNoProjectMessage() {
    this.hideAllSections();
    this.noProjectSection?.classList.remove('hidden');
  }

  showLoading() {
    this.isLoading = true;
  }

  showError(message) {
    this.showToast(message, 'error');
  }

  showToast(message, type = 'info') {
    window.dispatchEvent(new CustomEvent('toast:show', {
      detail: { message, type }
    }));
  }

  closeModal(modalId) {
    const modal = $(`#${modalId}`);
    if (modal) {
      modal.classList.add('hidden');
      modal.classList.remove('visible');
    }
    $('#modal-overlay')?.classList.add('hidden');
    store.closeModal(modalId);
  }

  setOperationLoading(operation, loading) {
    const buttonId = `btn-git-${operation}`;
    const button = $(`#${buttonId}`);
    if (button) {
      button.disabled = loading;
      if (loading) {
        button.classList.add('loading');
      } else {
        button.classList.remove('loading');
      }
    }
  }

  // View Control
  show() {
    this.giteaView?.classList.remove('hidden');
    this.giteaView?.classList.add('active');
    this.updateModeView();
    this.startAutoRefresh();
  }

  hide() {
    this.giteaView?.classList.add('hidden');
    this.giteaView?.classList.remove('active');
    this.stopAutoRefresh();
  }

  startAutoRefresh() {
    this.stopAutoRefresh();
    // Status alle 30 Sekunden aktualisieren
    this.refreshInterval = setInterval(() => {
      if (this.isLoading) return;

      if (this.currentMode === 'server') {
        // Server-Modus: Server-Daten aktualisieren
        this.loadServerGitData();
      } else if (this.application?.configured) {
        // Projekt-Modus: Projekt-Daten aktualisieren
        this.loadGitData();
      }
    }, 30000);
  }

  stopAutoRefresh() {
    if (this.refreshInterval) {
      clearInterval(this.refreshInterval);
      this.refreshInterval = null;
    }
  }
}

const giteaManager = new GiteaManager();
export { giteaManager };
export default giteaManager;
