<script setup lang="ts">
import { computed, ref } from "vue";
import { Head, router } from "@inertiajs/vue3";
import { RotateCcw } from "lucide-vue-next";
import Button from "../../components/ui/Button.vue";
import Dialog from "../../components/ui/Dialog.vue";
import DialogScrollContent from "../../components/ui/DialogScrollContent.vue";
import DialogHeader from "../../components/ui/DialogHeader.vue";
import DialogTitle from "../../components/ui/DialogTitle.vue";
import DialogDescription from "../../components/ui/DialogDescription.vue";
import DialogFooter from "../../components/ui/DialogFooter.vue";
import PageHeader from "../../components/PageHeader.vue";
import RevisionDiffTable from "../../components/RevisionDiffTable.vue";
import { useTranslations } from "../../composables/useTranslations";
import { useBuilderPrefix } from "../../composables/useBuilderPrefix";
import { formatDateTime } from "../../utils/formatDate";

type DiffEntry = { old: unknown; new: unknown };
type TranslationDiff = Record<string, Record<string, DiffEntry>>;
type MediaDiff = Record<string, { old: number[]; new: number[] }>;

type BlockGranularEntry =
  | {
      action: "added" | "removed";
      position: number;
      key: string;
      data: Record<string, unknown>;
      media: Record<string, number[]>;
    }
  | {
      action: "modified";
      position: number;
      key: string;
      data_diff: Record<string, DiffEntry>;
      media_diff: Record<string, { old: number[]; new: number[] }>;
    };

type BlockGranularDiff = Record<string, BlockGranularEntry[]>;
type TranslationBlockGranularDiff = Record<string, BlockGranularDiff>;

type RevisionEntry = {
  id: number;
  created_at: string | null;
  user_name: string | null;
  diff: Record<string, DiffEntry>;
  translation_diff: TranslationDiff;
  block_granular_diff: BlockGranularDiff;
  translation_block_granular_diff: TranslationBlockGranularDiff;
  media_diff: MediaDiff;
  field_labels: Record<string, string>;
  media_names: Record<number, string>;
  block_labels: Record<string, string>;
  block_field_labels: Record<string, Record<string, string>>;
  is_restored: boolean;
  restored_from_id: number | null;
};

const props = defineProps<{
  resource: {
    slug: string;
    label: string;
    singularLabel: string;
  };
  record: Record<string, unknown>;
  record_id: number | string;
  revisions: RevisionEntry[];
  back_url: string;
}>();

const { t } = useTranslations();
const prefix = useBuilderPrefix();

const selectedIndex = ref(0);
const confirmRestoreOpen = ref(false);
const restoring = ref(false);

const selectedRevision = computed<RevisionEntry | null>(
  () => props.revisions[selectedIndex.value] ?? null,
);

const isInitialRevision = computed(
  () => selectedIndex.value === props.revisions.length - 1,
);

function revisionChangeCount(revision: RevisionEntry): number {
  const blockCount = Object.values(revision.block_granular_diff).reduce(
    (sum, entries) => sum + entries.length,
    0,
  );
  const translationBlockCount = Object.values(
    revision.translation_block_granular_diff,
  ).reduce(
    (sum, localeDiff) =>
      sum +
      Object.values(localeDiff).reduce((s, entries) => s + entries.length, 0),
    0,
  );

  return (
    Object.keys(revision.diff).length +
    Object.values(revision.translation_diff).reduce(
      (sum, ld) => sum + Object.keys(ld).length,
      0,
    ) +
    blockCount +
    translationBlockCount +
    Object.keys(revision.media_diff).length
  );
}

function restoreUrl(revision: RevisionEntry): string {
  return `/${prefix}/${props.resource.slug}/${props.record_id}/revisions/${revision.id}/restore`;
}

function confirmRestore(): void {
  confirmRestoreOpen.value = true;
}

function executeRestore(): void {
  if (!selectedRevision.value) {
    return;
  }
  restoring.value = true;
  router.post(
    restoreUrl(selectedRevision.value),
    {},
    {
      onFinish: () => {
        restoring.value = false;
        confirmRestoreOpen.value = false;
      },
    },
  );
}
</script>

