<template>
  <div class="art-page-view space-y-4">
    <ElCard shadow="never">
      <div class="flex flex-wrap items-start justify-between gap-4">
        <div class="space-y-1">
          <div class="text-lg font-semibold">{{ t('announcement.edit.title') }}</div>
          <div class="text-sm text-[var(--el-text-color-secondary)]">
            {{ draftStatusText }}
          </div>
        </div>
        <div class="flex items-center gap-2">
          <ElButton @click="handleBack">
            {{ t('announcement.action.back') }}
          </ElButton>
          <ElButton type="primary" :loading="loading" :disabled="!isEditable" @click="handleSubmit">
            {{ t('announcement.action.save') }}
          </ElButton>
          <ElButton
            type="success"
            :loading="loading"
            :disabled="!isEditable"
            @click="handlePublish"
          >
            {{ t('announcement.action.publish') }}
          </ElButton>
        </div>
      </div>
    </ElCard>

    <ElAlert
      v-if="!isEditable"
      type="warning"
      :closable="false"
      :title="t('announcement.edit.notEditable')"
    />
    <ElAlert
      v-else
      type="info"
      :closable="false"
      :title="t('announcement.edit.readonlyFieldsHint')"
    />

    <ElCard shadow="never" v-loading="pageLoading">
      <ElForm ref="formRef" :model="formModel" :rules="formRules" label-position="top">
        <div class="grid grid-cols-1 gap-4 lg:grid-cols-2">
          <ElFormItem class="lg:col-span-2" prop="title" :label="t('announcement.form.title')">
            <ElInput
              v-model="formModel.title"
              maxlength="128"
              show-word-limit
              :disabled="!isEditable"
              :placeholder="t('announcement.form.titlePlaceholder')"
            />
          </ElFormItem>

          <ElFormItem prop="announcementType" :label="t('announcement.form.type')">
            <ElSelect v-model="formModel.announcementType" disabled>
              <ElOption
                v-for="option in typeOptions"
                :key="option.value"
                :label="option.label"
                :value="option.value"
              />
            </ElSelect>
          </ElFormItem>

          <ElFormItem prop="priority" :label="t('announcement.form.priority')">
            <ElInputNumber v-model="formModel.priority" :min="1" :max="5" disabled class="w-full" />
          </ElFormItem>

          <ElFormItem prop="effectiveFrom" :label="t('announcement.form.effectiveFrom')">
            <ElDatePicker
              v-model="formModel.effectiveFrom"
              type="datetime"
              disabled
              class="w-full"
              :value-format="dateTimeFormat"
            />
          </ElFormItem>

          <ElFormItem prop="effectiveTo" :label="t('announcement.form.effectiveTo')">
            <ElDatePicker
              v-model="formModel.effectiveTo"
              type="datetime"
              disabled
              class="w-full"
              :value-format="dateTimeFormat"
            />
          </ElFormItem>

          <ElFormItem
            class="lg:col-span-2"
            prop="targetType"
            :label="t('announcement.form.target')"
          >
            <AudienceSelector
              :model-value="{
                targetType: formModel.targetType,
                targetRules: formModel.targetRules,
                targetUserIds: formModel.targetUserIds
              }"
              :disabled="!isEditable"
              @update:model-value="
                (value) => {
                  formModel.targetType = value.targetType
                  formModel.targetRules = value.targetRules
                  formModel.targetUserIds = value.targetUserIds
                }
              "
            />
          </ElFormItem>

          <ElFormItem class="lg:col-span-2" prop="content" :label="t('announcement.form.content')">
            <RichTextEditor
              v-model="formModel.content"
              :height="'360px'"
              :placeholder="t('announcement.form.contentPlaceholder')"
              :disabled="!isEditable"
            />
          </ElFormItem>
        </div>
      </ElForm>
    </ElCard>
  </div>
</template>

