<script setup lang="ts">
import { ref, watch, computed, nextTick } from 'vue';
import { ElMessage } from 'element-plus';
import CountryFlagSelect from './outright/CountryFlagSelect.vue';
import {
  countryLogoUrl,
  detectCountryLogoKind,
  getBuiltinCountry,
  hasCountryCrest,
  resolveCountryCode,
  type BuiltinCountry,
  type CountryLogoKind,
} from '../data/builtinCountries';
import { useAdminLocale } from '../composables/useAdminLocale';
import api from '../api';

const LOGO_ACCEPT = 'image/png,image/jpeg,image/webp,image/gif,image/svg+xml';

const props = defineProps<{
  modelValue: string;
  teamCode?: string;
  /** 上传分类，默认 teams */
  uploadCategory?: string;
  /** 表格等窄布局：隐藏 URL 输入框，仅国家 + 国旗/队徽 */
  compact?: boolean;
  /** 仅上传与 URL，不显示国家选择 */
  uploadOnly?: boolean;
  /** 是否标记删除旧资源（父组件保存时执行） */
  deleteOld?: boolean;
}>();

const emit = defineEmits<{
  'update:modelValue': [value: string];
  'update:deleteOld': [value: boolean];
  pick: [country: BuiltinCountry];
}>();

const { t } = useAdminLocale();
const countryCode = ref('');
const logoKind = ref<CountryLogoKind>('crest');
const uploading = ref(false);
const dragging = ref(false);
const fileInputRef = ref<HTMLInputElement | null>(null);

const canPickCrest = computed(() => {
  const code = countryCode.value;
  return code ? hasCountryCrest(code) : false;
});

const previewUrl = computed(() => localUrl.value.trim() || '');

/** Local URL mirror for immediate preview updates regardless of parent sync */
const localUrl = ref(props.modelValue);
watch(() => props.modelValue, (v) => { localUrl.value = v; }, { immediate: true });

/**
 * Update URL both locally (instant preview) and emit to parent.
 * nextTick ensures Vue processes the parent update before continuing.
 */
async function updateUrl(url: string) {
  localUrl.value = url;
  emit('update:modelValue', url);
  await nextTick();
}

watch(
  () => [props.modelValue, props.teamCode, props.uploadOnly] as const,
  ([url, code, uploadOnly]) => {
    if (uploadOnly) return;
    countryCode.value = resolveCountryCode(code, url || null);
    if (url) {
      logoKind.value = detectCountryLogoKind(url, countryCode.value);
    }
  },
  { immediate: true },
);

watch(countryCode, (code, prev) => {
  if (props.uploadOnly) return;
  if (!code && prev && (logoKind.value === 'flag' || logoKind.value === 'crest')) {
    emit('update:modelValue', '');
  }
});

function applyLogoForCountry(country: BuiltinCountry) {
  const kind =
    logoKind.value === 'crest' && hasCountryCrest(country) ? 'crest' : 'flag';
  logoKind.value = kind;
  updateUrl(countryLogoUrl(country, kind));
}

function onCountryPick(country: BuiltinCountry) {
  countryCode.value = country.code;
  if (!props.modelValue.trim()) {
    logoKind.value = hasCountryCrest(country) ? 'crest' : 'flag';
  }
  applyLogoForCountry(country);
  emit('pick', country);
}

function onLogoKindChange(kind: CountryLogoKind) {
  if (kind === 'custom') return;
  const country = getBuiltinCountry(countryCode.value);
  if (!country) return;
  logoKind.value = kind === 'crest' && !hasCountryCrest(country) ? 'flag' : kind;
  updateUrl(countryLogoUrl(country, logoKind.value as 'flag' | 'crest'));
}

function onCustomUrlInput(value: string) {
  logoKind.value = detectCountryLogoKind(value, countryCode.value);
  updateUrl(value);
}

function triggerUpload() {
  fileInputRef.value?.click();
}

