<script setup lang="ts">
import { computed, ref, type CSSProperties } from "vue";
import { useCompareStage } from "../composables/useCompareStage";
import type { ResultInfo } from "../lib/types";

const props = defineProps<{
  baseImageUrl: string;
  overlayImageUrl: string;
  baseLabel: string;
  baseResolution: string;
  overlayResolution: string;
  emptyMessage: string;
  resultInfo: ResultInfo;
  canDownload: boolean;
  statusTone: string;
}>();

const emit = defineEmits<{
  download: [];
}>();

const compareStageRef = ref<HTMLElement | null>(null);
const hasBaseImage = computed(() => Boolean(props.baseImageUrl));
const hasOverlayImage = computed(() => Boolean(props.overlayImageUrl));
const { handleWheel, preventContextMenu, startCompareDrag, styleVars, zoomLabel, zoomScale } =
  useCompareStage(compareStageRef, hasBaseImage, hasOverlayImage);

const progressFillWidth = computed(() => {
  const progressMatch = props.resultInfo.progress.match(/(\d+(?:\.\d+)?)%/);
  const rawProgress = progressMatch ? Number.parseFloat(progressMatch[1]) : 0;
  const clampedProgress = Number.isFinite(rawProgress) ? Math.min(100, Math.max(0, rawProgress)) : 0;

  const tileMatch = props.resultInfo.tiles.match(/^(\d+)\s*\/\s*(\d+)$/);
  const totalTiles = tileMatch ? Number.parseInt(tileMatch[2], 10) : 0;

  if (totalTiles === 1 && clampedProgress < 100) {
    return `${Math.max(clampedProgress, 33.3333)}%`;
  }

  return `${clampedProgress}%`;
});

const progressFillClass = computed(() => {
  if (props.statusTone === "success") {
    return "bg-emerald-400/80";
  }

  if (props.statusTone === "error") {
    return "bg-rose-400/80";
  }

  if (props.statusTone === "busy") {
    return "bg-amber-400/80";
  }

  return "bg-stone-300/90";
});

const checkerboardBackground = [
  "linear-gradient(45deg, #f0f0f0 25%, transparent 25%) -16px 0 / 32px 32px",
  "linear-gradient(-45deg, #f0f0f0 25%, transparent 25%) -16px 0 / 32px 32px",
  "linear-gradient(45deg, transparent 75%, #f0f0f0 75%) -16px 0 / 32px 32px",
  "linear-gradient(-45deg, transparent 75%, #f0f0f0 75%) -16px 0 / 32px 32px",
  "#fff",
].join(", ");

const compareStageStyle = computed(() => ({
  ...styleVars.value,
  background: checkerboardBackground,
}));

const baseImageStyle = computed<CSSProperties>(() => ({
  transform: "scale(var(--zoom))",
  transformOrigin: "var(--origin-x) var(--origin-y)",
  imageRendering: zoomScale.value > 1 ? "pixelated" : "auto",
}));

const overlayImageStyle = computed<CSSProperties>(() => ({
  ...baseImageStyle.value,
  clipPath: "inset(0 calc(100% - var(--split-adjusted)) 0 0)",
}));

const dividerStyle = {
  left: "calc(var(--split) - 1px)",
  background: "linear-gradient(180deg, transparent, #666 18%, #333 50%, #666 82%, transparent)",
  boxShadow: "0 0 0 1px rgba(0,0,0,0.1), 0 0 12px rgba(0,0,0,0.2)",
};
</script>

