<script setup lang="ts">
import { InfoCircleOutlined } from '@ant-design/icons-vue'
import type { PromptRule, PromptRuleGroup } from '@geo/shared-types'
import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query'
import { message } from 'ant-design-vue'
import { computed, reactive, watch } from 'vue'
import { useI18n } from 'vue-i18n'

import KnowledgeGroupSelect from '@/components/KnowledgeGroupSelect.vue'
import { promptRulesApi } from '@/lib/api'
import { formatError } from '@/lib/errors'
import { useCompanyStore } from '@/stores/company'

const props = defineProps<{
  open: boolean
  rule?: PromptRule | null
}>()

const emit = defineEmits<{
  'update:open': [value: boolean]
  saved: [ruleId: number]
}>()

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

const form = reactive({
  name: '',
  prompt_content: '',
  scene: '',
  default_tone: '',
  default_word_count: undefined as number | undefined,
  group_id: undefined as number | undefined,
  knowledge_group_ids: [] as number[],
})

const groupsQuery = useQuery({
  queryKey: computed(() => ['promptRules', 'groups', companyStore.currentBrandId]),
  enabled: computed(() => props.open && Boolean(companyStore.currentBrandId)),
  queryFn: () => promptRulesApi.listGroups(),
})

watch(
  () => props.open,
  (open) => {
    if (!open) {
      return
    }

    const rule = props.rule
    form.name = rule?.name ?? ''
    form.prompt_content = rule?.prompt_content ?? ''
    form.scene = rule?.scene ?? ''
    form.default_tone = rule?.default_tone ?? ''
    form.default_word_count = rule?.default_word_count ?? undefined
    form.group_id = rule?.group_id ?? undefined
    form.knowledge_group_ids = rule?.knowledge_group_ids ?? []
  },
)

watch(
  () => companyStore.currentBrandId,
  () => {
    if (props.open) {
      emit('update:open', false)
    }
  },
)

const createMutation = useMutation({
  mutationFn: () =>
    promptRulesApi.create({
      group_id: form.group_id ?? null,
      name: form.name.trim(),
      prompt_content: form.prompt_content.trim(),
      scene: form.scene.trim() || undefined,
      default_tone: form.default_tone.trim() || undefined,
      default_word_count: form.default_word_count,
      knowledge_group_ids: form.knowledge_group_ids,
    }),
  onSuccess: async (data) => {
    message.success(t('custom.messages.ruleCreated'))
    emit('saved', data.id)
    emit('update:open', false)
    await queryClient.invalidateQueries({ queryKey: ['promptRules'] })
  },
  onError: (error) => message.error(formatError(error)),
})

const updateMutation = useMutation({
  mutationFn: () =>
    promptRulesApi.update(props.rule!.id, {
      group_id: form.group_id ?? null,
      name: form.name.trim(),
      prompt_content: form.prompt_content.trim(),
      scene: form.scene.trim() || undefined,
      default_tone: form.default_tone.trim() || undefined,
      default_word_count: form.default_word_count,
      knowledge_group_ids: form.knowledge_group_ids,
    }),
  onSuccess: async () => {
    message.success(t('custom.messages.ruleUpdated'))
    if (props.rule?.id) {
      emit('saved', props.rule.id)
    }
    emit('update:open', false)
    await queryClient.invalidateQueries({ queryKey: ['promptRules'] })
  },
  onError: (error) => message.error(formatError(error)),
})

const submitLoading = computed(
  () => createMutation.isPending.value || updateMutation.isPending.value,
)

const drawerTitle = computed(() =>
  props.rule?.id ? t('custom.promptRule.editTitle') : t('custom.promptRule.createTitle'),
)

async function handleSubmit(): Promise<void> {
  if (!form.name.trim()) {
    message.warning(t('custom.messages.missingPromptName'))
    return
  }

  if (!form.prompt_content.trim()) {
    message.warning(t('custom.messages.missingPromptContent'))
    return
  }

  if (props.rule?.id) {
    await updateMutation.mutateAsync()
    return
  }

  await createMutation.mutateAsync()
}
</script>

