<script setup lang="ts">
import type { PropType } from 'vue';

import type { llmType } from '#/api';
import type { ModelAbilityItem } from '#/views/ai/model/modelUtils/model-ability';
import type { VerifyButtonStatus } from '#/views/ai/model/modelUtils/model-verification';

import { ref } from 'vue';

import {
  CircleCheck,
  CircleClose,
  Delete,
  Edit,
  Loading,
  Select,
  Warning,
} from '@element-plus/icons-vue';
import { ElButton, ElIcon, ElMessage, ElTag } from 'element-plus';

import { verifyModelConfig } from '#/api/ai/llm';
import ModelProviderBadge from '#/views/ai/model/ModelProviderBadge.vue';
import { getDefaultModelAbility } from '#/views/ai/model/modelUtils/model-ability';
import { mapLlmToModelAbility } from '#/views/ai/model/modelUtils/model-ability-utils';
import {
  getVerifyButtonText as getStatusButtonText,
  resolveModelVerificationFeedback,
} from '#/views/ai/model/modelUtils/model-verification';

const props = defineProps({
  llmList: {
    type: Array as PropType<llmType[]>,
    default: () => [],
  },
  needHiddenSettingIcon: {
    type: Boolean,
    default: false,
  },
});

const emit = defineEmits(['deleteLlm', 'editLlm']);
const verifyStatusMap = ref<Record<string, VerifyButtonStatus>>({});
const getModelId = (llm: llmType) =>
  String((llm as any).id || (llm as any).llmId || (llm as any).modelId || '');
const getVerifyStatus = (llm: llmType): VerifyButtonStatus =>
  verifyStatusMap.value[getModelId(llm)] || 'idle';
const isVerifying = (llm: llmType) => getVerifyStatus(llm) === 'loading';
const setVerifyStatus = (id: string, status: VerifyButtonStatus) => {
  if (!id) {
    return;
  }
  verifyStatusMap.value[id] = status;
};
const getVerifyButtonText = (llm: llmType) => {
  return getStatusButtonText(getVerifyStatus(llm));
};
const getVerifyButtonIcon = (llm: llmType) => {
  const status = getVerifyStatus(llm);
  if (status === 'loading') {
    return Loading;
  }
  if (status === 'success') {
    return CircleCheck;
  }
  if (status === 'warning') {
    return Warning;
  }
  if (status === 'error') {
    return CircleClose;
  }
  return Select;
};

const handleDeleteLlm = (id: string) => {
  emit('deleteLlm', id);
};

const handleEditLlm = (id: string) => {
  emit('editLlm', id);
};

const canVerify = (llm: llmType) => llm.modelType !== 'rerankModel';

const handleVerifyLlm = async (llm: llmType) => {
  const modelId = getModelId(llm);
  if (!modelId || isVerifying(llm)) {
    if (!modelId) {
      ElMessage.warning('当前模型缺少ID，无法验证配置');
    }
    return;
  }

  setVerifyStatus(modelId, 'loading');

  try {
    const res = await verifyModelConfig(modelId);

    const feedback = resolveModelVerificationFeedback(res, llm.modelType);
    setVerifyStatus(modelId, feedback.status);

    if (feedback.status === 'success') {
      ElMessage.success(feedback.message);
    } else if (feedback.status === 'warning') {
      ElMessage.warning(feedback.message);
    } else {
      if (!res.message) {
        ElMessage.error(feedback.message);
      }
    }
  } catch {
    setVerifyStatus(modelId, 'error');
    // error toast is already handled by global response interceptors
  } finally {
    // keep final status for explicit visual feedback
  }
};

const getSelectedAbilityTagsForLlm = (llm: llmType): ModelAbilityItem[] => {
  const defaultAbility = getDefaultModelAbility();
  const allTags = mapLlmToModelAbility(llm, defaultAbility);
  return allTags.filter((tag) => tag.selected);
};
</script>

