<template>
  <div v-if="show" class="modal-backdrop open" @click.self="closeDialog">
    <div class="modal-container" style="min-width: 600px" ref="modalContentRef" role="dialog" aria-modal="true"
      aria-labelledby="conflictDialogTitle">
      <div class="modal-header">
        <h3 id="conflictDialogTitle">Conflict Resolution</h3>
      </div>
      <div class="modal-body">
        <p class="mb-2">
          This item was modified while you were offline. Please review the changes and choose how to resolve the
          conflict.
        </p>

        <div class="tabs">
          <ul class="tab-list" role="tablist" aria-label="Conflict Resolution Options">
            <li class="tab-item" role="tab" :aria-selected="activeTab === 'compare'"
              :tabindex="activeTab === 'compare' ? 0 : -1" @click="activeTab = 'compare'"
              @keydown.enter.space="activeTab = 'compare'">
              Compare Versions
            </li>
            <li class="tab-item" role="tab" :aria-selected="activeTab === 'merge'"
              :tabindex="activeTab === 'merge' ? 0 : -1" @click="activeTab = 'merge'"
              @keydown.enter.space="activeTab = 'merge'">
              Merge Changes
            </li>
          </ul>

          <div v-if="activeTab === 'compare'" class="tab-content" role="tabpanel" aria-labelledby="tab-compare">
            <div class="flex" style="gap: 1rem;">
              <!-- Local Version -->
              <div class="card flex-grow" style="width: 50%;">
                <div class="card-header">
                  <h4>Your Version</h4>
                </div>
                <div class="card-body">
                  <p class="text-caption mb-1">
                    Last modified: {{ formatDate(conflictData?.localVersion.timestamp ?? 0) }}
                  </p>
                  <ul class="item-list simple-list">
                    <li v-for="(value, key) in conflictData?.localVersion.data" :key="key" class="list-item-simple">
                      <strong class="text-caption-strong">{{ formatKey(key) }}</strong>
                      <span :class="{ 'text-positive-inline': isDifferent(key as string) }">{{ formatValue(value)
                      }}</span>
                    </li>
                  </ul>
                </div>
              </div>

              <!-- Server Version -->
              <div class="card flex-grow" style="width: 50%;">
                <div class="card-header">
                  <h4>Server Version</h4>
                </div>
                <div class="card-body">
                  <p class="text-caption mb-1">
                    Last modified: {{ formatDate(conflictData?.serverVersion.timestamp ?? 0) }}
                  </p>
                  <ul class="item-list simple-list">
                    <li v-for="(value, key) in conflictData?.serverVersion.data" :key="key" class="list-item-simple">
                      <strong class="text-caption-strong">{{ formatKey(key) }}</strong>
                      <span :class="{ 'text-positive-inline': isDifferent(key as string) }">{{ formatValue(value)
                      }}</span>
                    </li>
                  </ul>
                </div>
              </div>
            </div>
          </div>

          <div v-if="activeTab === 'merge'" class="tab-content" role="tabpanel" aria-labelledby="tab-merge">
            <div class="card">
              <div class="card-header">
                <h4>Merge Changes</h4>
              </div>
              <div class="card-body">
                <p class="text-caption mb-2">Select which version to keep for each field.</p>
                <ul class="item-list simple-list">
                  <li v-for="(localValue, key) in conflictData?.localVersion.data" :key="key"
                    class="list-item-simple merge-choice-item">
                    <strong class="text-caption-strong">{{ formatKey(key) }}</strong>
                    <div class="flex" style="gap: 1rem; margin-top: 0.5rem;">
                      <div class="radio-group-inline">
                        <label class="radio-label">
                          <input type="radio" :name="String(key)" v-model="mergeChoices[key]" value="local" />
                          <span class="checkmark radio-mark"></span>
                          Your Version: <span class="value-preview">{{ formatValue(localValue) }}</span>
                        </label>
                      </div>
                      <div class="radio-group-inline">
                        <label class="radio-label">
                          <input type="radio" :name="String(key)" v-model="mergeChoices[key]" value="server" />
                          <span class="checkmark radio-mark"></span>
                          Server Version: <span class="value-preview">{{
                            formatValue(conflictData?.serverVersion.data[key]) }}</span>
                        </label>
                      </div>
                    </div>
                  </li>
                </ul>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="modal-footer">
        <button v-if="activeTab === 'compare'" type="button" class="btn btn-neutral" @click="resolveConflict('local')">
          Keep Local Version
        </button>
        <button v-if="activeTab === 'compare'" type="button" class="btn btn-neutral ml-2"
          @click="resolveConflict('server')">
          Keep Server Version
        </button>
        <button v-if="activeTab === 'compare'" type="button" class="btn btn-primary ml-2" @click="activeTab = 'merge'">
          Merge Changes
        </button>
        <button v-if="activeTab === 'merge'" type="button" class="btn btn-primary ml-2" @click="applyMergedChanges">
          Apply Merged Changes
        </button>
        <button type="button" class="btn btn-danger ml-2" @click="closeDialog">
          Cancel
        </button>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';
