<script setup>
import { ref, computed, onMounted } from 'vue'
import { useTranslation } from 'i18next-vue'
import ModalDialog from './ModalDialog.vue'
import { useJsonImport, COLLISION_ACTION } from '../composables/useJsonImport.js'

const props = defineProps({
  envelope: { type: Object, required: true },
  localUuid: { type: String, required: true },
  asMine: { type: Boolean, default: false },
})

const emit = defineEmits(['close', 'done'])

const { t } = useTranslation()
const { analyzeAll, applyAllImport } = useJsonImport()

// State machine: 'loading' | 'suffix' | 'preview' | 'collisions' | 'applying' | 'report'
const step = ref('loading')
const analysis = ref(null)
const applying = ref(false)
const report = ref(null)

// Suffix input for different-user imports
const suffixInput = ref('')
const suffixError = ref('')

// Collision resolutions per entity type (also receives cross-user title-conflict
// resolutions once they're discovered in onApply — see crossUserConflictsChecked)
const exerciseResolutions = ref([])
const comboResolutions = ref([])
const sessionResolutions = ref([])
const collectionResolutions = ref([])

// Guards against re-running findTitleConflicts after the user has already resolved them
const crossUserConflictsChecked = ref(false)

const summary = computed(() => analysis.value?.summary || {})

const totalEntityCount = computed(() => {
  let count = 0
  if (analysis.value?.exercises) count += analysis.value.exercises.total
  if (analysis.value?.combos) count += analysis.value.combos.total
  if (analysis.value?.sessions) count += analysis.value.sessions.total
  if (analysis.value?.collections) count += analysis.value.collections.total
  if (analysis.value?.executionLogs) count += analysis.value.executionLogs.total
  return count
})

// Derived from the resolution refs directly (not from `analysis`) so it stays correct
// whether resolutions came from same-user id/title collisions or cross-user title conflicts.
const hasCollisions = computed(() => totalCollisions.value > 0)

const totalCollisions = computed(
  () =>
    exerciseResolutions.value.length +
    comboResolutions.value.length +
    sessionResolutions.value.length +
    collectionResolutions.value.length,
)

onMounted(async () => {
  analysis.value = await analyzeAll(props.envelope, { asMine: props.asMine })
  const a = analysis.value

  if (a.summary.isSameUser) {
    // Initialize collision resolutions (id and title conflicts are both bucketed
    // into sameUserCollisions by useJsonImport.js)
    if (a.exercises?.sameUserCollisions?.length) {
      exerciseResolutions.value = a.exercises.sameUserCollisions.map((c) => ({
        ...c,
        action: COLLISION_ACTION.SKIP,
      }))
    }
    if (a.combos?.sameUserCollisions?.length) {
      comboResolutions.value = a.combos.sameUserCollisions.map((c) => ({
        ...c,
        action: COLLISION_ACTION.SKIP,
      }))
    }
    if (a.sessions?.sameUserCollisions?.length) {
      sessionResolutions.value = a.sessions.sameUserCollisions.map((c) => ({
        ...c,
        action: COLLISION_ACTION.SKIP,
      }))
    }
    if (a.collections?.sameUserCollisions?.length) {
      collectionResolutions.value = a.collections.sameUserCollisions.map((c) => ({
        ...c,
        action: COLLISION_ACTION.SKIP,
      }))
    }
    step.value = hasCollisions.value ? 'collisions' : 'preview'
  } else {
    if (a.suffixInfo?.needsSuffix) {
      suffixInput.value = a.summary.exporterName
      step.value = 'suffix'
    } else {
      step.value = 'preview'
    }
  }
})

// --- Actions ---

/**
 * Check title conflicts for a list of different-user entities against existing data.
 * Returns the matched existing row alongside the entry so the caller can offer
 * Replace/Skip against it (same as same-user collisions) instead of forcing a rename.
 */
async function findTitleConflicts(entries, entityType, titleField, suffix, getAll) {
  if (!entries?.length) return []
  const allEntities = await getAll()
  const conflicts = []
  for (const entry of entries) {
    const suffixedTitle = `${entry.imported[titleField]} [${suffix}]`
    if (entry.action === 'update' && entry.existing?.[titleField] === suffixedTitle) continue
    const conflict = allEntities.find(
      (e) => e[titleField] === suffixedTitle && e.id !== entry.imported.id,
    )
    if (conflict) {
      conflicts.push({ entity: entityType, entry, existing: conflict })
    }
  }
  return conflicts
}

