<template>
  <div class="flex h-full flex-col border-t border-zinc-800">
    <!-- en-tête + actions distantes -->
    <div class="flex items-center gap-1 px-2 py-1 text-[11px] font-semibold uppercase tracking-wide text-zinc-500">
      <GitCompare :size="13" /> {{ t('workspace.changes') }}
      <span v-if="git.ahead" class="text-emerald-500">↑{{ git.ahead }}</span>
      <span v-if="git.behind" class="text-amber-500">↓{{ git.behind }}</span>
      <span class="ml-auto flex items-center gap-1">
        <button type="button" class="rounded p-0.5 hover:bg-zinc-800 hover:text-zinc-300 disabled:opacity-40" :title="t('commit.fetch')" :disabled="!!busy" @click="onFetch"><Download :size="13" /></button>
        <button type="button" class="rounded p-0.5 hover:bg-zinc-800 hover:text-zinc-300 disabled:opacity-40" :title="t('commit.pull')" :disabled="!!busy" @click="onPull('ff-only')"><ArrowDownToLine :size="13" /></button>
      </span>
    </div>

    <div class="min-h-0 flex-1 overflow-auto">
      <!-- fichiers indexés (staged) -->
      <div v-if="staged.length" class="px-1">
        <div class="flex items-center px-1 py-0.5 text-[11px] text-zinc-500">
          {{ t('commit.staged') }} ({{ staged.length }})
          <button type="button" class="ml-auto rounded px-1 hover:bg-zinc-800 hover:text-zinc-300 disabled:opacity-40" :disabled="!!busy" @click="onUnstageAll">{{ t('commit.unstageAll') }}</button>
        </div>
        <FileRow v-for="c in staged" :key="`s-${c.path}`" :c="c" :active="active === c.path" staged @select="select(c, true)">
          <button type="button" class="rounded p-0.5 hover:bg-zinc-700" :title="t('commit.unstage')" :disabled="!!busy" @click.stop="onUnstage(c)"><Minus :size="13" /></button>
        </FileRow>
      </div>

      <!-- changements non indexés / non suivis -->
      <div class="px-1">
        <div class="flex items-center px-1 py-0.5 text-[11px] text-zinc-500">
          {{ t('commit.changes') }} ({{ unstaged.length }})
          <button v-if="unstaged.length" type="button" class="ml-auto rounded px-1 hover:bg-zinc-800 hover:text-zinc-300 disabled:opacity-40" :disabled="!!busy" @click="onStageAll">{{ t('commit.stageAll') }}</button>
        </div>
        <p v-if="unstaged.length === 0 && staged.length === 0" class="px-2 py-1 text-xs text-zinc-600">{{ t('workspace.noChanges') }}</p>
        <FileRow v-for="c in unstaged" :key="`u-${c.path}`" :c="c" :active="active === c.path" @select="select(c, false)">
          <button v-if="discardArmed === c.path" type="button" class="rounded p-0.5 text-rose-300 hover:bg-rose-900/40" :title="t('commit.confirmDiscard')" :disabled="!!busy" @click.stop="onDiscard(c)"><Check :size="13" /></button>
          <button v-else type="button" class="rounded p-0.5 hover:bg-zinc-700" :title="t('commit.discard')" :disabled="!!busy" @click.stop="discardArmed = c.path"><Undo2 :size="13" /></button>
          <button type="button" class="rounded p-0.5 hover:bg-zinc-700" :title="t('commit.stage')" :disabled="!!busy" @click.stop="onStage(c)"><Plus :size="13" /></button>
        </FileRow>
      </div>
      <p v-if="truncated" class="px-2 py-1 text-[11px] text-amber-500">{{ t('workspace.changesTruncated') }}</p>
    </div>

    <!-- zone de commit -->
    <div class="flex flex-col gap-1 border-t border-zinc-800 p-2">
      <textarea
        v-model="message"
        rows="2"
        class="input resize-none text-xs"
        :placeholder="amend ? t('commit.amendPlaceholder') : t('commit.messagePlaceholder')"
      />
      <label class="flex items-center gap-1 text-[11px] text-zinc-400">
        <input v-model="amend" type="checkbox" /> {{ t('commit.amend') }}
      </label>
      <div class="flex items-center gap-2">
        <BaseButton size="sm" variant="primary" :icon="Check" :loading="busy === 'commit'" :disabled="!canCommit" @click="onCommit">
          {{ t('commit.commit') }}
        </BaseButton>
        <BaseButton size="sm" :icon="Upload" :loading="busy === 'push'" :disabled="!!busy || !canPush" @click="onPush">
          {{ t('commit.push') }}<span v-if="git.ahead"> ↑{{ git.ahead }}</span>
        </BaseButton>
        <BaseButton v-if="canRebase" size="sm" variant="ghost" :loading="busy === 'rebase'" @click="onPull('rebase')">{{ t('commit.pullRebase') }}</BaseButton>
      </div>
      <p v-if="error" class="text-[11px] text-amber-400">{{ error }}</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { ArrowDownToLine, Check, Download, GitCompare, Minus, Plus, Undo2, Upload } from '@lucide/vue';
