<template>
  <n-drawer
    class="top0"
    to="#main"
    :show="show"
    width="5.2rem"
    :mask-closable="false"
  >
    <n-drawer-content>
      <template #header>
        <div class="head">
          <p>{{ mode ? basicData.name : '新增活动' }}</p>
          <n-space>
            <n-button size="small" @click="closeDrawer">取消</n-button>
            <template v-if="mode === 'view'">
              <n-button type="error" size="small" @click="mode = 'modify'">
                编辑
              </n-button>
              <n-button type="primary" size="small" @click="handleExport">
                <template #icon>
                  <n-icon size=".12rem">
                    <svg-icon :data="exportIcon" original />
                  </n-icon>
                </template>
                导出
              </n-button>
            </template>
            <n-button v-else type="primary" size="small" @click="submit">
              完成
            </n-button>
          </n-space>
        </div>
      </template>
      <div class="content" :class="{ 'view-mode': mode === 'view' }">
        <div>
          <p class="title">基本信息</p>
          <n-form
            ref="basicRef"
            :model="basicData"
            :rules="rules"
            size="small"
            label-placement="top"
          >
            <n-grid :cols="24" :x-gap="12">
              <n-form-item-gi :span="12" label="活动名称" path="name">
                <p v-if="mode === 'view'">{{ basicData.name }}</p>
                <n-input v-else v-model:value="basicData.name" />
              </n-form-item-gi>
              <n-form-item-gi :span="12" label="标签类别" path="type">
                <p v-if="mode === 'view'">
                  {{
                    typeOptions.find((e) => e.value === basicData.type)?.label
                  }}
                </p>
                <n-select
                  v-else
                  v-model:value="basicData.type"
                  :options="typeOptions"
                />
              </n-form-item-gi>
              <n-form-item-gi
                :span="24"
                :label="`党组织名称${
                  mode === 'view' ? '' : '（下拉或输入关键字选择）'
                }`"
                path="orgName"
              >
                <p v-if="mode === 'view'">
                  {{
                    orgOptions.find((e) => e.value === basicData.orgName)?.label
                  }}
                </p>
                <n-select
                  v-else
                  v-model:value="basicData.orgName"
                  :options="orgOptions"
                  filterable
                />
              </n-form-item-gi>
              <n-form-item-gi :span="12" label="活动日期" path="date">
                <p v-if="mode === 'view'">
                  {{ dayjs(basicData.date).format('ll') }}
                </p>
                <n-date-picker
                  v-else
                  v-model:value="basicData.date"
                  style="width: 100%"
                />
              </n-form-item-gi>
              <n-form-item-gi
                :span="24"
                :label="`活动地址${
                  mode === 'view'
                    ? ''
                    : '（请具体填写，如“XX区XX路XX号XX中心”）'
                }`"
                path="address"
              >
                <p v-if="mode === 'view'">{{ basicData.address }}</p>
                <n-input v-else v-model:value="basicData.address" />
              </n-form-item-gi>
            </n-grid>
          </n-form>
        </div>
        <div>
          <p class="title">
            人员参与情况
            <span>
              党员总数：
              <span>{{ totalPerson }}人</span>
            </span>
          </p>
          <n-form
            ref="memberRef"
            :model="memberData"
            :rules="rules"
            size="small"
            label-placement="top"
          >
            <n-grid :cols="24" :x-gap="12">
              <n-form-item-gi :span="12" label="实际参与人数" path="count">
                <p v-if="mode === 'view'">{{ memberData.count }}</p>
                <n-input-number
                  v-else
                  v-model:value="memberData.count"
                  size="small"
                  :show-button="false"
                  :validator="checkMemberCount"
                >
                  <template #suffix>人</template>
                </n-input-number>
              </n-form-item-gi>
              <n-form-item-gi
                :span="12"
                label="不计入参与活动党员人数"
                path="excludeCount"
              >
                <p v-if="mode === 'view'">{{ memberData.excludeCount }}</p>
                <n-input-number
                  v-else
                  v-model:value="memberData.excludeCount"
                  size="small"
                  :show-button="false"
                  :validator="checkMemberCount"
                >
                  <template #suffix>人</template>
                </n-input-number>
              </n-form-item-gi>
              <n-form-item-gi
                :span="24"
                :label="`电子表格或签到照片${
                  mode === 'view' ? '' : '（大小20M以内）'
                }`"
                path="fileType"
              >
                <n-select
                  v-if="mode !== 'view'"
                  v-model:value="memberData.fileType"
                  :options="fileOptions"
                  placeholder="请选择上传类型"
                />
              </n-form-item-gi>
              <n-form-item-gi
                v-if="memberData.fileType === 'file'"
                :span="24"
                path="attachment"
                class="no-label"
              >
                <n-upload
                  :default-file-list="memberData.attachment || []"
                  style="width: 100%"
                  accept=".docx,.doc,.xlsx,.xls,.csv,.txt"
                  :on-change="(e) => onChange(e, 'memberData.attachment')"
                  :show-remove-button="mode !== 'view'"
                >
                  <n-button> 上传附件 </n-button>
                </n-upload>
              </n-form-item-gi>
              <n-form-item-gi
                v-if="memberData.fileType === 'photo'"
                :span="24"
                path="attachmentPhoto"
                class="no-label"
                :style="mode === 'view' ? 'margin-top:-0.6rem' : null"
              >
                <n-upload
                  style="width: 100%"
                  :default-file-list="memberData.attachmentPhoto || []"
                  accept="image/jpg,image/jpeg,image/png,image/img"
                  list-type="image-card"
                  :show-remove-button="mode !== 'view'"
                  :on-change="(e) => onChange(e, 'memberData.attachmentPhoto')"
                  @preview="handlePreview"
                >
                  点击上传
                </n-upload>
              </n-form-item-gi>
            </n-grid>
          </n-form>
        </div>
        <div>
          <p class="title">活动详情</p>
          <n-form
            ref="detailRef"
            :model="detailData"
            :rules="rules"
            size="small"
            label-placement="top"
          >
            <n-grid :cols="24" :x-gap="12">
              <n-form-item-gi
                :span="24"
                :label="`活动内容描述或描述照片${
                  mode === 'view' ? '' : '（大小20M以内）'
                }`"
                path="describeType"
              >
                <template v-if="mode === 'view'">
                  <p v-if="detailData.describeType === 'text'">
                    {{ detailData.attachment }}
                  </p>
                </template>
                <n-select
                  v-else
                  v-model:value="detailData.describeType"
                  :options="describeOptions"
                  placeholder="请选择上传类型"
                />
              </n-form-item-gi>
              <n-form-item-gi
                v-if="detailData.describeType === 'text' && mode !== 'view'"
                :span="24"
                path="attachment"
                class="no-label"
              >
                <n-input
                  v-model:value="detailData.attachment"
                  type="textarea"
                />
              </n-form-item-gi>
              <n-form-item-gi
                v-if="detailData.describeType === 'photo'"
                :span="24"
                path="attachmentPhoto"
                class="no-label"
              >
                <n-upload
                  style="width: 100%"
                  :default-file-list="detailData.attachmentPhoto || []"
                  accept="image/jpg,image/jpeg,image/png,image/img"
                  list-type="image-card"
                  :show-remove-button="mode !== 'view'"
                  :on-change="(e) => onChange(e, 'detailData.attachmentPhoto')"
                  @preview="handlePreview"
                >
                  点击上传
                </n-upload>
              </n-form-item-gi>
              <n-form-item-gi
                :span="24"
                :label="`活动照片${
                  mode === 'view'
                    ? ''
                    : '（格式为jpg、jpeg、png、img， 大小20M以内）'
                }`"
                path="photoList"
              >
                <n-upload
                  style="width: 100%"
                  :default-file-list="detailData.photoList || []"
                  accept="image/jpg,image/jpeg,image/png,image/img"
                  list-type="image-card"
                  :show-remove-button="mode !== 'view'"
                  :on-change="(e) => onChange(e, 'detailData.photoList')"
                  @preview="handlePreview"
                >
                  点击上传
                </n-upload>
              </n-form-item-gi>
            </n-grid>
          </n-form>
        </div>
      </div>
    </n-drawer-content>
  </n-drawer>
  <n-modal
    v-model:show="showPhoto"
    preset="card"
    style="width: 30%"
    title="照片预览"
  >
    <img :src="previewImageUrl" style="width: 100%" />
  </n-modal>
</template>

<script lang="ts" setup>
import store from '@/store'
import { computed, onMounted, PropType, ref, watch } from 'vue'
import { FormRules, NForm, useMessage } from 'naive-ui'
import exportIcon from '@images/export.svg'
import { activity } from '@/util/tags'
import { useFetchOrg, usePostActivity, usePutActivity } from '@/hooks/useFetch'
import dayjs from '@/util/dayjs'
import useAliOss from '@/hooks/useAliOss'
import useExportFile from '@/hooks/useExportFile'

const message = useMessage()
const props = defineProps({
  data: {
    type: Object as PropType<{ [key: string]: any }>,
    default: null,
  },
  cb: {
    type: Function as PropType<(query?: string) => unknown>,
    default: null,
  },
})
const mode = ref<string | null>(null)

const orgOptions = ref<any[]>([])
onMounted(async () => {
  orgOptions.value = (
    await useFetchOrg({
      a: 'id,count',
      keys: '党组织名称',
    })
  )?.map((item: any) => ({
    label: item['党组织名称'],
    value: item['党组织名称'],
  }))
})

const show = computed(() => store.state.showNewActivityDrawer)
const closeDrawer = () => {
  store.commit('SET_NEW_ACTIVITY_DRAWER', false)
  basicData.value = {}
  memberData.value = {}
  detailData.value = {}
  mode.value = null
}

const typeOptions = computed(() => {
  return activity.map((item) => ({
    label: item.name,
    value: item.name,
  }))
})
const fileOptions = [
  { label: '电子表格（docx、doc、xlsx、xls、csv、txt）', value: 'file' },
  { label: '签到照片（jpg、jpeg、png、img）', value: 'photo' },
]
const describeOptions = [
  { label: '活动内容描述', value: 'text' },
  { label: '描述照片（jpg、jpeg、png、img）', value: 'photo' },
]

const basicRef = ref<typeof NForm | null>(null)
const memberRef = ref<typeof NForm | null>(null)
const detailRef = ref<typeof NForm | null>(null)
const basicData = ref<any>({})
const memberData = ref<any>({})
const detailData = ref<any>({})

watch(
  () => props.data,
  (data) => {
    if (!data) {
      basicData.value = {}
      memberData.value = {}
      detailData.value = {}
      return
    }
    getPersonNum(data['党组织名称'])
    basicData.value = {
      name: data['活动名称'],
      type: data['标签类别'],
      orgName: data['党组织名称'],
      date: +(data['活动日期'] + '000') || null,
      address: data['活动地址'],
    }
    const isFile = data['签到表文件'] && data['签到表文件'].length > 0
    const isPhoto = data['签到表照片'] && data['签到表照片'].length > 0
    const fileType = isFile ? 'file' : isPhoto ? 'photo' : null
    memberData.value = {
      count: data['实际参与人数'],
      excludeCount: data['不计入参与活动党员人数'],
      fileType,
      attachment: fileType === 'file' ? data['签到表文件'] : [],
      attachmentPhoto:
        fileType === 'photo'
          ? (data['签到表照片'] || []).map((url: string) => ({
              url,
              status: 'finished',
            }))
          : [],
    }

    const isText = data['活动内容描述']
    const isImage = data['台账记录照片'] && data['台账记录照片'].length > 0
    const describeType = isText ? 'text' : isImage ? 'photo' : null
    detailData.value = {
      describeType,
      attachment: describeType === 'text' ? data['活动内容描述'] : '',
      attachmentPhoto:
        describeType === 'photo'
          ? (data['台账记录照片'] || []).map((url: string) => ({
              url,
              status: 'finished',
            }))
          : [],
      photoList:
        (data['活动照片'] || []).map((url: string) => ({
          url,
          status: 'finished',
        })) || [],
    }
    mode.value = data._mode || null
  },
  { immediate: true },
)

const rules: FormRules = {
  name: {
    required: true,
    trigger: ['blur', 'input'],
    message: '请输入活动名称',
  },
  type: {
    required: true,
    trigger: ['blur', 'change'],
    message: '请选择标签类别',
  },
  orgName: {
    required: true,
    trigger: ['blur', 'change'],
    message: '请选择党组织',
  },
  date: {
    type: 'number',
    required: true,
    trigger: ['blur', 'change'],
    message: '请选择活动日期',
  },
  address: {
    required: true,
    trigger: ['blur', 'input'],
    message: '请输入活动地址',
  },
  count: [
    {
      type: 'number',
      required: true,
      trigger: ['blur', 'input'],
      message: '请输入实际参与人数',
    },
    {
      type: 'number',
      validator: (_, val) => checkMemberCount(val),
      message: '不能大于党员总数',
      trigger: ['blur', 'input'],
    },
  ],
  excludeCount: [
    {
      type: 'number',
      required: true,
      trigger: ['blur', 'input'],
      message: '请输入不计入参与活动党员人数',
    },
    {
      type: 'number',
      validator: (_, val) => checkMemberCount(val),
      message: '不能大于党员总数',
      trigger: ['blur', 'input'],
    },
  ],
  fileType: {
    required: true,
    trigger: ['blur', 'change'],
    message: '请选择上传类型',
  },
  describeType: {
    required: true,
    trigger: ['blur', 'change'],
    message: '请选择描述类型',
  },
}

const submit = () => {
  basicRef.value?.validate((errors: any) => {
    if (errors) return
    memberRef.value?.validate((errors: any) => {
      if (errors) return
      detailRef.value?.validate(async (errors: any) => {
        if (errors) return
        const { name, type, orgName, date, address } = basicData.value
        const { count, excludeCount, attachment, attachmentPhoto, fileType } =
          memberData.value
        const {
          attachment: detailAttachment,
          attachmentPhoto: detailAttachmentPhoto,
          describeType,
          photoList,
        } = detailData.value
        const data: any = {
          活动名称: name,
          标签类别: type,
          党组织名称: orgName,
          活动日期: +(date + '').slice(0, 10), // 截掉10位后的10，不然这接口会认为不是时间戳
          活动地址: address,
          实际参与人数: count,
          不计入参与活动党员人数: excludeCount,
          活动照片: photoList?.map((item: any) => item.url) || [],
          出席率:
            totalPerson.value === excludeCount
              ? 0
              : getPercent(
                  Math.round(
                    (count / (totalPerson.value - excludeCount)) * 100,
                  ),
                ),
        }
        if (fileType === 'file') {
          data['签到表文件'] = attachment?.map((item: any) => item.url) || []
          data['签到表照片'] = []
        } else if (fileType === 'photo') {
          data['签到表照片'] =
            attachmentPhoto?.map((item: any) => item.url) || []
          data['签到表文件'] = []
        }
        if (describeType === 'text') {
          data['活动内容描述'] = detailAttachment
          data['台账记录照片'] = []
        } else if (describeType === 'photo') {
          data['台账记录照片'] =
            detailAttachmentPhoto?.map((item: any) => item.url) || []
          data['活动内容描述'] = ''
        }
        if (mode.value === 'modify') {
          await usePutActivity({
            separate: [
              {
                id: props.data.id,
                extra: data,
              },
            ],
          })
          closeDrawer()
          props.cb && props.cb()
          message.success('活动修改成功')
        } else {
          await usePostActivity({
            extra: data,
          })
          closeDrawer()
          props.cb && props.cb()
          message.success('活动新增成功')
        }
      })
    })
  })
}

// const previewFileList = ref([
//   {
//     url: 'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg',
//   },
// ])
const previewImageUrl = ref('')
const showPhoto = ref(false)
function handlePreview({ url }: any) {
  previewImageUrl.value = url
  showPhoto.value = true
}

function getPercent(val: number) {
  if (val > 100) return 100
  return val
}

async function onChange(options: any, type: string) {
  console.log('change', options, type)
  if (!options || !options.fileList || options.fileList.length === 0) return
  const urls = await Promise.all(
    options.fileList.map(async (item: any) => await useAliOss(item.file)),
  )

  switch (type) {
    case 'memberData.attachment':
      memberData.value.attachment = urls
      break
    case 'memberData.attachmentPhoto':
      memberData.value.attachmentPhoto = urls
      break
    case 'detailData.attachmentPhoto':
      detailData.value.attachmentPhoto = urls
      break
    case 'detailData.photoList':
      detailData.value.photoList = urls
      break
    default:
      break
  }
}

const totalPerson = ref(0)
async function getPersonNum(name: string) {
  if (!name) return 0
  return (
    (
      await useFetchOrg({
        keys: '党员数量',
        q: `paths @ "党组织名称" && string == "${name}"`,
      })
    )?.[0]?.['党员数量'] || 0
  )
}
watch(
  () => basicData.value.orgName,
  async (name) => {
    totalPerson.value = await getPersonNum(name)
  },
)

function checkMemberCount(val: number) {
  return val >= 0 && val <= totalPerson.value
}
const handleExport = async () => {
  const { name, type, orgName, date, address } = basicData.value
  const { count, excludeCount } = memberData.value
  const { attachment } = detailData.value
  const data = [
    {
      活动名称: name,
      标签类别: type,
      党组织名称: orgName,
      活动日期: dayjs(date).format('ll'), // 截掉10位后的10，不然这接口会认为不是时间戳
      活动地址: address,
    },
    {
      实际参与人数: count,
      不计入参与活动党员人数: excludeCount,
      出席率:
        totalPerson.value === excludeCount
          ? '0%'
          : getPercent(
              Math.round((count / (totalPerson.value - excludeCount)) * 100),
            ) + '%',
    },
    {
      活动内容描述: attachment,
      // TODO 测试图片
      活动照片: [
        'https://raw.githubusercontent.com/dolanmiu/docx/master/demo/images/cat.jpg',
        'https://raw.githubusercontent.com/dolanmiu/docx/master/demo/images/cat.jpg',
      ],
    },
  ]
  await useExportFile(
    [
      {
        _title: '基本信息',
        ...data[0],
      },
      {
        _title: '人员参与情况',
        ...data[1],
      },
      {
        _title: '活动详情',
        ...data[2],
      },
    ],
    '_title',
    basicData.value.name,
  )
}
</script>

<style lang="stylus" scoped>
@import '../../components/MyComponent/main.styl'
.head
  width 100%
  $flex-align()
  justify-content space-between
.content
  height 100%
  overflow-y auto
  background #f7f7f7
  padding .08rem .1rem
  box-sizing border-box
  p
    font-size .11rem
    padding-left .02rem
  >div
    background $white-bg
    border-radius .04rem
    margin-bottom .08rem
    padding .08rem
    overflow hidden
    box-sizing border-box
    .title
      font-family $font-ping-medium
      margin-bottom .1rem
      font-size .14rem
      $flex-align()
      &:before
        content ''
        display inline-block
        width .02rem
        height .14rem
        background $red
        margin-right .06rem
      >span
        flex 1
        text-align right
        font-family $font-ping
        font-size .1rem
        >span
          color $blue
</style>
<style lang="stylus">
@import '../../components/MyComponent/main.styl'
.n-drawer.n-drawer--right-placement.top0
  top 0
  .n-drawer-header__main
    width 100%
  .n-input-number
    width 100%
    .n-input-wrapper
      padding-right 0
    .n-input__suffix
      background #f3f4f7
      border-left .01rem solid $light-gray
      padding 0 .1rem

.content
  .n-upload
    .n-upload-file-list.n-upload-file-list--grid
      min-height .9rem
  &.view-mode
    .n-upload__trigger.n-upload__trigger--image-card
      display none !important
  .no-label
    margin-top -0.3rem
</style>