<template>
  <a-drawer
    :open="open"
    :title="drawerTitle"
    placement="right"
    width="860"
    :mask-closable="false"
    class="prompt-rule-drawer"
    @close="emit('update:open', false)"
  >
    <div class="prompt-rule-drawer__body">
      <div class="prompt-rule-drawer__field">
        <label class="prompt-rule-drawer__label prompt-rule-drawer__label--required">
          {{ t('custom.promptRule.name') }}：
        </label>
        <a-input
          v-model:value="form.name"
          size="large"
          :maxlength="100"
          :placeholder="t('custom.promptRule.namePlaceholder')"
        />
      </div>

      <div class="prompt-rule-drawer__field">
        <label class="prompt-rule-drawer__label prompt-rule-drawer__label--required">
          {{ t('custom.promptRule.content') }}：
        </label>
        <a-textarea
          v-model:value="form.prompt_content"
          :rows="12"
          :placeholder="t('custom.promptRule.contentPlaceholder')"
        />
      </div>

      <div class="prompt-rule-drawer__field">
        <label class="prompt-rule-drawer__label">{{ t('custom.group.title') }}：</label>
        <a-select
          v-model:value="form.group_id"
          size="large"
          style="width: 100%"
          :placeholder="t('custom.promptRule.groupPlaceholder')"
          :options="
            (groupsQuery.data.value ?? []).map((group: PromptRuleGroup) => ({
              label: group.name,
              value: group.id,
            }))
          "
          allow-clear
        />
      </div>

      <div class="prompt-rule-drawer__grid">
        <div class="prompt-rule-drawer__field">
          <label class="prompt-rule-drawer__label">{{ t('custom.promptRule.scene') }}：</label>
          <a-input v-model:value="form.scene" size="large" />
        </div>

        <div class="prompt-rule-drawer__field">
          <label class="prompt-rule-drawer__label">{{ t('custom.promptRule.tone') }}：</label>
          <a-input v-model:value="form.default_tone" size="large" />
        </div>

        <div class="prompt-rule-drawer__field">
          <label class="prompt-rule-drawer__label">
            {{ t('custom.promptRule.wordCount') }}：
            <a-tooltip :title="t('custom.promptRule.wordCountHint')">
              <InfoCircleOutlined style="margin-left: 6px; color: #8c8c8c; cursor: help" />
            </a-tooltip>
          </label>
          <a-input-number
            v-model:value="form.default_word_count"
            :min="100"
            :max="6000"
            style="width: 100%"
            size="large"
          />
        </div>
      </div>

      <div class="prompt-rule-drawer__field">
        <label class="prompt-rule-drawer__label">知识库引用：</label>
        <KnowledgeGroupSelect
          v-model="form.knowledge_group_ids"
          placeholder="可选，用于补充生成内容的背景信息"
        />
      </div>
    </div>

    <template #footer>
      <div class="prompt-rule-drawer__footer">
        <a-button size="large" @click="emit('update:open', false)">
          {{ t('common.cancel') }}
        </a-button>
        <a-button type="primary" size="large" :loading="submitLoading" @click="handleSubmit">
          {{ t('common.confirm') }}
        </a-button>
      </div>
    </template>
  </a-drawer>
</template>

<style scoped>
.prompt-rule-drawer :deep(.ant-drawer-header) {
  padding: 30px 28px;
  border-bottom: 1px solid #edf2f7;
}

.prompt-rule-drawer :deep(.ant-drawer-title) {
  color: #111827;
  font-size: 18px;
  font-weight: 800;
}

.prompt-rule-drawer :deep(.ant-drawer-body) {
  padding: 30px 32px 32px;
  background: #fff;
}

.prompt-rule-drawer :deep(.ant-drawer-footer) {
  padding: 18px 28px;
  border-top: 1px solid #edf2f7;
  background: #fff;
}

.prompt-rule-drawer__body {
  padding: 0 20px;
  display: flex;
  flex-direction: column;
}

.prompt-rule-drawer__field {
  margin-top: 24px;
}

.prompt-rule-drawer__field:first-child {
  margin-top: 0;
}

.prompt-rule-drawer__grid .prompt-rule-drawer__field {
  margin-top: 0;
}

.prompt-rule-drawer__field :deep(.ant-input),
.prompt-rule-drawer__field :deep(.ant-input-number),
.prompt-rule-drawer__field :deep(.ant-select-selector),
.prompt-rule-drawer__field :deep(textarea.ant-input) {
  margin-top: 4px;
}

.prompt-rule-drawer__label {
  display: inline-flex;
  align-items: center;
  margin-bottom: 12px;
  color: #1f2937;
  font-size: 15px;
  font-weight: 700;
}

.prompt-rule-drawer__label--required::before {
  content: '*';
  margin-right: 4px;
  color: #ff4d4f;
}

.prompt-rule-drawer__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px 18px;
  margin-top: 24px;
}

.prompt-rule-drawer__footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

@media (max-width: 820px) {
  .prompt-rule-drawer__grid {
    grid-template-columns: 1fr;
  }
}
</style>
