<script setup lang="ts">
import { EditOutlined, LoadingOutlined, UserOutlined } from '@ant-design/icons-vue'
import type { KolProfile } from '@geo/shared-types'
import { useMutation, useQueryClient } from '@tanstack/vue-query'
import { message } from 'ant-design-vue'
import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'

import { kolManageApi, resolveApiURL } from '@/lib/api'
import { formatError } from '@/lib/errors'

const props = defineProps<{
  profile: KolProfile
}>()

const { t } = useI18n()
const queryClient = useQueryClient()

const editing = ref<'display_name' | 'bio' | null>(null)
const draftDisplayName = ref(props.profile.display_name)
const draftBio = ref(props.profile.bio ?? '')
const avatarUploading = ref(false)
const fileInput = ref<HTMLInputElement | null>(null)

const avatarURL = computed(() => resolveApiURL(props.profile.avatar_url))

const updateMutation = useMutation({
  mutationFn: kolManageApi.updateProfile,
  onSuccess: async () => {
    message.success(t('kol.profile.persona.saveSuccess'))
    await Promise.all([
      queryClient.invalidateQueries({ queryKey: ['kol', 'profile'] }),
      queryClient.invalidateQueries({ queryKey: ['workspace', 'kol-cards'] }),
      queryClient.invalidateQueries({ queryKey: ['kol', 'packages'] }),
    ])
    editing.value = null
  },
  onError: (error) => {
    message.error(formatError(error) || t('kol.profile.persona.saveError'))
    draftDisplayName.value = props.profile.display_name
    draftBio.value = props.profile.bio ?? ''
  },
})

function saveFields(patch: {
  display_name?: string
  bio?: string | null
  avatar_url?: string | null
}) {
  updateMutation.mutate({
    display_name: patch.display_name ?? props.profile.display_name,
    bio: patch.bio !== undefined ? patch.bio : props.profile.bio,
    avatar_url: patch.avatar_url !== undefined ? patch.avatar_url : props.profile.avatar_url,
  })
}

function commitDisplayName() {
  const next = draftDisplayName.value.trim()
  if (!next) {
    message.error(t('kol.profile.persona.displayNameRequired'))
    return
  }
  if (next.length > 40) {
    message.error(t('kol.profile.persona.displayNameTooLong'))
    return
  }
  if (next === props.profile.display_name) {
    editing.value = null
    return
  }
  saveFields({ display_name: next })
}

function commitBio() {
  const next = draftBio.value.trim()
  if (next.length > 500) {
    message.error(t('kol.profile.persona.bioTooLong'))
    return
  }
  const nextVal = next === '' ? null : next
  if (nextVal === (props.profile.bio ?? null)) {
    editing.value = null
    return
  }
  saveFields({ bio: nextVal })
}

function cancelEdit() {
  draftDisplayName.value = props.profile.display_name
  draftBio.value = props.profile.bio ?? ''
  editing.value = null
}

function startDisplayNameEdit() {
  draftDisplayName.value = props.profile.display_name
  editing.value = 'display_name'
}

function startBioEdit() {
  draftBio.value = props.profile.bio ?? ''
  editing.value = 'bio'
}

function triggerAvatarPicker() {
  fileInput.value?.click()
}

async function handleFilePicked(event: Event) {
  const input = event.target as HTMLInputElement
  const file = input.files?.[0]
  input.value = ''
  if (!file) return

  if (!/^image\/(png|jpe?g|gif|webp)$/i.test(file.type)) {
    message.error(t('kol.profile.persona.avatarInvalidType'))
    return
  }
  if (file.size > 2 * 1024 * 1024) {
    message.error(t('kol.profile.persona.avatarTooLarge'))
    return
  }

  avatarUploading.value = true
  try {
    const uploaded = await kolManageApi.uploadAvatar(file)
    saveFields({ avatar_url: uploaded.url })
  } catch (error) {
    message.error(formatError(error) || t('kol.profile.persona.saveError'))
  } finally {
    avatarUploading.value = false
  }
}
</script>