<template>
  <div class="llm-list">
    <article v-for="llm in props.llmList" :key="llm.id" class="llm-item">
      <div class="llm-item__main">
        <ModelProviderBadge
          :icon="llm.modelProvider?.icon"
          :provider-name="llm.modelProvider?.providerName"
          :provider-type="llm.modelProvider?.providerType"
          :size="40"
        />
        <div class="llm-item__content">
          <div class="llm-item__headline">
            <h4 class="llm-item__title">{{ llm.title }}</h4>
            <div
              v-if="getSelectedAbilityTagsForLlm(llm).length > 0"
              class="llm-item__tags"
            >
              <ElTag
                v-for="tag in getSelectedAbilityTagsForLlm(llm)"
                :key="tag.value"
                effect="plain"
                size="small"
                class="llm-item__tag"
              >
                {{ tag.label }}
              </ElTag>
            </div>
          </div>
          <p v-if="llm.description" class="llm-item__description">
            {{ llm.description }}
          </p>
        </div>
      </div>

      <div class="llm-item__actions">
        <ElButton
          v-if="canVerify(llm)"
          text
          size="small"
          class="llm-item__verify-btn"
          :class="`is-${getVerifyStatus(llm)}`"
          :disabled="isVerifying(llm) || !getModelId(llm)"
          @click="handleVerifyLlm(llm)"
        >
          <template #icon>
            <ElIcon
              class="llm-item__verify-icon"
              :class="`is-${getVerifyStatus(llm)}`"
            >
              <component :is="getVerifyButtonIcon(llm)" />
            </ElIcon>
          </template>
          {{ getVerifyButtonText(llm) }}
        </ElButton>

        <ElButton
          v-if="!needHiddenSettingIcon"
          text
          size="small"
          :icon="Edit"
          @click="handleEditLlm(llm.id)"
        >
          编辑
        </ElButton>

        <ElButton
          text
          size="small"
          :icon="Delete"
          class="llm-item__danger"
          @click="handleDeleteLlm(llm.id)"
        >
          删除
        </ElButton>
      </div>
    </article>
  </div>
</template>

<style scoped>
.llm-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.llm-item {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  justify-content: space-between;
  padding: 16px 18px;
  background: hsl(var(--surface-panel) / 90%);
  border: 1px solid hsl(var(--divider-faint) / 54%);
  border-radius: 18px;
  transition:
    border-color 0.2s ease,
    transform 0.2s ease,
    box-shadow 0.2s ease;
}

.llm-item:hover {
  border-color: hsl(var(--primary) / 28%);
  box-shadow: 0 18px 30px -28px hsl(var(--foreground) / 34%);
  transform: translateY(-1px);
}

.llm-item__main {
  display: flex;
  flex: 1;
  gap: 14px;
  align-items: flex-start;
  min-width: 0;
}

.llm-item__content {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.llm-item__headline {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.llm-item__title {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
  color: hsl(var(--text-strong));
}

.llm-item__description {
  display: -webkit-box;
  margin: 0;
  overflow: hidden;
  -webkit-line-clamp: 2;
  font-size: 13px;
  line-height: 1.5;
  color: hsl(var(--text-muted));
  -webkit-box-orient: vertical;
}

.llm-item__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.llm-item__tag {
  color: hsl(var(--text-strong));
  background: hsl(var(--primary) / 8%);
  border-color: transparent;
}

.llm-item__actions {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: center;
  justify-content: flex-end;
}

.llm-item__actions :deep(.el-button) {
  border-radius: 10px;
}

.llm-item__verify-btn.is-idle {
  color: hsl(var(--text-muted));
}

.llm-item__verify-btn.is-loading {
  color: hsl(var(--primary));
}

.llm-item__verify-btn.is-success {
  color: hsl(var(--success));
}

.llm-item__verify-btn.is-warning {
  color: hsl(var(--warning));
}

.llm-item__verify-btn.is-error {
  color: hsl(var(--destructive));
}

.llm-item__verify-icon {
  transition:
    color 0.24s ease,
    transform 0.24s ease;
}

.llm-item__verify-icon.is-loading {
  animation: llm-item-verify-spin 0.9s linear infinite;
}

.llm-item__verify-icon.is-success,
.llm-item__verify-icon.is-warning,
.llm-item__verify-icon.is-error {
  animation: llm-item-verify-pop 0.32s ease;
}

.llm-item__danger {
  color: hsl(var(--danger) / 90%);
}

.llm-item__danger:hover,
.llm-item__danger:focus-visible {
  color: hsl(var(--danger));
}

@keyframes llm-item-verify-spin {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

@keyframes llm-item-verify-pop {
  0% {
    opacity: 0.72;
    transform: scale(0.82);
  }

  100% {
    opacity: 1;
    transform: scale(1);
  }
}

@media (max-width: 768px) {
  .llm-item {
    flex-direction: column;
  }

  .llm-item__actions {
    justify-content: flex-start;
    width: 100%;
  }
}
</style>
