// ═══════════════════════════════════════════════
//  INIT
// ═══════════════════════════════════════════════

async function initApp() {
  const stored = getAuthToken();
  if (!stored) {
    showAuthScreen();
    return;
  }

  let authOk = false;
  try {
    const res = await apiAuthCheck(stored);
    authOk = !!(res && res.ok);
  } catch (e) {
    if (e && e.status === 401) {
      clearAuthToken();
      showAuthScreen();
      return;
    }
    // Transient failure (network, 5xx): keep the stored token and let the
    // app boot. Any subsequent real 401 from api.js will still trigger
    // auth:required via _handleAuthFailure.
    authOk = true;
  }

  if (!authOk) {
    clearAuthToken();
    showAuthScreen();
    return;
  }

  const ctx = getWorkspaceContext();

  if (!ctx) {
    showProjectSelector();
    return;
  }

  stopLspPolling();
  _lspProfiles = [];

  resetAppState();
  ACTIVE_TERMINAL_KIND = 'claude';

  try {
    const response = await apiGetState(ctx.projectId, ctx.branch);
    const stateData = response.data;

    LOCK_DATA.branch = ctx.branch;
    LOCK_DATA.session_id = stateData.session_id || null;
    LOCK_DATA.working_dir = stateData.working_dir || null;
    LOCK_DATA.sessions = stateData.sessions || [];

    applyStateData(stateData);

    if (LOCK_DATA.locale && LOCK_DATA.locale !== 'en') {
      await loadI18n(LOCK_DATA.locale);
    }
  } catch (e) {
    console.warn('API unavailable, using static data:', e.message);
  }

  try {
    const contextData = await apiGet('/api/ws/' + encodeURIComponent(ctx.projectId) + '/' + encodeURIComponent(ctx.branch) + '/context');
    if (contextData) {
      AppState.context = contextData;
      CONTEXT_DATA = AppState.context;
    }
  } catch (e) {
    console.warn('Context API unavailable:', e.message);
  }

  try {
    const diffData = await apiGetDiff(ctx.projectId, ctx.branch, state.diffSource);
    if (diffData && diffData.files) {
      AppState.diff = diffData;
      DIFF_DATA = AppState.diff;
    }
  } catch (e) {
    console.warn('Diff API unavailable, using static data:', e.message);
  }

  document.getElementById('branchName').textContent = LOCK_DATA.branch || ctx.branch;
  document.getElementById('phaseLabel').textContent = t('phase.label', {phase: state.phase, name: getPhaseName(state.phase)});

  // Update browser tab title with branch name
  if (LOCK_DATA.branch) {
    document.title = LOCK_DATA.branch + ' — Workspace Control';
  } else {
    document.title = 'Workspace Control';
  }

  var localeSelect = document.getElementById('localeSelect');
  if (localeSelect && LOCK_DATA.locale) {
    localeSelect.value = LOCK_DATA.locale;
  }

  var yoloCheck = document.getElementById('yoloCheck');
  if (yoloCheck) yoloCheck.checked = !!LOCK_DATA.yolo_mode;

  if (LOCK_DATA.session_id) {
    var sessionBlock = document.getElementById('sessionBlock');
    if (sessionBlock) {
      sessionBlock.style.display = 'contents';
    }
  }

  loadReviewComments();

  renderPhaseBar('phaseBarControl', 'phaseLabelsControl');
  renderPhaseHistory();
  renderPlan();
  renderScope();
  updatePlanApprovalUI(LOCK_DATA.plan_status || 'pending');
  renderResearch();
  renderPreplanning();
  renderFileList();
  renderPhaseActions();
  renderApprovalStatus();
  renderContext();
  loadVerificationData();
  loadLspProfiles();
  startLspPolling();
  loadCriteria();
  loadGitConfig();
  loadGitRules();
  loadRules();
  loadClaudeCommand();
  loadChannelsPreference();
  loadModulesCard();
  if (typeof renderNetworkMode === 'function') renderNetworkMode();
  if (typeof renderLspShortcutsConfig === 'function') renderLspShortcutsConfig();

  // Restore diff toggle states from localStorage
  document.querySelectorAll('#viewModeToggle .toggle-opt').forEach(function(b) {
    b.classList.toggle('active', b.dataset.mode === state.fileView);
  });
  document.querySelectorAll('#diffModeToggle .toggle-opt').forEach(function(b) {
    b.classList.toggle('active', b.dataset.mode === state.diffMode);
  });
  document.querySelectorAll('#diffSourceToggle .toggle-opt').forEach(function(b) {
    b.classList.toggle('active', b.dataset.mode === state.diffSource);
  });

  hideProjectSelector();
  setupCollapsibleCards();
  _initialLoad = false;

  setInterval(refreshState, 10000);
}

// ═══════════════════════════════════════════════
//  CLIPBOARD HELPERS
// ═══════════════════════════════════════════════

function safeCopyToClipboard(text) {
  if (navigator.clipboard && navigator.clipboard.writeText) {
    return navigator.clipboard.writeText(text).catch(function() {
      return fallbackCopy(text);
    });
  }
  return fallbackCopy(text);
}

function fallbackCopy(text) {
  return new Promise(function(resolve) {
    var textarea = document.createElement('textarea');
    textarea.value = text;
    textarea.style.position = 'fixed';
    textarea.style.left = '-9999px';
    document.body.appendChild(textarea);
    textarea.select();
    try { document.execCommand('copy'); } catch(e) {}
    document.body.removeChild(textarea);
    resolve();
  });
}