<script setup lang="ts">
  import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
  import { useI18n } from 'vue-i18n'
  import { useRoute, useRouter } from 'vue-router'
  import { storeToRefs } from 'pinia'
  import type { FormInstance, FormItemRule, FormRules } from 'element-plus'
  import {
    ElAlert,
    ElButton,
    ElCard,
    ElDatePicker,
    ElForm,
    ElFormItem,
    ElInput,
    ElInputNumber,
    ElMessage,
    ElMessageBox,
    ElOption,
    ElSelect
  } from 'element-plus'
  import RichTextEditor from '@/components/common/RichTextEditor.vue'
  import AudienceSelector from '@/components/announcement/AudienceSelector.vue'
  import { platformAnnouncementApi } from '@/api/announcement'
  import { useAnnouncementStore } from '@/store/modules/announcement'
  import { normalizeAnnouncementStatus } from '@/utils/announcementStatus'
  import type {
    AnnouncementFormData,
    AnnouncementTargetType,
    AnnouncementTypeOption,
    TargetRules,
    TenantAnnouncementDto,
    TenantAnnouncementType
  } from '@/types/announcement'
  import { TenantAnnouncementType as TenantAnnouncementTypeEnum } from '@/types/announcement'

  defineOptions({ name: 'PlatformAnnouncementEdit' })

  const { t } = useI18n()
  const route = useRoute()
  const router = useRouter()

  // 1. 初始化 Store 与加载状态
  const announcementStore = useAnnouncementStore()
  const { loading } = storeToRefs(announcementStore)
  const pageLoading = ref(false)

  // 2. 详情数据与编辑状态
  const announcementDetail = ref<TenantAnnouncementDto | null>(null)
  const resolveStatus = (status: unknown) => normalizeAnnouncementStatus(status)
  const isEditable = computed(() => resolveStatus(announcementDetail.value?.status) === 'Draft')

  // 3. 表单模型
  const formModel = reactive<AnnouncementFormData>({
    title: '',
    content: '',
    announcementType: TenantAnnouncementTypeEnum.System,
    priority: 1,
    effectiveFrom: new Date().toISOString(),
    effectiveTo: null,
    targetType: 'All',
    targetRules: undefined,
    targetUserIds: [],
    rowVersion: undefined
  })

  // 4. 日期格式
  const dateTimeFormat = 'YYYY-MM-DDTHH:mm:ss.SSSZ'

  // 5. 公告类型选项
  const typeOptions = computed<AnnouncementTypeOption[]>(() => {
    const values = Object.values(TenantAnnouncementTypeEnum).filter(
      (value) => typeof value === 'number'
    ) as TenantAnnouncementType[]

    return values.map((value) => ({
      value,
      label: getTypeLabel(value)
    }))
  })

  // 7. FluentValidation 风格校验规则构建器
  const createRuleBuilder = () => {
    const rules: FormItemRule[] = []

    const withValidator = (
      validator: (value: unknown) => string | null,
      trigger: FormItemRule['trigger']
    ) => {
      rules.push({
        trigger,
        validator: (_rule, value, callback) => {
          const message = validator(value)
          if (message) {
            callback(new Error(message))
            return
          }
          callback()
        }
      })
    }

    return {
      required(message: string, trigger: FormItemRule['trigger'] = 'blur') {
        rules.push({ required: true, message, trigger })
        return this
      },
      maxLength(max: number, message: string, trigger: FormItemRule['trigger'] = 'blur') {
        withValidator((value) => {
          if (!value) {
            return null
          }
          return String(value).length > max ? message : null
        }, trigger)
        return this
      },
      custom(
        validator: (value: unknown) => string | null,
        trigger: FormItemRule['trigger'] = 'change'
      ) {
        withValidator(validator, trigger)
        return this
      },
      build() {
        return rules
      }
    }
  }

  // 8. 表单校验规则
  const formRules = computed<FormRules<AnnouncementFormData>>(() => ({
    title: createRuleBuilder()
      .required(t('announcement.validation.titleRequired'))
      .maxLength(128, t('announcement.validation.titleMax'))
      .build(),
    content: createRuleBuilder().required(t('announcement.validation.contentRequired')).build(),
    targetType: createRuleBuilder()
      .required(t('announcement.validation.targetTypeRequired'), 'change')
      .custom(validateAudience, 'change')
      .build()
  }))

  const formRef = ref<FormInstance>()
  const autoSaveCleanup = ref<(() => void) | null>(null)

  // 9. 草稿状态提示
  const draftStatusText = computed(() => {
    if (!isEditable.value) {
      return t('announcement.draft.readOnly')
    }

    const lastSaved = announcementStore.currentDraft?.lastSaved
    if (!lastSaved) {
      return t('announcement.draft.notSaved')
    }

    return t('announcement.draft.savedAt', { time: formatTime(lastSaved) })
  })

  const validateAudience = (value: unknown) => {
    const targetType = value as AnnouncementTargetType
    if (!targetType) {
      return t('announcement.validation.targetTypeRequired')
    }

    if ((targetType === 'Rules' || targetType === 'Roles') && !formModel.targetRules) {
      return t('announcement.validation.targetRulesRequired')
    }

    if (
      (targetType === 'Users' || targetType === 'Manual') &&
      (!formModel.targetUserIds || formModel.targetUserIds.length === 0)
    ) {
      return t('announcement.validation.targetUsersRequired')
    }

    return null
  }

  const handleSubmit = async () => {
    if (!formRef.value) {
      return
    }

    if (!announcementDetail.value) {
      ElMessage.error(t('announcement.message.loadFailed'))
      return
    }

    try {
      // 1. 触发表单校验
      await formRef.value.validate()
    } catch {
      ElMessage.warning(t('announcement.message.validationFailed'))
      return
    }

    if (!formModel.rowVersion) {
      ElMessage.error(t('announcement.message.rowVersionMissing'))
      return
    }

    try {
      // 2. 构建更新参数
      const payload: AnnouncementFormData = {
        title: formModel.title.trim(),
        content: formModel.content,
        announcementType: formModel.announcementType,
        priority: formModel.priority,
        effectiveFrom: formModel.effectiveFrom,
        effectiveTo: formModel.effectiveTo || null,
        targetType: formModel.targetType,
        targetRules: formModel.targetRules,
        targetUserIds: formModel.targetUserIds,
        rowVersion: formModel.rowVersion
      }

      // 3. 调用更新接口
      const result = await announcementStore.updateAnnouncement(
        announcementDetail.value.id,
        payload,
        { scope: 'platform' }
      )

      if (result) {
        ElMessage.success(t('announcement.message.updateSuccess'))
        // 跳转到详情页
        void router.push(`/platform/announcements/${announcementDetail.value.id}`)
      }
    } catch (error: any) {
      // 处理并发冲突错误 (409 Conflict)
      if (error?.response?.status === 409) {
        ElMessage.error(
          t('announcement.message.concurrencyConflict', {
            message: t('announcement.message.refreshAndRetry')
          })
        )
      } else {
        ElMessage.error(error?.response?.data?.message || t('announcement.message.updateFailed'))
      }
    }
  }

  const handlePublish = async () => {
    if (!announcementDetail.value) {
      ElMessage.error(t('announcement.message.loadFailed'))
      return
    }

    if (!announcementDetail.value.rowVersion) {
      ElMessage.error(t('announcement.message.rowVersionMissing'))
      return
    }

    const confirmed = await confirmAction(t('announcement.message.publishConfirm'))
    if (!confirmed) {
      return
    }

    try {
      const result = await announcementStore.publishAnnouncement(
        announcementDetail.value.id,
        announcementDetail.value.rowVersion,
        { scope: 'platform' }
      )
      if (result) {
        ElMessage.success(t('announcement.message.publishSuccess'))
        announcementDetail.value = result
        formModel.rowVersion = result.rowVersion
        autoSaveCleanup.value?.()
        autoSaveCleanup.value = null
      }
    } catch {
      ElMessage.error(t('announcement.message.publishFailed'))
    }
  }

  const confirmAction = async (message: string) => {
    try {
      // 1. 弹出二次确认
      await ElMessageBox.confirm(message, t('common.tips'), {
        type: 'warning',
        confirmButtonText: t('common.confirm'),
        cancelButtonText: t('common.cancel')
      })

      return true
    } catch {
      return false
    }
  }

  const handleBack = () => {
    // 1. 返回上一页
    router.back()
  }

  const loadDetail = async () => {
    const announcementId = route.params.id ? String(route.params.id) : ''
    if (!announcementId) {
      ElMessage.error(t('announcement.message.missingId'))
      return
    }

    pageLoading.value = true

    try {
      // 1. 直接调用平台公告详情接口
      const detail = await platformAnnouncementApi.detail(announcementId)
      announcementDetail.value = detail

      // 2. 同步表单字段
      applyDetail(detail)

      // 3. 草稿状态下启动自动保存
      if (resolveStatus(detail.status) === 'Draft') {
        autoSaveCleanup.value?.()
        autoSaveCleanup.value = announcementStore.autoSaveDraft(formModel, 30000)
      } else {
        autoSaveCleanup.value?.()
        autoSaveCleanup.value = null
      }
    } catch {
      ElMessage.error(t('announcement.message.loadFailed'))
    } finally {
      pageLoading.value = false
    }
  }

  const applyDetail = (detail: TenantAnnouncementDto) => {
    formModel.title = detail.title
    formModel.content = detail.content
    formModel.announcementType = detail.announcementType
    formModel.priority = detail.priority
    formModel.effectiveFrom = detail.effectiveFrom
    formModel.effectiveTo = detail.effectiveTo ?? null
    formModel.targetType = detail.targetType
    formModel.rowVersion = detail.rowVersion

    const parsed = parseTargetParameters(detail.targetParameters, detail.targetType)
    formModel.targetRules = parsed.targetRules
    formModel.targetUserIds = parsed.targetUserIds
  }

  const parseTargetParameters = (
    raw: string | null | undefined,
    targetType: AnnouncementTargetType
  ) => {
    if (!raw) {
      return { targetRules: undefined, targetUserIds: [] as string[] }
    }

    try {
      const parsed = JSON.parse(raw) as unknown
      if ((targetType === 'Rules' || targetType === 'Roles') && isTargetRules(parsed)) {
        return { targetRules: parsed, targetUserIds: [] as string[] }
      }

      if ((targetType === 'Users' || targetType === 'Manual') && isUserIdsPayload(parsed)) {
        return { targetRules: undefined, targetUserIds: parsed.userIds }
      }
    } catch {
      ElMessage.warning(t('announcement.message.targetParseFailed'))
    }

    return { targetRules: undefined, targetUserIds: [] as string[] }
  }

  const isTargetRules = (value: unknown): value is TargetRules => {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
      return false
    }

    const candidate = value as TargetRules
    const isStringArray = (items?: string[]) =>
      !items || (Array.isArray(items) && items.every((item) => typeof item === 'string'))

    return (
      isStringArray(candidate.departments) &&
      isStringArray(candidate.roles) &&
      isStringArray(candidate.tags)
    )
  }

  const isUserIdsPayload = (value: unknown): value is { userIds: string[] } => {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
      return false
    }

    const candidate = value as { userIds?: unknown }
    return (
      Array.isArray(candidate.userIds) &&
      candidate.userIds.every((item) => typeof item === 'string')
    )
  }

  const formatTime = (value: string) => {
    const date = new Date(value)
    if (Number.isNaN(date.getTime())) {
      return value
    }
    return date.toLocaleTimeString()
  }

  const getTypeLabel = (type: TenantAnnouncementType) => {
    switch (type) {
      case TenantAnnouncementTypeEnum.System:
        return t('announcement.type.system')
      case TenantAnnouncementTypeEnum.Billing:
        return t('announcement.type.billing')
      case TenantAnnouncementTypeEnum.Operation:
        return t('announcement.type.operation')
      case TenantAnnouncementTypeEnum.SYSTEM_PLATFORM_UPDATE:
        return t('announcement.type.platformUpdate')
      case TenantAnnouncementTypeEnum.SYSTEM_SECURITY_NOTICE:
        return t('announcement.type.security')
      case TenantAnnouncementTypeEnum.SYSTEM_COMPLIANCE:
        return t('announcement.type.compliance')
      case TenantAnnouncementTypeEnum.TENANT_INTERNAL:
        return t('announcement.type.tenantInternal')
      case TenantAnnouncementTypeEnum.TENANT_FINANCE:
        return t('announcement.type.tenantFinance')
      case TenantAnnouncementTypeEnum.TENANT_OPERATION:
        return t('announcement.type.tenantOperation')
      default:
        return t('announcement.type.unknown')
    }
  }

  onMounted(() => {
    // 1. 加载详情
    void loadDetail()
  })

  onBeforeUnmount(() => {
    // 1. 清理草稿定时器
    autoSaveCleanup.value?.()
  })
</script>