<template>
  <section class="persona-card">
    <div
      class="persona-avatar-wrap"
      :class="{ uploading: avatarUploading }"
      @click="triggerAvatarPicker"
    >
      <template v-if="avatarURL">
        <img :src="avatarURL" class="persona-avatar" alt="" />
      </template>
      <template v-else>
        <div class="persona-avatar persona-avatar-fallback">
          <UserOutlined />
        </div>
      </template>
      <div class="persona-avatar-mask">
        <LoadingOutlined v-if="avatarUploading" />
        <span v-else>{{ t('kol.profile.persona.avatarLabel') }}</span>
      </div>
      <input
        ref="fileInput"
        type="file"
        accept="image/png,image/jpeg,image/gif,image/webp"
        class="persona-avatar-input"
        @change="handleFilePicked"
      />
    </div>

    <div class="persona-fields">
      <div class="persona-field">
        <label class="persona-field-label">{{ t('kol.profile.persona.displayNameLabel') }}</label>
        <template v-if="editing === 'display_name'">
          <a-input
            v-model:value="draftDisplayName"
            :disabled="updateMutation.isPending.value"
            :placeholder="t('kol.profile.persona.displayNamePlaceholder')"
            :max-length="40"
            allow-clear
            @press-enter="commitDisplayName"
            @blur="commitDisplayName"
            @keyup.esc="cancelEdit"
          />
        </template>
        <template v-else>
          <div class="persona-field-static" @click="startDisplayNameEdit">
            <span class="persona-field-value">{{ profile.display_name }}</span>
            <EditOutlined class="persona-field-edit-icon" />
          </div>
        </template>
      </div>

      <div class="persona-field">
        <label class="persona-field-label">{{ t('kol.profile.persona.bioLabel') }}</label>
        <template v-if="editing === 'bio'">
          <a-textarea
            v-model:value="draftBio"
            :disabled="updateMutation.isPending.value"
            :placeholder="t('kol.profile.persona.bioPlaceholder')"
            :auto-size="{ minRows: 2, maxRows: 6 }"
            :max-length="500"
            show-count
            @blur="commitBio"
            @keydown.ctrl.enter.prevent="commitBio"
            @keydown.meta.enter.prevent="commitBio"
            @keyup.esc="cancelEdit"
          />
        </template>
        <template v-else>
          <div class="persona-field-static persona-field-static-multiline" @click="startBioEdit">
            <span class="persona-field-value persona-field-value-bio">
              {{ profile.bio || t('kol.profile.persona.bioPlaceholder') }}
            </span>
            <EditOutlined class="persona-field-edit-icon" />
          </div>
        </template>
      </div>

      <p class="persona-avatar-hint">{{ t('kol.profile.persona.avatarHint') }}</p>
    </div>
  </section>
</template>

<style scoped>
.persona-card {
  display: flex;
  align-items: flex-start;
  gap: 32px;
  background: #ffffff;
  border-radius: 12px;
  padding: 24px;
}
.persona-avatar-wrap {
  position: relative;
  width: 120px;
  height: 120px;
  border-radius: 50%;
  overflow: hidden;
  cursor: pointer;
  flex-shrink: 0;
  background: #f5f5f5;
}
.persona-avatar,
.persona-avatar-fallback {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 40px;
  color: #bfbfbf;
}
.persona-avatar-mask {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.persona-avatar-wrap:hover .persona-avatar-mask,
.persona-avatar-wrap.uploading .persona-avatar-mask {
  opacity: 1;
}
.persona-avatar-input {
  display: none;
}
.persona-fields {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 20px;
  min-width: 0;
}
.persona-field-label {
  display: block;
  color: #8c8c8c;
  font-size: 12px;
  margin-bottom: 6px;
}
.persona-field-static {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: text;
  padding: 2px 0;
  max-width: 100%;
}
.persona-field-static-multiline {
  align-items: flex-start;
}
.persona-field-value {
  font-size: 16px;
  font-weight: 600;
  color: #1a1a1a;
  word-break: break-word;
}
.persona-field-value-bio {
  font-size: 14px;
  font-weight: 400;
  color: #595959;
  white-space: pre-wrap;
}
.persona-field-edit-icon {
  color: #bfbfbf;
  font-size: 14px;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.persona-field-static:hover .persona-field-edit-icon {
  opacity: 1;
}
.persona-avatar-hint {
  margin: 0;
  color: #bfbfbf;
  font-size: 12px;
}
</style>