function flashButton(btn, text) {
  var original = btn.textContent;
  btn.textContent = text;
  setTimeout(function() { btn.textContent = original; }, 1500);
}

// ═══════════════════════════════════════════════
//  TERMINAL COMMANDS
// ═══════════════════════════════════════════════

function showTerminalDropdown(type, btn) {
  document.querySelectorAll('.btn-dropdown-menu').forEach(function(m) { m.style.display = 'none'; });

  var dropdown = document.getElementById(type + 'Dropdown');
  if (dropdown) {
    dropdown.style.display = dropdown.style.display === 'none' ? 'block' : 'none';
  }

  setTimeout(function() {
    document.addEventListener('click', function closeDropdown(e) {
      if (!e.target.closest('.btn-dropdown')) {
        document.querySelectorAll('.btn-dropdown-menu').forEach(function(m) { m.style.display = 'none'; });
        document.removeEventListener('click', closeDropdown);
      }
    });
  }, 10);
}

function doTerminalAction(endpoint, btnId, mode) {
  doTerminalActionWithKind(endpoint, btnId, mode, 'claude');
}

var ACTIVE_TERMINAL_KIND = 'claude';

function doTerminalActionWithKind(endpoint, btnId, mode, sessionKind) {
  document.querySelectorAll('.btn-dropdown-menu').forEach(function(m) { m.style.display = 'none'; });

  var ctx = getWorkspaceContext();
  if (!ctx) return;

  var btn = document.getElementById(btnId);
  if (btn) btn.disabled = true;

  var body = {};
  if ((sessionKind || 'claude') === 'claude') {
    var channelsEnabled = localStorage.getItem('channels_enabled') === 'true';
    var channelsValue = localStorage.getItem('channels_value') || '';
    if (channelsEnabled && channelsValue) {
      body.channels = channelsValue;
    }
  }

  apiPost('/api/ws/' + encodeURIComponent(ctx.projectId) + '/' + encodeURIComponent(ctx.branch) + '/terminal/' + endpoint, body)
    .then(function(result) {
      ACTIVE_TERMINAL_KIND = result.kind || sessionKind || 'claude';
      if (mode === 'split') {
        var container = document.getElementById('splitContainer');
        if (container && !container.classList.contains('split-active')) {
          toggleSplitTerminal();
        } else if (container && container.classList.contains('split-active')) {
          connectSplitTerminal();
        }
      } else {
        switchTab('terminal');
        setTimeout(function() { connectTerminal(); }, 500);
      }

      if (typeof loadTerminalSessions === 'function') loadTerminalSessions();

      safeCopyToClipboard(result.attach_command).then(function() {
        if (btn) {
          btn.disabled = false;
          flashButton(btn, t('actions.copied'));
        }
      });
    })
    .catch(function(e) {
      if (btn) btn.disabled = false;
      showToast(endpoint.charAt(0).toUpperCase() + endpoint.slice(1) + ' failed: ' + e.message);
    });
}

function doStart(mode) {
  doTerminalActionWithKind('start', 'startBtn', mode, 'claude');
}

function doResume(mode) {
  doTerminalActionWithKind('resume', 'resumeBtn', mode, 'claude');
}

function doNotify(type) {
  document.querySelectorAll('.btn-dropdown-menu').forEach(function(m) { m.style.display = 'none'; });

  var ctx = getWorkspaceContext();
  if (!ctx) return;

  var messages = {
    'comments': 'I left review comments for you to address. Check workspace_get_comments for details.',
    'go': 'You can proceed. Continue with the current task.'
  };

  var message = messages[type] || messages['go'];

  var btn = document.getElementById('notifyBtn');
  if (btn) btn.disabled = true;

  apiPost('/api/ws/' + encodeURIComponent(ctx.projectId) + '/' + encodeURIComponent(ctx.branch) + '/terminal/notify', { message: message })
  .then(function() {
    if (btn) {
      btn.disabled = false;
      flashButton(btn, t('actions.notified'));
    }
  })
  .catch(function(e) {
    if (btn) btn.disabled = false;
    showToast('Notify failed: ' + e.message);
  });
}

function copyWorkspacePath() {
  var workingDir = LOCK_DATA.working_dir;
  if (!workingDir) return;
  var cmd = 'cd ' + workingDir;
  safeCopyToClipboard(cmd).then(function() {
    var btn = document.getElementById('copyPathBtn');
    if (!btn) return;
    flashButton(btn, t('actions.copied'));
  });
}

function onLocaleChange(locale) {
  setLocale(locale);
}

function toggleYoloMode(enabled) {
  var ctx = getWorkspaceContext();
  if (!ctx) return;
  LOCK_DATA.yolo_mode = enabled;
  apiPut('/api/ws/' + encodeURIComponent(ctx.projectId) + '/' + encodeURIComponent(ctx.branch) + '/yolo',
    { enabled: enabled });
}

function setupCollapsibleCards() {
  document.querySelectorAll('.card-header').forEach(function(header) {
    if (header.querySelector('.card-collapse-chevron')) return;

    var chevron = document.createElement('span');
    chevron.className = 'card-collapse-chevron';
    chevron.textContent = '\u25BC';
    header.insertBefore(chevron, header.firstChild);

    header.addEventListener('click', function(e) {
      if (e.target.closest('button, input, select, textarea, .diagram-zoom-controls, .comment-icon, .comment-icon-header, .comment-thread, a')) return;
      this.closest('.card').classList.toggle('collapsed');
    });

    if (!header.closest('.card').classList.contains('card-primary')) {
      header.closest('.card').classList.add('collapsed');
    }
  });
}