import { useVModel, onClickOutside } from '@vueuse/core';
import type { OfflineAction } from '@/stores/offline';

interface ConflictData {
  localVersion: {
    data: Record<string, unknown>;
    timestamp: number;
  };
  serverVersion: {
    data: Record<string, unknown>;
    timestamp: number;
  };
  action: OfflineAction;
}

const props = defineProps<{
  modelValue: boolean;
  conflictData: ConflictData | null;
}>();

const emit = defineEmits<{
  (e: 'update:modelValue', value: boolean): void;
  (e: 'resolve', resolution: { version: 'local' | 'server' | 'merge'; action: OfflineAction; mergedData?: Record<string, unknown> }): void;
}>();

const show = useVModel(props, 'modelValue', emit);
const activeTab = ref('compare');
const mergeChoices = ref<Record<string, 'local' | 'server'>>({});
const modalContentRef = ref<HTMLElement | null>(null);

onClickOutside(modalContentRef, () => {
  if (show.value) {
    // Potentially ask for confirmation before closing or just close
    // closeDialog();
  }
});

const closeDialog = () => {
  show.value = false;
};

watch(() => props.conflictData, (newData) => {
  if (newData) {
    const choices: Record<string, 'local' | 'server'> = {};
    Object.keys(newData.localVersion.data).forEach(key => {
      // Default to local, or server if local is undefined/null but server is not
      if (isDifferent(key)) {
        choices[key] = newData.localVersion.data[key] !== undefined ? 'local' : 'server';
      } else {
        choices[key] = 'local';
      }
    });
    mergeChoices.value = choices;
    activeTab.value = 'compare'; // Reset to compare tab
  }
}, { immediate: true, deep: true });

const formatDate = (timestamp: number): string => {
  if (timestamp === 0) return 'N/A';
  return new Date(timestamp).toLocaleString();
};

const formatKey = (key: string): string => {
  return key
    .replace(/([A-Z])/g, ' $1')
    .replace(/^./, (str) => str.toUpperCase());
};

const formatValue = (value: unknown): string => {
  if (value === null || value === undefined) return '-';
  if (typeof value === 'boolean') return value ? 'Yes' : 'No';
  if (typeof value === 'object') return JSON.stringify(value, null, 2); // Pretty print object
  if (typeof value === 'number' || typeof value === 'string') return String(value);
  return '[Unsupported Type]';
};

const isDifferent = (key: string): boolean => {
  if (!props.conflictData) return false;
  const localValue = props.conflictData.localVersion.data[key];
  const serverValue = props.conflictData.serverVersion.data[key];
  return JSON.stringify(localValue) !== JSON.stringify(serverValue);
};

const resolveConflict = (version: 'local' | 'server'): void => {
  if (!props.conflictData) return;
  emit('resolve', {
    version,
    action: props.conflictData.action,
  });
  closeDialog();
};

const applyMergedChanges = (): void => {
  if (!props.conflictData) return;

  const mergedData: Record<string, unknown> = {};
  Object.entries(mergeChoices.value).forEach(([key, choice]) => {
    mergedData[key] = choice === 'local'
      ? props.conflictData!.localVersion.data[key]
      : props.conflictData!.serverVersion.data[key];
  });

  emit('resolve', {
    version: 'merge',
    action: props.conflictData.action,
    mergedData,
  });
  closeDialog();
};

</script>

<style scoped>
.text-caption {
  font-size: 0.85rem;
  color: var(--dark);
  opacity: 0.8;
}

.text-caption-strong {
  font-size: 0.9rem;
  color: var(--dark);
  font-weight: bold;
  display: block;
  margin-bottom: 0.25rem;
}

.text-positive-inline {
  color: var(--success);
  /* Assuming --success is greenish */
  font-weight: bold;
  background-color: #e6ffed;
  /* Light green background for highlight */
  padding: 2px 4px;
  border-radius: 3px;
}

.simple-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.list-item-simple {
  padding: 0.5rem 0;
  border-bottom: 1px solid #eee;
}

.list-item-simple:last-child {
  border-bottom: none;
}

.merge-choice-item .radio-group-inline {
  margin-bottom: 0.5rem;
}

.merge-choice-item .radio-label {
  align-items: flex-start;
  /* Better alignment for multi-line content */
}

.value-preview {
  font-style: italic;
  color: #555;
  margin-left: 0.5em;
  display: inline-block;
  max-width: 200px;
  /* Adjust as needed */
  white-space: pre-wrap;
  /* Show formatted JSON */
  word-break: break-all;
}

.ml-2 {
  margin-left: 0.5rem;
}

.mb-1 {
  margin-bottom: 0.5rem;
}

.mb-2 {
  margin-bottom: 1rem;
}

.flex-grow {
  flex-grow: 1;
}
</style>