async function onApply() {
  applying.value = true
  step.value = 'applying'

  try {
    const a = analysis.value

    // For different-user imports, check title conflicts (on the suffixed title) once,
    // before applying. Found conflicts are folded into the same resolution arrays used
    // for same-user collisions, so the existing Replace/Skip screen handles them too.
    if (!a.summary.isSameUser && !crossUserConflictsChecked.value) {
      crossUserConflictsChecked.value = true
      const suffix = a.suffixInfo?.existingSuffix || suffixInput.value.trim()

      const [exConflicts, coConflicts, seConflicts, clConflicts] = await Promise.all([
        findTitleConflicts(a.exercises?.differentUser, 'exercise', 'title', suffix, async () => {
          const { exerciseRepository } = await import('../db/repositories/exerciseRepository.js')
          return exerciseRepository.getAll()
        }),
        findTitleConflicts(a.combos?.differentUser, 'combo', 'title', suffix, async () => {
          const { comboRepository } = await import('../db/repositories/comboRepository.js')
          return comboRepository.getAll()
        }),
        findTitleConflicts(a.sessions?.differentUser, 'session', 'title', suffix, async () => {
          const { sessionRepository } = await import('../db/repositories/sessionRepository.js')
          return sessionRepository.getAll()
        }),
        findTitleConflicts(
          a.collections?.differentUser,
          'collection',
          'label',
          suffix,
          async () => {
            const { collectionRepository } =
              await import('../db/repositories/collectionRepository.js')
            return collectionRepository.getAll()
          },
        ),
      ])

      const conflicts = [...exConflicts, ...coConflicts, ...seConflicts, ...clConflicts]

      if (conflicts.length > 0) {
        for (const conflict of conflicts) {
          const resolutions = getResolutionsForType(conflict.entity)
          resolutions.value.push({
            imported: conflict.entry.imported,
            existing: conflict.existing,
            action: COLLISION_ACTION.SKIP,
          })
        }
        step.value = 'collisions'
        applying.value = false
        return
      }
    }

    // Apply import
    report.value = await applyAllImport(analysis.value, {
      suffix: analysis.value.suffixInfo?.existingSuffix || suffixInput.value.trim(),
      exerciseResolutions: exerciseResolutions.value,
      comboResolutions: comboResolutions.value,
      sessionResolutions: sessionResolutions.value,
      collectionResolutions: collectionResolutions.value,
    })

    step.value = 'report'
  } catch (e) {
    report.value = {
      exercises: { imported: 0, skipped: 0, replaced: 0, updated: 0 },
      combos: { imported: 0, skipped: 0, replaced: 0, updated: 0 },
      sessions: { imported: 0, skipped: 0, replaced: 0, updated: 0 },
      collections: { imported: 0, skipped: 0, replaced: 0, updated: 0 },
      executionLogs: { imported: 0, skipped: 0 },
      settings: { imported: 0 },
      errors: [e.message],
    }
    step.value = 'report'
  } finally {
    applying.value = false
  }
}

async function onConfirmSuffix() {
  const trimmed = suffixInput.value.trim()
  if (!trimmed) {
    suffixError.value = t('import.suffixRequired')
    return
  }

  const { suffixRepository } = await import('../db/repositories/suffixRepository.js')
  const existing = await suffixRepository.getBySuffix(trimmed)
  if (existing && existing.user_uuid !== analysis.value.summary.exporterUuid) {
    suffixError.value = t('import.suffixTaken')
    return
  }

  suffixError.value = ''
  step.value = 'preview'
}

function setAllCollisions(entityType, action) {
  const resolutions = getResolutionsForType(entityType)
  resolutions.value = resolutions.value.map((c) => ({ ...c, action }))
}

function setCollisionAction(entityType, index, action) {
  const resolutions = getResolutionsForType(entityType)
  resolutions.value[index] = { ...resolutions.value[index], action }
}

function getResolutionsForType(entityType) {
  switch (entityType) {
    case 'exercise':
      return exerciseResolutions
    case 'combo':
      return comboResolutions
    case 'session':
      return sessionResolutions
    case 'collection':
      return collectionResolutions
    default:
      return { value: [] }
  }
}

function onDone() {
  emit('done', report.value)
}

function formatDate(isoString) {
  try {
    return new Date(isoString).toLocaleDateString()
  } catch {
    return isoString
  }
}