import type { FileChange, WorktreeGitStatus, WorktreeSummary } from '@arboretum/shared';
import { gitApi } from '../../lib/git-api';
import { ApiError } from '../../lib/api';
import { useWorktreesStore } from '../../stores/worktrees';
import BaseButton from '../ui/BaseButton.vue';
import FileRow from './FileRow.vue';

const props = defineProps<{ repoId: string; wt: string; changes: FileChange[]; git: WorktreeGitStatus; truncated: boolean; active: string | null }>();
const emit = defineEmits<{ select: [sel: { file: string; staged: boolean }]; changed: [] }>();
const { t } = useI18n();
const store = useWorktreesStore();

const staged = computed(() => props.changes.filter((c) => c.staged));
const unstaged = computed(() => props.changes.filter((c) => c.unstaged || c.untracked));

const message = ref('');
const amend = ref(false);
const busy = ref<string | null>(null);
const error = ref<string | null>(null);
const discardArmed = ref<string | null>(null);
const canRebase = ref(false);

const canCommit = computed(() => !busy.value && staged.value.length > 0 && (amend.value || message.value.trim() !== ''));
const canPush = computed(() => !!props.git && props.git.behind === 0); // push simple (ff) ; le serveur gère l'upstream

function select(c: FileChange, stagedSide: boolean): void {
  emit('select', { file: c.path, staged: stagedSide });
}

// Exécute une mutation git, applique le worktree renvoyé (header live) et signale le changement.
async function run(key: string, fn: () => Promise<{ worktree: WorktreeSummary }>): Promise<void> {
  if (busy.value) return;
  busy.value = key;
  error.value = null;
  try {
    const res = await fn();
    store.applyWorktree(res.worktree);
    emit('changed');
  } catch (err) {
    error.value = err instanceof Error ? err.message : String(err);
    throw err;
  } finally {
    busy.value = null;
  }
}

const onStage = (c: FileChange) => run(`stage:${c.path}`, () => gitApi.stage(props.repoId, props.wt, [c.path]));
const onUnstage = (c: FileChange) => run(`unstage:${c.path}`, () => gitApi.unstage(props.repoId, props.wt, [c.path]));
const onStageAll = () => run('stageAll', () => gitApi.stage(props.repoId, props.wt, unstaged.value.map((c) => c.path)));
const onUnstageAll = () => run('unstageAll', () => gitApi.unstage(props.repoId, props.wt, staged.value.map((c) => c.path)));
const onFetch = () => run('fetch', () => gitApi.fetch(props.repoId, props.wt)).catch(() => {});

async function onDiscard(c: FileChange): Promise<void> {
  discardArmed.value = null;
  await run(`discard:${c.path}`, () => gitApi.discard(props.repoId, props.wt, [c.path], c.untracked)).catch(() => {});
}

async function onCommit(): Promise<void> {
  try {
    await run('commit', () => gitApi.commit(props.repoId, props.wt, message.value.trim(), { mode: 'staged', amend: amend.value }));
    message.value = '';
    amend.value = false;
  } catch (err) {
    if (err instanceof ApiError && err.code === 'ALREADY_PUSHED') error.value = t('commit.alreadyPushed');
  }
}

const onPush = () => run('push', () => store.pushWorktree(props.repoId, props.wt).then((worktree) => ({ worktree }))).catch(() => {});

async function onPull(mode: 'ff-only' | 'rebase'): Promise<void> {
  canRebase.value = false;
  try {
    await run(mode === 'rebase' ? 'rebase' : 'pull', () => gitApi.pull(props.repoId, props.wt, mode));
  } catch {
    if (mode === 'ff-only') canRebase.value = true; // ff impossible (divergence) → proposer le rebase
  }
}
</script>