<template>
  <section class="flex min-h-0 flex-1 flex-col gap-2">
    <div
      ref="compareStageRef"
      class="relative flex-1 overflow-hidden rounded-xl border border-stone-300 bg-white touch-none"
      :style="compareStageStyle"
      @pointerdown="startCompareDrag"
      @contextmenu="preventContextMenu"
      @wheel="handleWheel"
    >
      <img
        :src="baseImageUrl"
        class="pointer-events-none absolute inset-0 h-full w-full select-none object-contain"
        :style="baseImageStyle"
        :alt="`${baseLabel} image`"
        :hidden="!hasBaseImage"
      />
      <img
        :src="overlayImageUrl"
        class="pointer-events-none absolute inset-0 h-full w-full select-none object-contain"
        :style="overlayImageStyle"
        alt="Upscaled output"
        :hidden="!hasOverlayImage"
      />
      <div
        class="pointer-events-none absolute inset-y-0 w-0.5"
        :style="dividerStyle"
        :hidden="!(hasBaseImage && hasOverlayImage)"
      ></div>

      <div
        class="pointer-events-none absolute left-3 top-3 flex flex-col gap-0.5 rounded-lg border border-stone-300 bg-white/95 px-2.5 py-1.5 text-xs text-stone-600 shadow-sm"
        :hidden="!hasOverlayImage"
      >
        <div class="font-semibold text-stone-800">Upscaled</div>
        <div class="text-[11px] text-stone-500">{{ overlayResolution }}</div>
      </div>

      <div
        class="pointer-events-none absolute right-3 top-3 flex flex-col gap-0.5 rounded-lg border border-stone-300 bg-white/95 px-2.5 py-1.5 text-xs text-stone-600 shadow-sm"
        :hidden="!hasBaseImage"
      >
        <div class="font-semibold text-stone-800">{{ baseLabel }}</div>
        <div class="text-[11px] text-stone-500">{{ baseResolution }}</div>
      </div>

      <div
        class="absolute bottom-3 right-3 min-w-14 rounded-lg border border-stone-300 bg-white/95 px-2.5 py-1.5 text-center text-xs font-medium text-stone-600 shadow-sm"
      >
        {{ zoomLabel }}
      </div>
      <div
        class="absolute inset-0 grid place-items-center bg-white/50 p-8 text-center text-sm text-stone-500"
        :hidden="hasBaseImage"
      >
        {{ emptyMessage }}
      </div>
    </div>

    <div
      class="relative overflow-hidden rounded-xl border border-stone-300 bg-white/85 px-4 py-2.5 text-xs text-stone-700 shadow-sm"
    >
      <div
        :class="[
          'pointer-events-none absolute left-0 top-0 h-2 transition-[width] duration-300',
          progressFillClass,
        ]"
        :style="{ width: progressFillWidth }"
      ></div>

      <div class="relative flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
        <div class="flex flex-wrap gap-x-4 gap-y-2">
          <div class="flex items-center gap-1.5">
            <span class="font-medium text-stone-500">Progress:</span>
            <span class="text-stone-800">{{ resultInfo.progress }}</span>
          </div>
          <div class="flex items-center gap-1.5">
            <span class="font-medium text-stone-500">Tiles:</span>
            <span class="text-stone-800">{{ resultInfo.tiles }}</span>
          </div>
          <div class="flex items-center gap-1.5">
            <span class="font-medium text-stone-500">Avg/tile:</span>
            <span class="text-stone-800">{{ resultInfo.speed }}</span>
          </div>
          <div class="flex items-center gap-1.5">
            <span class="font-medium text-stone-500">Run time:</span>
            <span class="text-stone-800">{{ resultInfo.totalTime }}</span>
          </div>
        </div>

        <div class="flex flex-wrap items-center gap-x-4 gap-y-2">
          <div class="flex items-center gap-1.5">
            <span class="font-medium text-stone-500">Resolution:</span>
            <span class="text-stone-800">{{ resultInfo.resolution }}</span>
          </div>
          <div class="flex items-center gap-1.5">
            <span class="font-medium text-stone-500">Size:</span>
            <span class="text-stone-800">{{ resultInfo.size }}</span>
          </div>
          <button
            type="button"
            class="inline-flex items-center justify-center rounded-md bg-white px-2.5 py-1.5 text-xs font-semibold text-stone-900 ring-1 ring-inset ring-stone-300 transition hover:bg-stone-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-stone-400 disabled:cursor-not-allowed disabled:bg-stone-100 disabled:text-stone-400 disabled:ring-stone-200"
            :disabled="!canDownload"
            @click="emit('download')"
          >
            Download
          </button>
        </div>
      </div>
    </div>
  </section>
</template>