async function onFileChange(e: Event) {
  const input = e.target as HTMLInputElement;
  const file = input.files?.[0];
  if (!file) return;
  input.value = '';
  uploading.value = true;
  try {
    const fd = new FormData();
    fd.append('file', file);
    const category = props.uploadCategory || 'teams';
    const { data } = await api.post(`/admin/uploads?category=${category}`, fd, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    const url = data.data?.url as string;
    if (url) {
      logoKind.value = 'custom';
      await updateUrl(url);
      ElMessage.success(t('content.upload.success'));
    }
  } catch (err: any) {
    const msg = err?.response?.data?.message || t('content.upload.failed');
    ElMessage.error(String(msg));
  } finally {
    uploading.value = false;
  }
}

function onDragOver(e: DragEvent) {
  e.preventDefault();
  dragging.value = true;
}

function onDragLeave() {
  dragging.value = false;
}

async function onFileDrop(e: DragEvent) {
  e.preventDefault();
  dragging.value = false;
  const file = e.dataTransfer?.files[0];
  if (!file || !file.type.startsWith('image/')) return;
  uploading.value = true;
  try {
    const fd = new FormData();
    fd.append('file', file);
    const category = props.uploadCategory || 'teams';
    const { data } = await api.post(`/admin/uploads?category=${category}`, fd, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    const url = data.data?.url as string;
    if (url) {
      logoKind.value = 'custom';
      await updateUrl(url);
      ElMessage.success(t('content.upload.success'));
    }
  } catch (err: any) {
    const msg = err?.response?.data?.message || t('content.upload.failed');
    ElMessage.error(String(msg));
  } finally {
    uploading.value = false;
  }
}

/** Track the original URL (from when component mounted) so user can mark old resource for deletion */
const oldUrl = ref(props.modelValue);
</script>

<template>
  <div class="logo-url-field" :class="{ compact, 'upload-only': uploadOnly }">
    <template v-if="!uploadOnly">
      <CountryFlagSelect
        v-model="countryCode"
        hide-preview
        class="flag-part"
        @pick="onCountryPick"
      />
      <el-radio-group
        v-if="countryCode"
        :model-value="logoKind === 'custom' ? 'flag' : logoKind"
        size="small"
        class="kind-group"
        @update:model-value="onLogoKindChange($event as CountryLogoKind)"
      >
        <el-radio-button value="flag">{{ t('teamLogo.kind.flag') }}</el-radio-button>
        <el-radio-button value="crest" :disabled="!canPickCrest">
          {{ t('teamLogo.kind.crest') }}
        </el-radio-button>
      </el-radio-group>
    </template>
    <div class="upload-row">
      <div
        class="drop-zone"
        :class="{ 'is-dragging': dragging }"
        @click="triggerUpload"
        @dragover.prevent="onDragOver"
        @dragleave="onDragLeave"
        @drop="onFileDrop"
      >
        <img v-if="previewUrl" :src="previewUrl" alt="" class="drop-preview" loading="lazy" />
        <div v-else class="drop-placeholder">
          <svg class="drop-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
            <path d="M12 5v14M5 12h14" />
          </svg>
          <span class="drop-text">{{ uploading ? '上传中…' : '拖拽或点击上传' }}</span>
        </div>
      </div>
      <label
        v-if="oldUrl"
        class="delete-old-check"
      >
        <input
          type="checkbox"
          :checked="deleteOld"
          @change="emit('update:deleteOld', ($event.target as HTMLInputElement).checked)"
        />
        <span>保存时删除旧图</span>
      </label>
    </div>
    <input
      ref="fileInputRef"
      type="file"
      :accept="LOGO_ACCEPT"
      style="display: none"
      @change="onFileChange"
    />
    <el-input
      v-if="!compact"
      :model-value="localUrl"
      size="small"
      :placeholder="t('matchEditor.ph.logo_url')"
      clearable
      class="url-part"
      @update:model-value="onCustomUrlInput"
    />
  </div>
</template>

<style scoped>
.logo-url-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  min-width: 0;
  align-items: flex-start;
}

.flag-part {
  width: 100%;
}

.kind-group {
  flex-shrink: 0;
}

.upload-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.drop-zone {
  width: 100px;
  height: 100px;
  flex-shrink: 0;
  border: 2px dashed #d5cfc3;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.2s;
  background: #fbfaf7;
  overflow: hidden;
}

.delete-old-check {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--danger-text);
  cursor: pointer;
  padding: 2px 4px;
  border-radius: 4px;
  transition: background 0.15s;
  white-space: nowrap;
  user-select: none;
}

.delete-old-check:hover {
  background: var(--danger-bg);
}

.delete-old-check input[type="checkbox"] {
  accent-color: #e55;
  margin: 0;
  width: 13px;
  height: 13px;
  cursor: pointer;
}

.drop-zone:hover {
  border-color: var(--primary);
  background: var(--accent-hover);
}

.drop-zone.is-dragging {
  border-color: var(--primary);
  background: var(--accent-hover);
}

.drop-preview {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.drop-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
}

.drop-icon {
  width: 28px;
  height: 28px;
}

.drop-text {
  font-size: 11px;
  white-space: nowrap;
}

.url-part {
  width: 100%;
}

.logo-url-field.compact .drop-zone {
  width: 80px;
  height: 80px;
}
</style>