const totalImported = computed(() => {
  if (!report.value) return 0
  let count = 0
  for (const key of ['exercises', 'combos', 'sessions', 'collections', 'executionLogs']) {
    const r = report.value[key]
    if (r) {
      count += (r.imported || 0) + (r.replaced || 0) + (r.updated || 0)
    }
  }
  return count
})

const totalSkipped = computed(() => {
  if (!report.value) return 0
  let count = 0
  for (const key of ['exercises', 'combos', 'sessions', 'collections', 'executionLogs']) {
    const r = report.value[key]
    if (r) count += r.skipped || 0
  }
  return count
})
</script>

<template>
  <ModalDialog
    :title="asMine ? $t('import.titleAsMine') : $t('import.title')"
    wide
    @close="$emit('close')"
  >
    <!-- Loading -->
    <div v-if="step === 'loading'" class="import-loading" data-testid="import-loading">
      <i class="bi bi-arrow-repeat spin"></i>
      <p>{{ $t('app.loading') }}</p>
    </div>

    <!-- Suffix prompt -->
    <div v-else-if="step === 'suffix'" class="import-suffix" data-testid="import-suffix-step">
      <p>{{ $t('import.suffixExplanation', { name: summary.exporterName }) }}</p>
      <div class="form-group">
        <label for="suffix-input">{{ $t('import.suffixLabel') }}</label>
        <input
          id="suffix-input"
          v-model="suffixInput"
          type="text"
          data-testid="import-suffix-input"
          :placeholder="$t('import.suffixPlaceholder')"
          @keyup.enter="onConfirmSuffix"
        />
        <p v-if="suffixError" class="field-error" data-testid="import-suffix-error">
          {{ suffixError }}
        </p>
      </div>
      <p class="text-muted import-suffix-preview">
        {{ $t('import.suffixPreview', { title: 'Push-ups', suffix: suffixInput.trim() || '...' }) }}
      </p>
      <div class="import-actions">
        <button class="btn" data-testid="import-cancel" @click="$emit('close')">
          {{ $t('import.cancel') }}
        </button>
        <button
          class="btn btn-primary"
          data-testid="import-suffix-confirm"
          @click="onConfirmSuffix"
        >
          {{ $t('import.continue') }}
        </button>
      </div>
    </div>

    <!-- Preview -->
    <div v-else-if="step === 'preview'" class="import-preview" data-testid="import-preview-step">
      <div class="import-summary">
        <p>
          <strong>{{ totalEntityCount }}</strong>
          {{ $t('import.totalCount', { count: totalEntityCount }) }}
        </p>
        <p class="text-muted">
          {{
            $t('import.from', { name: summary.exporterName, date: formatDate(summary.exportDate) })
          }}
        </p>
        <p
          v-if="!summary.isSameUser && (analysis.suffixInfo?.existingSuffix || suffixInput.trim())"
          class="text-muted"
        >
          {{
            $t('import.usingSuffix', {
              suffix: analysis.suffixInfo?.existingSuffix || suffixInput.trim(),
            })
          }}
        </p>
        <!-- Entity breakdown -->
        <ul class="entity-breakdown">
          <li v-if="analysis.exercises">
            {{ analysis.exercises.total }} {{ $t('nav.exercises') }}
          </li>
          <li v-if="analysis.combos">{{ analysis.combos.total }} {{ $t('nav.combos') }}</li>
          <li v-if="analysis.sessions">{{ analysis.sessions.total }} {{ $t('nav.sessions') }}</li>
          <li v-if="analysis.collections">
            {{ analysis.collections.total }} {{ $t('nav.collections') }}
          </li>
          <li v-if="analysis.executionLogs">
            {{ analysis.executionLogs.total }} {{ $t('import.executionLogs') }}
          </li>
        </ul>
      </div>
      <div class="import-actions">
        <button class="btn" data-testid="import-cancel" @click="$emit('close')">
          {{ $t('import.cancel') }}
        </button>
        <button class="btn btn-primary" data-testid="import-apply" @click="onApply">
          {{ $t('import.apply') }}
        </button>
      </div>
    </div>

    <!-- Same-user collisions -->
    <div
      v-else-if="step === 'collisions'"
      class="import-collisions"
      data-testid="import-collisions-step"
    >
      <p>{{ $t('import.collisionExplanation', { count: totalCollisions }) }}</p>

      <!-- Exercises collisions -->
      <div
        v-if="exerciseResolutions.length > 0"
        class="collision-group"
        data-testid="collision-group-exercises"
      >
        <h4>{{ $t('nav.exercises') }}</h4>
        <div class="collision-batch">
          <button
            class="btn btn-sm"
            data-testid="exercise-replace-all"
            @click="setAllCollisions('exercise', COLLISION_ACTION.REPLACE)"
          >
            {{ $t('import.replaceAll') }}
          </button>
          <button
            class="btn btn-sm"
            data-testid="exercise-skip-all"
            @click="setAllCollisions('exercise', COLLISION_ACTION.SKIP)"
          >
            {{ $t('import.skipAll') }}
          </button>
        </div>
        <div
          v-for="(collision, index) in exerciseResolutions"
          :key="collision.imported.id"
          class="collision-item"
          :data-testid="'collision-item-exercise-' + index"
        >
          <div class="collision-info">
            <strong>{{ collision.imported.title }}</strong>
          </div>
          <div class="collision-actions">
            <button
              class="btn btn-sm"
              :class="{ 'btn-primary': collision.action === COLLISION_ACTION.REPLACE }"
              :data-testid="'collision-replace-exercise-' + index"
              @click="setCollisionAction('exercise', index, COLLISION_ACTION.REPLACE)"
            >
              {{ $t('import.replace') }}
            </button>
            <button
              class="btn btn-sm"
              :class="{ 'btn-primary': collision.action === COLLISION_ACTION.SKIP }"
              :data-testid="'collision-skip-exercise-' + index"
              @click="setCollisionAction('exercise', index, COLLISION_ACTION.SKIP)"
            >
              {{ $t('import.skip') }}
            </button>
          </div>
        </div>
      </div>

      <!-- Combos collisions -->
      <div
        v-if="comboResolutions.length > 0"
        class="collision-group"
        data-testid="collision-group-combos"
      >
        <h4>{{ $t('nav.combos') }}</h4>
        <div class="collision-batch">
          <button
            class="btn btn-sm"
            data-testid="combo-replace-all"
            @click="setAllCollisions('combo', COLLISION_ACTION.REPLACE)"
          >
            {{ $t('import.replaceAll') }}
          </button>
          <button
            class="btn btn-sm"
            data-testid="combo-skip-all"
            @click="setAllCollisions('combo', COLLISION_ACTION.SKIP)"
          >
            {{ $t('import.skipAll') }}
          </button>
        </div>
        <div
          v-for="(collision, index) in comboResolutions"
          :key="collision.imported.id"
          class="collision-item"
          :data-testid="'collision-item-combo-' + index"
        >
          <div class="collision-info">
            <strong>{{ collision.imported.title }}</strong>
          </div>
          <div class="collision-actions">
            <button
              class="btn btn-sm"
              :class="{ 'btn-primary': collision.action === COLLISION_ACTION.REPLACE }"
              :data-testid="'collision-replace-combo-' + index"
              @click="setCollisionAction('combo', index, COLLISION_ACTION.REPLACE)"
            >
              {{ $t('import.replace') }}
            </button>
            <button
              class="btn btn-sm"
              :class="{ 'btn-primary': collision.action === COLLISION_ACTION.SKIP }"
              :data-testid="'collision-skip-combo-' + index"
              @click="setCollisionAction('combo', index, COLLISION_ACTION.SKIP)"
            >
              {{ $t('import.skip') }}
            </button>
          </div>
        </div>
      </div>

      <!-- Sessions collisions -->
      <div
        v-if="sessionResolutions.length > 0"
        class="collision-group"
        data-testid="collision-group-sessions"
      >
        <h4>{{ $t('nav.sessions') }}</h4>
        <div class="collision-batch">
          <button
            class="btn btn-sm"
            data-testid="session-replace-all"
            @click="setAllCollisions('session', COLLISION_ACTION.REPLACE)"
          >
            {{ $t('import.replaceAll') }}
          </button>
          <button
            class="btn btn-sm"
            data-testid="session-skip-all"
            @click="setAllCollisions('session', COLLISION_ACTION.SKIP)"
          >
            {{ $t('import.skipAll') }}
          </button>
        </div>
        <div
          v-for="(collision, index) in sessionResolutions"
          :key="collision.imported.id"
          class="collision-item"
          :data-testid="'collision-item-session-' + index"
        >
          <div class="collision-info">
            <strong>{{ collision.imported.title }}</strong>
          </div>
          <div class="collision-actions">
            <button
              class="btn btn-sm"
              :class="{ 'btn-primary': collision.action === COLLISION_ACTION.REPLACE }"
              :data-testid="'collision-replace-session-' + index"
              @click="setCollisionAction('session', index, COLLISION_ACTION.REPLACE)"
            >
              {{ $t('import.replace') }}
            </button>
            <button
              class="btn btn-sm"
              :class="{ 'btn-primary': collision.action === COLLISION_ACTION.SKIP }"
              :data-testid="'collision-skip-session-' + index"
              @click="setCollisionAction('session', index, COLLISION_ACTION.SKIP)"
            >
              {{ $t('import.skip') }}
            </button>
          </div>
        </div>
      </div>

      <!-- Collections collisions -->
      <div
        v-if="collectionResolutions.length > 0"
        class="collision-group"
        data-testid="collision-group-collections"
      >
        <h4>{{ $t('nav.collections') }}</h4>
        <div class="collision-batch">
          <button
            class="btn btn-sm"
            data-testid="collection-replace-all"
            @click="setAllCollisions('collection', COLLISION_ACTION.REPLACE)"
          >
            {{ $t('import.replaceAll') }}
          </button>
          <button
            class="btn btn-sm"
            data-testid="collection-skip-all"
            @click="setAllCollisions('collection', COLLISION_ACTION.SKIP)"
          >
            {{ $t('import.skipAll') }}
          </button>
        </div>
        <div
          v-for="(collision, index) in collectionResolutions"
          :key="collision.imported.id"
          class="collision-item"
          :data-testid="'collision-item-collection-' + index"
        >
          <div class="collision-info">
            <strong>{{ collision.imported.label }}</strong>
          </div>
          <div class="collision-actions">
            <button
              class="btn btn-sm"
              :class="{ 'btn-primary': collision.action === COLLISION_ACTION.REPLACE }"
              :data-testid="'collision-replace-collection-' + index"
              @click="setCollisionAction('collection', index, COLLISION_ACTION.REPLACE)"
            >
              {{ $t('import.replace') }}
            </button>
            <button
              class="btn btn-sm"
              :class="{ 'btn-primary': collision.action === COLLISION_ACTION.SKIP }"
              :data-testid="'collision-skip-collection-' + index"
              @click="setCollisionAction('collection', index, COLLISION_ACTION.SKIP)"
            >
              {{ $t('import.skip') }}
            </button>
          </div>
        </div>
      </div>

      <div class="import-actions">
        <button class="btn" data-testid="import-cancel" @click="$emit('close')">
          {{ $t('import.cancel') }}
        </button>
        <button class="btn btn-primary" data-testid="import-apply" @click="onApply">
          {{ $t('import.apply') }}
        </button>
      </div>
    </div>

    <!-- Applying -->
    <div v-else-if="step === 'applying'" class="import-loading" data-testid="import-applying">
      <i class="bi bi-arrow-repeat spin"></i>
      <p>{{ $t('import.importing') }}</p>
    </div>

    <!-- Report -->
    <div v-else-if="step === 'report'" class="import-report" data-testid="import-report-step">
      <div
        class="report-summary"
        :class="report.errors?.length ? 'report-has-errors' : 'report-ok'"
      >
        <i :class="report.errors?.length ? 'bi bi-exclamation-triangle' : 'bi bi-check-circle'"></i>
        <strong>{{ $t('import.reportTitle') }}</strong>
      </div>
      <ul class="report-details">
        <li v-if="totalImported" data-testid="import-report-imported">
          {{ $t('import.reportTotalImported', { count: totalImported }) }}
        </li>
        <li v-if="totalSkipped" data-testid="import-report-skipped">
          {{ $t('import.reportSkipped', { count: totalSkipped }) }}
        </li>
        <!-- Per-entity breakdown -->
        <li v-if="report.exercises?.imported" data-testid="import-report-exercises-imported">
          {{ $t('import.reportImported', { count: report.exercises.imported }) }}
          {{ $t('nav.exercises') }}
        </li>
        <li v-if="report.exercises?.replaced" data-testid="import-report-exercises-replaced">
          {{ $t('import.reportReplaced', { count: report.exercises.replaced }) }}
          {{ $t('nav.exercises') }}
        </li>
        <li v-if="report.exercises?.updated" data-testid="import-report-exercises-updated">
          {{ $t('import.reportUpdated', { count: report.exercises.updated }) }}
          {{ $t('nav.exercises') }}
        </li>
        <li v-if="report.combos?.imported" data-testid="import-report-combos-imported">
          {{ $t('import.reportImported', { count: report.combos.imported }) }}
          {{ $t('nav.combos') }}
        </li>
        <li v-if="report.combos?.replaced" data-testid="import-report-combos-replaced">
          {{ $t('import.reportReplaced', { count: report.combos.replaced }) }}
          {{ $t('nav.combos') }}
        </li>
        <li v-if="report.combos?.updated" data-testid="import-report-combos-updated">
          {{ $t('import.reportUpdated', { count: report.combos.updated }) }}
          {{ $t('nav.combos') }}
        </li>
        <li v-if="report.sessions?.imported" data-testid="import-report-sessions-imported">
          {{ $t('import.reportImported', { count: report.sessions.imported }) }}
          {{ $t('nav.sessions') }}
        </li>
        <li v-if="report.sessions?.replaced" data-testid="import-report-sessions-replaced">
          {{ $t('import.reportReplaced', { count: report.sessions.replaced }) }}
          {{ $t('nav.sessions') }}
        </li>
        <li v-if="report.sessions?.updated" data-testid="import-report-sessions-updated">
          {{ $t('import.reportUpdated', { count: report.sessions.updated }) }}
          {{ $t('nav.sessions') }}
        </li>
        <li v-if="report.collections?.imported" data-testid="import-report-collections-imported">
          {{ $t('import.reportImported', { count: report.collections.imported }) }}
          {{ $t('nav.collections') }}
        </li>
        <li v-if="report.collections?.replaced" data-testid="import-report-collections-replaced">
          {{ $t('import.reportReplaced', { count: report.collections.replaced }) }}
          {{ $t('nav.collections') }}
        </li>
        <li v-if="report.collections?.updated" data-testid="import-report-collections-updated">
          {{ $t('import.reportUpdated', { count: report.collections.updated }) }}
          {{ $t('nav.collections') }}
        </li>
        <li v-if="report.executionLogs?.imported" data-testid="import-report-logs-imported">
          {{ $t('import.reportImported', { count: report.executionLogs.imported }) }}
          {{ $t('import.executionLogs') }}
        </li>
        <li v-if="report.settings?.imported" data-testid="import-report-settings-imported">
          {{ $t('import.reportImported', { count: report.settings.imported }) }}
          {{ $t('nav.settings') }}
        </li>
        <li
          v-for="(err, i) in report.errors"
          :key="i"
          class="report-error-item"
          :data-testid="'import-report-error-' + i"
        >
          {{ err }}
        </li>
      </ul>
      <div class="import-actions">
        <button class="btn btn-primary" data-testid="import-done" @click="onDone">
          {{ $t('import.done') }}
        </button>
      </div>
    </div>
  </ModalDialog>