<template>
  <Head :title="t('builder.revisions.title')" />

  <PageHeader
    :title="t('builder.revisions.title')"
    :back-href="back_url"
    :back-label="t('builder.revisions.back_to_edit')"
  />

  <div
    v-if="revisions.length === 0"
    class="text-sm text-muted-foreground py-8 text-center"
  >
    {{ t("builder.revisions.no_revisions") }}
  </div>

  <div
    v-else
    class="grid grid-cols-[280px_1fr] gap-0 border rounded-lg overflow-hidden"
  >
    <!-- Timeline sidebar -->
    <div class="border-r overflow-y-auto max-h-[calc(100vh-14rem)]">
      <button
        v-for="(revision, index) in revisions"
        :key="revision.id"
        class="w-full text-left px-4 py-3 border-b last:border-0 hover:bg-muted/50 transition-colors"
        :class="{ 'bg-muted': selectedIndex === index }"
        @click="selectedIndex = index"
      >
        <div class="flex items-center justify-between gap-2">
          <span class="text-xs font-medium truncate">
            {{ formatDateTime(revision.created_at) }}
          </span>
          <span
            v-if="index === 0"
            class="text-[10px] px-1.5 py-0.5 rounded bg-primary/10 text-primary shrink-0"
          >
            {{ t("builder.revisions.current") }}
          </span>
        </div>
        <div class="text-xs text-muted-foreground mt-0.5 truncate">
          {{ revision.user_name ?? t("builder.revisions.system") }}
        </div>
        <div
          v-if="revision.is_restored"
          class="text-xs text-amber-600 dark:text-amber-400 mt-0.5 truncate"
        >
          {{
            t("builder.revisions.restored_from", {
              id: revision.restored_from_id,
            })
          }}
        </div>
        <div
          v-else-if="index !== revisions.length - 1"
          class="text-xs text-muted-foreground mt-0.5"
        >
          {{
            t("builder.revisions.changes", {
              count: revisionChangeCount(revision),
            })
          }}
        </div>
      </button>
    </div>

    <!-- Diff panel -->
    <div class="p-6 overflow-y-auto max-h-[calc(100vh-14rem)]">
      <template v-if="selectedRevision">
        <div class="flex items-start justify-between gap-4 mb-6">
          <div>
            <h2 class="text-base font-semibold">
              {{ formatDateTime(selectedRevision.created_at) }}
            </h2>
            <p class="text-sm text-muted-foreground mt-0.5">
              {{ t("builder.revisions.saved_by") }}
              {{ selectedRevision.user_name ?? t("builder.revisions.system") }}
            </p>
          </div>
          <Button
            v-if="selectedIndex !== 0"
            variant="outline"
            size="sm"
            :disabled="restoring"
            @click="confirmRestore"
          >
            <RotateCcw class="w-3.5 h-3.5 mr-1.5" />
            {{ t("builder.revisions.restore") }}
          </Button>
        </div>

        <p v-if="isInitialRevision" class="text-sm text-muted-foreground">
          {{ t("builder.revisions.initial") }}
        </p>
        <RevisionDiffTable
          v-else
          :diff="selectedRevision.diff"
          :translation-diff="selectedRevision.translation_diff"
          :block-granular-diff="selectedRevision.block_granular_diff"
          :translation-block-granular-diff="
            selectedRevision.translation_block_granular_diff
          "
          :media-diff="selectedRevision.media_diff"
          :field-labels="selectedRevision.field_labels"
          :media-names="selectedRevision.media_names"
          :block-labels="selectedRevision.block_labels"
          :block-field-labels="selectedRevision.block_field_labels"
        />
      </template>
    </div>
  </div>

  <!-- Restore confirmation dialog -->
  <Dialog v-model:open="confirmRestoreOpen">
    <DialogScrollContent>
      <DialogHeader>
        <DialogTitle>{{ t("builder.revisions.restore") }}</DialogTitle>
        <DialogDescription>
          {{ t("builder.revisions.confirm_restore") }}
        </DialogDescription>
      </DialogHeader>
      <DialogFooter>
        <Button variant="outline" @click="confirmRestoreOpen = false">
          {{ t("builder.resources.cancel") }}
        </Button>
        <Button :disabled="restoring" @click="executeRestore">
          {{ t("builder.revisions.restore") }}
        </Button>
      </DialogFooter>
    </DialogScrollContent>
  </Dialog>
</template>
