<script lang="ts">
  import { Check, FileDiff, RotateCcw, Undo2 } from "@lucide/svelte";
  import type { FileStatusKind, GitFileStatus, GitStatus } from "../types";

  interface Props {
    changedFiles: GitFileStatus[];
    stagedCount: number;
    unstagedCount: number;
    hasRepository: boolean;
    isBusy: boolean;
    status: GitStatus | null;
    selectedFilePath: string;
    onSelectFile: (file: GitFileStatus) => void;
    onStage: (file: GitFileStatus) => void;
    onUnstage: (file: GitFileStatus) => void;
    onDiscard: (file: GitFileStatus, staged: boolean) => void;
    onPatch: (file: GitFileStatus, staged: boolean) => void;
    onStageAll: () => void;
    onUnstageAll: () => void;
  }

  let {
    changedFiles = [],
    stagedCount = 0,
    unstagedCount = 0,
    hasRepository = false,
    isBusy = false,
    status = null,
    selectedFilePath = "",
    onSelectFile = () => {},
    onStage = () => {},
    onUnstage = () => {},
    onDiscard = () => {},
    onPatch = () => {},
    onStageAll = () => {},
    onUnstageAll = () => {},
  }: Props = $props();

  function statusLabel(kind: FileStatusKind | null): string {
    return kind ?? "none";
  }

  function displayPath(file: GitFileStatus): string {
    return file.old_path ? `${file.old_path} -> ${file.path}` : file.path;
  }

  function baseName(path: string): string {
    return path.split(/[\\/]/).filter(Boolean).pop() ?? path;
  }

  function fileName(file: GitFileStatus): string {
    return file.old_path ? `${baseName(file.old_path)} -> ${baseName(file.path)}` : baseName(file.path);
  }

  function canPatch(kind: FileStatusKind | null): boolean {
    return kind === "modified";
  }

  let hasUnstaged = $derived(changedFiles.some((f) => f.unstaged !== null));
  let hasStaged = $derived(changedFiles.some((f) => f.staged !== null));
</script>

<section class="panel grid grid-rows-[auto_auto_1fr] overflow-hidden" aria-label="Working tree status">
  <div class="section-head">
    <div>
      <span class="eyebrow">Working tree</span>
      <h2 class="mt-0.5 text-ink text-base font-bold leading-tight">Status</h2>
    </div>
    <div class="flex items-center gap-1.5">
      <span class="pill pill-count">{stagedCount} staged</span>
      <span class="pill pill-count">{unstagedCount} unstaged</span>
    </div>
  </div>

  {#if hasRepository && changedFiles.length > 0}
    <div class="status-toolbar">
      <button
        class="btn-sm"
        type="button"
        onclick={onStageAll}
        disabled={isBusy || !hasUnstaged}
        title="Stage all unstaged files"
      >
        <Check size={14} aria-hidden="true" />
        Stage all
      </button>
      <button
        class="btn-sm"
        type="button"
        onclick={onUnstageAll}
        disabled={isBusy || !hasStaged}
        title="Unstage all staged files"
      >
        <Undo2 size={14} aria-hidden="true" />
        Unstage all
      </button>
    </div>
  {/if}

  {#if !hasRepository}
    <div class="blank-state">No repository loaded.</div>
  {:else if status?.clean}
    <div class="blank-state">Working tree is clean.</div>
  {:else if changedFiles.length === 0}
    <div class="blank-state">No file changes returned.</div>
  {:else}
    <div class="overflow-auto p-2">
      {#each changedFiles as file (`${file.old_path ?? ""}:${file.path}`)}
        <article
          class="file-row"
          class:selected={selectedFilePath === file.path}
        >
          <div class="file-title">
            <button
              class="file-title-button"
              type="button"
              onclick={() => onSelectFile(file)}
              title={`Select ${displayPath(file)} in Explorer`}
            >
              <strong>{fileName(file)}</strong>
            </button>
          </div>

          <div class="change-lanes">
            <div class="change-lane" class:inactive={!file.staged}>
              <div class="lane-header">
                <span class="lane-name">Staged</span>
                <span class={`status-badge ${file.staged ?? "none"}`}>{statusLabel(file.staged)}</span>
              </div>
              <div class="lane-actions">
                {#if file.staged}
                  <button class="btn-sm" type="button" onclick={() => onUnstage(file)} disabled={isBusy} title="Unstage file">
                    <Undo2 size={14} aria-hidden="true" />
                    Unstage
                  </button>
                  <button class="btn-sm" type="button" onclick={() => onPatch(file, true)} disabled={isBusy || !canPatch(file.staged)} title="Stage, unstage, or discard selected lines">
                    <FileDiff size={14} aria-hidden="true" />
                    Details
                  </button>
                  <button class="btn-sm" type="button" onclick={() => onDiscard(file, true)} disabled={isBusy} title="Discard staged changes">
                    <RotateCcw size={14} aria-hidden="true" />
                    Discard
                  </button>
                {:else}
                  <span class="quiet">No staged change</span>
                {/if}
              </div>
            </div>

            <div class="change-lane" class:inactive={!file.unstaged}>
              <div class="lane-header">
                <span class="lane-name">Unstaged</span>
                <span class={`status-badge ${file.unstaged ?? "none"}`}>{statusLabel(file.unstaged)}</span>
              </div>
              <div class="lane-actions">
                {#if file.unstaged}
                  <button class="btn-sm" type="button" onclick={() => onStage(file)} disabled={isBusy} title="Stage file">
                    <Check size={14} aria-hidden="true" />
                    Stage
                  </button>
                  <button class="btn-sm" type="button" onclick={() => onPatch(file, false)} disabled={isBusy || !canPatch(file.unstaged)} title="Stage or discard selected lines">
                    <FileDiff size={14} aria-hidden="true" />
                    Details
                  </button>
                  <button class="btn-sm" type="button" onclick={() => onDiscard(file, false)} disabled={isBusy} title="Discard unstaged changes">
                    <RotateCcw size={14} aria-hidden="true" />
                    Discard
                  </button>
                {:else}
                  <span class="quiet">No unstaged change</span>
                {/if}
              </div>
            </div>
          </div>
        </article>
      {/each}
    </div>
  {/if}
</section>