</template>

<style scoped>
.import-loading {
  text-align: center;
  padding: 20px 0;
}

.import-loading .spin {
  font-size: 32px;
  display: inline-block;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.import-summary {
  margin-bottom: 16px;
}

.import-summary p {
  margin: 4px 0;
}

.entity-breakdown {
  list-style: disc;
  padding-left: 20px;
  margin: 8px 0 0;
  font-size: 14px;
  color: var(--color-text-muted);
}

.entity-breakdown li {
  margin-bottom: 2px;
}

.import-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border-color);
}

.form-group {
  margin: 12px 0;
}

.form-group label {
  display: block;
  font-weight: 600;
  font-size: 14px;
  margin-bottom: 4px;
}

.field-error {
  color: var(--btn-danger-bg);
  font-size: 13px;
  margin: 4px 0 0;
}

.import-suffix-preview {
  font-size: 13px;
  font-style: italic;
}

.collision-group {
  margin-bottom: 16px;
}

.collision-group h4 {
  margin: 0 0 8px;
  font-size: 15px;
  font-weight: 600;
}

.collision-batch {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
}

.collision-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--border-color);
}

.collision-info {
  flex: 1;
  min-width: 0;
}

.collision-info strong {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.collision-info .text-muted {
  font-size: 12px;
}

.collision-actions {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
  margin-left: 8px;
}

.btn-sm {
  font-size: 12px;
  padding: 4px 10px;
}

.report-summary {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 16px;
  margin-bottom: 12px;
}

.report-ok {
  color: #28a745;
}

.report-has-errors {
  color: var(--btn-danger-bg);
}

.report-details {
  list-style: disc;
  padding-left: 20px;
  font-size: 14px;
}

.report-details li {
  margin-bottom: 4px;
}

.report-error-item {
  color: var(--btn-danger-bg);
}
</style>
