<template>
  <view class="record-form-root" :style="themePickerRootStyle">
    <AppNavbar :title="pageTitle" show-back fallback-url="/pages/collaboration/records/index" />

    <view class="page record-form-page">
      <AtTabs
        class="record-form-tabs"
        :current="activeTab"
        :tab-list="tabList"
        scroll
        :swipeable="false"
        @click="switchTab"
      >
        <AtTabsPane :current="activeTab" :index="0">
          <view class="tab-content">
            <view class="field">
              <AtInput v-model:value="form.brand" name="brand" title="品牌" placeholder="请输入品牌" />
            </view>
            <view class="field">
              <AtInput v-model:value="form.goods" name="goods" title="物品" placeholder="请输入物品" />
            </view>
            <view class="field">
              <ThemePicker
                mode="selector"
                :range="optionValues('cooperationPlatform')"
                :value="optionIndex('cooperationPlatform', form.cooperationPlatform)"
                @change="event => setRecordOptionFromPicker('cooperationPlatform', event)"
              >
                <PickableFormItem title="合作平台" :value="form.cooperationPlatform" placeholder="请选择合作平台" />
              </ThemePicker>
            </view>
            <view class="field">
              <ThemePicker mode="date" :value="form.deadline" @change="event => setRecordDateFromPicker('deadline', event)">
                <PickableFormItem title="预完成日期" :value="form.deadline" placeholder="请选择预完成日期" />
              </ThemePicker>
            </view>
            <view class="field">
              <ThemePicker
                mode="selector"
                :range="optionValues('cooperatedMethod')"
                :value="optionIndex('cooperatedMethod', form.cooperatedMethod)"
                @change="event => setRecordOptionFromPicker('cooperatedMethod', event)"
              >
                <PickableFormItem title="合作方式" :value="form.cooperatedMethod" placeholder="请选择合作方式" />
              </ThemePicker>
            </view>
            <view class="field">
              <ThemePicker
                mode="selector"
                :range="optionValues('retainedMethod')"
                :value="optionIndex('retainedMethod', form.retainedMethod)"
                @change="event => setRecordOptionFromPicker('retainedMethod', event)"
              >
                <PickableFormItem title="留存方式" :value="form.retainedMethod" placeholder="请选择留存方式" />
              </ThemePicker>
            </view>
            <view class="field">
              <AtInput
                v-model:value="form.remuneration" name="remuneration"
                title="稿费"
                type="digit"
                placeholder="请输入稿费"
              />
            </view>
            <view class="field">
              <AtInput
                v-model:value="form.imageReturnNum" name="imageReturnNum"
                title="返图数量"
                type="number"
                placeholder="请输入返图数量"
              />
            </view>
            <view class="field">
              <ThemePicker
                mode="selector"
                :range="optionValues('purchaseMethod')"
                :value="optionIndex('purchaseMethod', form.purchaseMethod)"
                @change="event => setRecordOptionFromPicker('purchaseMethod', event)"
              >
                <PickableFormItem title="购入方式" :value="form.purchaseMethod" placeholder="请选择购入方式" />
              </ThemePicker>
            </view>
            <view class="field">
              <AtInput
                v-model:value="form.purchasePrice" name="purchasePrice"
                title="购入金额"
                type="digit"
                placeholder="请输入购入金额"
              />
            </view>
            <view class="field">
              <ThemePicker mode="date" :value="form.purchaseDate" @change="event => setRecordDateFromPicker('purchaseDate', event)">
                <PickableFormItem title="购入日期" :value="form.purchaseDate" placeholder="请选择购入日期" />
              </ThemePicker>
            </view>
            <view class="field">
              <ThemePicker
                mode="selector"
                :range="optionValues('purchasePlatform')"
                :value="optionIndex('purchasePlatform', form.purchasePlatform)"
                @change="event => setRecordOptionFromPicker('purchasePlatform', event)"
              >
                <PickableFormItem title="购入平台" :value="form.purchasePlatform" placeholder="请选择购入平台" />
              </ThemePicker>
            </view>
            <view class="field">
              <AtListItem title="图片" />
              <view class="image-upload-grid">
                <view v-for="file in goodsImageFileList" :key="file.uid || file.url" class="image-preview">
                  <image class="image-preview-img" :src="file.url || file.path" mode="aspectFill" />
                  <view class="upload-delete-btn" @tap.stop="removeUploadedFileByUrl('GOODS_IMAGE', file)">
                    <AtIcon value="close" size="14" :color="themeTokens.color.page" />
                  </view>
                </view>
                <view v-if="canAddGoodsImage" class="image-upload-trigger" @tap="chooseGoodsImages">
                  <AtIcon value="add" size="24" :color="themeTokens.color.textDisabled" />
                  <text>上传图片</text>
                </view>
              </view>
            </view>
            <view class="field">
              <AtListItem title="文件" />
              <AtList v-if="attachmentFileList.length" class="file-list">
                <AtListItem
                  v-for="file in attachmentFileList"
                  :key="file.uid || file.url"
                  :title="file.name || '未命名文件'"
                  :note="file.message"
                >
                  <AtIcon value="trash" size="18" :color="themeTokens.color.danger" @tap.stop="removeUploadedFileByUrl('ATTACHMENT', file)" />
                </AtListItem>
              </AtList>
              <AtButton class="upload-trigger-btn" :disabled="!canAddAttachment" @click="chooseAttachments">
                <template #icon>
                  <AtIcon value="add" size="16" :color="themeTokens.color.primary" />
                </template>
                <text>添加文件</text>
              </AtButton>
            </view>
            <view class="field">
              <AtListItem title="拍摄要求" />
              <AtTextarea
                v-model:value="form.requirements"
                placeholder="请输入拍摄要求"
              />
            </view>
            <view class="field">
              <AtListItem title="备注" />
              <AtTextarea v-model:value="form.remark" placeholder="请输入备注" />
            </view>
          </view>
        </AtTabsPane>

        <AtTabsPane :current="activeTab" :index="1">
          <view class="tab-content">
            <view>
              <view v-for="(task, index) in form.tasks" :key="`task-${index}`" class="child-row-wrapper">
                <AtSwipeAction
                  class="child-swipe-action"
                  :auto-close="true"
                  :options="childDeleteActionOptions"
                  @click="removeTask(index)"
                >
                  <view class="child-row task-row">
                    <ThemePicker class="child-main" mode="date" :value="task.releaseDate" @change="event => setTaskDateFromPicker(index, event)">
                      <PickableFormItem title="完成日期" :value="task.releaseDate" placeholder="请选择完成日期" />
                    </ThemePicker>
                  </view>
                </AtSwipeAction>
              </view>
            </view>
            <AtLoadMore status="noMore" v-if="!form.tasks.length" class="empty small-empty" no-more-text="暂无笔记任务" />
            <AtButton class="add-child-btn" @click="addTask">
              <template #icon>
                <AtIcon value="add" size="16" :color="themeTokens.color.primary" />
              </template>
              <text>添加</text>
            </AtButton>
          </view>
        </AtTabsPane>

        <AtTabsPane :current="activeTab" :index="2">
          <view class="tab-content">
            <view>
              <view v-for="(item, index) in form.expenditures" :key="`expenditure-${index}`" class="child-row-wrapper">
                <AtSwipeAction
                  class="child-swipe-action"
                  :auto-close="true"
                  :options="childDeleteActionOptions"
                  @click="removeExpenditure(index)"
                >
                  <view class="child-panel line-form-row expenditure-row">
                    <AtInput
                      v-model:value="item.amount" name="amount"
                      title="金额"
                      type="digit"
                      placeholder="金额"
                    />
                    <ThemePicker class="child-main" mode="date" :value="item.spendDate" @change="event => setExpenditureDateFromPicker(index, event)">
                      <PickableFormItem title="支出日期" :value="item.spendDate" placeholder="请选择支出日期" />
                    </ThemePicker>
                    <ThemePicker
                      class="child-main"
                      mode="selector"
                      :range="optionValues('expenditurePurpose')"
                      :value="optionIndex('expenditurePurpose', item.purpose)"
                      @change="event => setExpenditurePurposeFromPicker(index, event)"
                    >
                      <PickableFormItem title="用途" :value="item.purpose" placeholder="请选择用途" />
                    </ThemePicker>
                  </view>
                </AtSwipeAction>
              </view>
            </view>
            <AtLoadMore status="noMore" v-if="!form.expenditures.length" class="empty small-empty" no-more-text="暂无支出" />
            <AtButton class="add-child-btn" @click="addExpenditure">
              <template #icon>
                <AtIcon value="add" size="16" :color="themeTokens.color.primary" />
              </template>
              <text>添加</text>
            </AtButton>
          </view>
        </AtTabsPane>

        <AtTabsPane :current="activeTab" :index="3">
          <view class="tab-content">
            <view>
              <view v-for="(item, index) in form.settlements" :key="`settlement-${index}`" class="child-row-wrapper">
                <AtSwipeAction
                  class="child-swipe-action"
                  :auto-close="true"
                  :options="childDeleteActionOptions"
                  @click="removeSettlement(index)"
                >
                  <view class="child-panel line-form-row settlement-row">
                    <AtInput
                      v-model:value="item.income" name="income"
                      title="金额"
                      type="digit"
                      placeholder="金额"
                    />
                    <ThemePicker class="child-main" mode="date" :value="item.settleDate" @change="event => setSettlementDateFromPicker(index, event)">
                      <PickableFormItem title="结款日期" :value="item.settleDate" placeholder="请选择结款日期" />
                    </ThemePicker>
                    <ThemePicker
                      class="child-main"
                      mode="selector"
                      :range="optionValues('settlementMethod')"
                      :value="optionIndex('settlementMethod', item.method)"
                      @change="event => setSettlementMethodFromPicker(index, event)"
                    >
                      <PickableFormItem title="方式" :value="item.method" placeholder="请选择方式" />
                    </ThemePicker>
                    <ThemePicker
                      class="child-main"
                      mode="selector"
                      :range="optionValues('settlementPurpose')"
                      :value="optionIndex('settlementPurpose', item.purpose)"
                      @change="event => setSettlementPurposeFromPicker(index, event)"
                    >
                      <PickableFormItem title="用途" :value="item.purpose" placeholder="请选择用途" />
                    </ThemePicker>
                  </view>
                </AtSwipeAction>
              </view>
            </view>
            <AtLoadMore status="noMore" v-if="!form.settlements.length" class="empty small-empty" no-more-text="暂无结款" />
            <AtButton class="add-child-btn" @click="addSettlement">
              <template #icon>
                <AtIcon value="add" size="16" :color="themeTokens.color.primary" />
              </template>
              <text>添加</text>
            </AtButton>
          </view>
        </AtTabsPane>
      </AtTabs>

      <view class="submit-bar">
        <AtButton class="btn btn-primary submit-btn" @click="submitRecord">提交</AtButton>
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import Taro, { useDidShow } from '@tarojs/taro'
import { computed, reactive, ref } from 'vue'
import {
  addCollaborationRecordApi,
  getCollaborationOptionsApi,
  getCollaborationRecordInfoApi,
  updateCollaborationRecordApi,
  uploadCollaborationFileApi,
  type AddCollaborationRecordCommand,
  type CollaborationExpenditureCommand,
  type CollaborationFileType,
  type CollaborationFileCommand,
  type CollaborationRecordDetailDTO,
  type CollaborationSettlementCommand
} from '@/api/collaboration'
import { isLoggedIn, redirectToLogin } from '@/utils/auth'
import AppNavbar from '@/components/AppNavbar.vue'
import ThemePicker from '@/components/ThemePicker.vue'
import { useThemePickerLockedRootStyle } from '@/components/themePickerLock'
import PickableFormItem from './components/PickableFormItem.vue'
import { themeTokens } from '@/theme/tokens'

type RecordOptionField =
  | 'cooperationPlatform'
  | 'retainedMethod'
  | 'cooperatedMethod'
  | 'purchaseMethod'
  | 'purchasePlatform'
type RecordDateField = 'purchaseDate' | 'deadline'

interface RecordForm {
  recordId?: number
  brand: string
  goods: string
  cooperationPlatform: string
  imageReturnNum: string
  retainedMethod: string
  cooperatedMethod: string
  purchaseMethod: string
  purchasePrice: string
  purchaseDate: string
  purchasePlatform: string
  deadline: string
  remuneration: string
  requirements: string
  remark: string
  tasks: Array<{ releaseDate?: string }>
  expenditures: Array<{ spendDate?: string; amount: string; purpose?: string }>
  settlements: Array<{ settleDate?: string; method?: string; income: string; purpose?: string }>
  files: CollaborationFileCommand[]
}

interface UploadFileItem {
  uid?: string
  name?: string
  url?: string
  path?: string
  status?: string
  message?: string
  type?: string
}

interface SelectedLocalFile {
  path: string
  name?: string
  type?: string
  objectUrl?: string
}

interface DatePickerChangeEvent {
  detail?: {
    value?: string
  }
}

interface SelectorPickerChangeEvent {
  detail?: {
    value?: number | string
  }
}

const MAX_UPLOAD_COUNT = 9
const activeTab = ref(0)
const tabList = [
  { title: '基本信息' },
  { title: '笔记任务' },
  { title: '支出信息' },
  { title: '结款信息' }
]
const DEFAULT_RECORD_OPTION_FIELDS: RecordOptionField[] = [
  'cooperationPlatform',
  'retainedMethod',
  'cooperatedMethod'
]
const optionMap = ref<Record<string, string[]>>({})
const form = reactive(createEmptyForm())
const goodsImageFileList = ref<UploadFileItem[]>([])
const attachmentFileList = ref<UploadFileItem[]>([])
const childDeleteActionOptions = [
  {
    text: '删除',
    style: {
      borderRadius: '8px',
      color: '#fff',
      backgroundColor: themeTokens.color.danger
    }
  }
]
const pageTitle = computed(() => (form.recordId ? '编辑合作记录' : '新增合作记录'))
const themePickerRootStyle = useThemePickerLockedRootStyle()
const canAddGoodsImage = computed(() => canAddUploadFile(goodsImageFileList.value))
const canAddAttachment = computed(() => canAddUploadFile(attachmentFileList.value))

useDidShow(() => {
  if (!isLoggedIn()) {
    redirectToLogin()
    return
  }
  loadPageData()
})

function createEmptyForm(): RecordForm {
  return {
    brand: '',
    goods: '',
    cooperationPlatform: '',
    imageReturnNum: '1',
    retainedMethod: '',
    cooperatedMethod: '',
    purchaseMethod: '',
    purchasePrice: '',
    purchaseDate: '',
    purchasePlatform: '',
    deadline: '',
    remuneration: '',
    requirements: '',
    remark: '',
    tasks: [createEmptyTask()],
    expenditures: [],
    settlements: [],
    files: []
  }
}

function createEmptyTask() {
  return { releaseDate: '' }
}

async function loadPageData() {
  Object.assign(form, createEmptyForm())
  resetUploadFileList()
  activeTab.value = 0
  await loadOptions()
  await loadEditRecord()
  applyDefaultRecordOptions()
}

function switchTab(index: number) {
  activeTab.value = index
}

async function loadOptions() {
  const { data } = await getCollaborationOptionsApi()
  optionMap.value = data.reduce((map, item) => ({ ...map, [item.type]: item.values }), {})
}

async function loadEditRecord() {
  const recordId = getRecordId()
  if (!recordId) return
  const { data } = await getCollaborationRecordInfoApi(recordId)
  Object.assign(form, toRecordForm(data))
  resetUploadFileList()
}

function applyDefaultRecordOptions() {
  DEFAULT_RECORD_OPTION_FIELDS.forEach(field => {
    if (!form[field]) form[field] = optionValues(field)[0] || ''
  })
}

function getRecordId() {
  const params = Taro.getCurrentInstance().router?.params || {}
  return Number(params.recordId || 0)
}

function toRecordForm(record: CollaborationRecordDetailDTO): RecordForm {
  return {
    ...createEmptyForm(),
    ...record,
    recordId: record.recordId,
    imageReturnNum: String(record.imageReturnNum || 1),
    purchasePrice: toFormNumber(record.purchasePrice),
    remuneration: toFormNumber(record.remuneration),
    tasks: record.tasks.length ? record.tasks : [createEmptyTask()],
    expenditures: record.expenditures.map(toExpenditureForm),
    settlements: record.settlements.map(toSettlementForm),
    files: record.files.map(toFileForm)
  }
}

function toFormNumber(value?: number) {
  return value === undefined || value === null ? '' : String(value)
}

function toExpenditureForm(item: CollaborationExpenditureCommand) {
  return { ...item, amount: toFormNumber(item.amount) }
}

function toSettlementForm(item: CollaborationSettlementCommand) {
  return { ...item, income: toFormNumber(item.income) }
}

function toFileForm(item: CollaborationFileCommand) {
  return {
    fileType: item.fileType || 'ATTACHMENT',
    url: item.url || '',
    fileName: item.fileName,
    newFileName: item.newFileName,
    originalFilename: item.originalFilename || ''
  }
}

function resetUploadFileList() {
  goodsImageFileList.value = toUploadFileList('GOODS_IMAGE')
  attachmentFileList.value = toUploadFileList('ATTACHMENT')
}

function toUploadFileList(fileType: CollaborationFileType) {
  return form.files.filter(item => item.fileType === fileType).map(toUploadFileItem)
}

function toUploadFileItem(file: CollaborationFileCommand) {
  return {
    uid: getFileUrl(file),
    name: getFileName(file),
    url: getFileUrl(file),
    status: 'success',
    message: '上传成功'
  }
}

function optionValues(type: string) {
  return optionMap.value[type] || []
}

function optionIndex(type: string, value?: string) {
  return Math.max(optionValues(type).findIndex(item => item === value), 0)
}

function setRecordOptionFromPicker(field: RecordOptionField, event: SelectorPickerChangeEvent) {
  const value = getPickerOptionValue(field, event)
  if (value) form[field] = value
}

function setExpenditurePurposeFromPicker(index: number, event: SelectorPickerChangeEvent) {
  const item = form.expenditures[index]
  const value = getPickerOptionValue('expenditurePurpose', event)
  if (item && value) item.purpose = value
}

function setSettlementMethodFromPicker(index: number, event: SelectorPickerChangeEvent) {
  const item = form.settlements[index]
  const value = getPickerOptionValue('settlementMethod', event)
  if (item && value) item.method = value
}

function setSettlementPurposeFromPicker(index: number, event: SelectorPickerChangeEvent) {
  const item = form.settlements[index]
  const value = getPickerOptionValue('settlementPurpose', event)
  if (item && value) item.purpose = value
}

function getPickerOptionValue(type: string, event: SelectorPickerChangeEvent) {
  const index = Number(event.detail?.value ?? -1)
  return optionValues(type)[index] || ''
}

function setRecordDateFromPicker(field: RecordDateField, event: DatePickerChangeEvent) {
  const value = getPickerDateValue(event)
  if (value) form[field] = value
}

function setTaskDateFromPicker(index: number, event: DatePickerChangeEvent) {
  const task = form.tasks[index]
  const value = getPickerDateValue(event)
  if (task && value) task.releaseDate = value
}

function setExpenditureDateFromPicker(index: number, event: DatePickerChangeEvent) {
  const item = form.expenditures[index]
  const value = getPickerDateValue(event)
  if (item && value) item.spendDate = value
}

function setSettlementDateFromPicker(index: number, event: DatePickerChangeEvent) {
  const item = form.settlements[index]
  const value = getPickerDateValue(event)
  if (item && value) item.settleDate = value
}

function getPickerDateValue(event: DatePickerChangeEvent) {
  return event.detail?.value || ''
}

function addTask() {
  form.tasks.push(createEmptyTask())
}

function removeTask(index: number) {
  form.tasks.splice(index, 1)
}

function addExpenditure() {
  form.expenditures.push({ spendDate: '', amount: '', purpose: '' })
}

function removeExpenditure(index: number) {
  form.expenditures.splice(index, 1)
}

function addSettlement() {
  form.settlements.push({ settleDate: '', method: '', income: '', purpose: '' })
}

function removeSettlement(index: number) {
  form.settlements.splice(index, 1)
}

async function chooseGoodsImages() {
  const count = getRemainingUploadCount(goodsImageFileList.value)
  if (!count) return showMaxUploadToast()
  try {
    const { tempFiles } = await Taro.chooseImage({
      count,
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera']
    })
    await uploadSelectedFiles(tempFiles.map(toSelectedLocalFile), 'GOODS_IMAGE')
  } catch (error) {
    handleChooseFileError(error)
  }
}

async function chooseAttachments() {
  const count = getRemainingUploadCount(attachmentFileList.value)
  if (!count) return showMaxUploadToast()
  try {
    const files = await chooseAttachmentFiles(count)
    await uploadSelectedFiles(files, 'ATTACHMENT')
  } catch (error) {
    handleChooseFileError(error)
  }
}

async function uploadSelectedFiles(files: SelectedLocalFile[], fileType: CollaborationFileType) {
  for (const file of files.filter(item => item.path)) {
    try {
      await uploadSelectedFile(createUploadFileItem(file, fileType), fileType)
    } finally {
      releaseSelectedLocalFile(file)
    }
  }
}

async function uploadSelectedFile(fileItem: UploadFileItem, fileType: CollaborationFileType) {
  if (!fileItem.path) return
  appendUploadFile(fileItem, fileType)
  try {
    const { data } = await uploadCollaborationFileApi(fileItem.path, fileItem.name)
    form.files.push(toFileCommand(data, fileType))
    markUploadedFile(fileType, fileItem, data.url)
  } catch (error) {
    handleUploadError({ error, fileItem, fileType })
  }
}

function removeUploadedFileByUrl(fileType: CollaborationFileType, file: UploadFileItem) {
  const fileUrl = file.url || file.path
  if (!fileUrl) return
  const index = form.files.findIndex(item => item.fileType === fileType && getFileUrl(item) === fileUrl)
  if (index >= 0) {
    form.files.splice(index, 1)
  }
  removeUploadFile(fileType, file)
}

function toSelectedLocalFile(file): SelectedLocalFile {
  const path = file.path || file.tempFilePath || ''
  const fileName = file.name || file.originalFileObj?.name || getPathFileName(path)
  return {
    path,
    name: fileName,
    type: file.type
  }
}

async function chooseAttachmentFiles(count: number) {
  if (isWebEnv()) {
    return chooseWebFiles(count)
  }
  const { tempFiles } = await Taro.chooseMessageFile({ count, type: 'all' })
  return tempFiles.map(toSelectedLocalFile)
}

function chooseWebFiles(count: number) {
  return new Promise<SelectedLocalFile[]>(resolve => {
    const input = createWebFileInput(count)
    let isResolved = false
    const resolveFiles = () => {
      if (isResolved) return
      isResolved = true
      cleanupWebFileInput(input, resolveFiles, resolveOnFocus)
      resolve(Array.from(input.files || []).slice(0, count).map(toSelectedWebFile))
    }
    const resolveOnFocus = () => setTimeout(resolveFiles, 200)
    input.addEventListener('change', resolveFiles)
    window.addEventListener('focus', resolveOnFocus, { once: true })
    document.body.appendChild(input)
    input.click()
  })
}

function createWebFileInput(count: number) {
  const input = document.createElement('input')
  input.type = 'file'
  input.multiple = count > 1
  input.style.display = 'none'
  return input
}

function cleanupWebFileInput(input: HTMLInputElement, onChange: EventListener, onFocus: EventListener) {
  input.removeEventListener('change', onChange)
  window.removeEventListener('focus', onFocus)
  input.remove()
}

function toSelectedWebFile(file: File): SelectedLocalFile {
  const objectUrl = URL.createObjectURL(file)
  return { path: objectUrl, name: file.name, type: file.type, objectUrl }
}

function releaseSelectedLocalFile(file: SelectedLocalFile) {
  if (file.objectUrl) URL.revokeObjectURL(file.objectUrl)
}

function isWebEnv() {
  return Taro.getEnv() === Taro.ENV_TYPE.WEB
}

function createUploadFileItem(file: SelectedLocalFile, fileType: CollaborationFileType) {
  return {
    uid: createUploadUid(),
    name: file.name || getPathFileName(file.path),
    path: file.path,
    url: fileType === 'GOODS_IMAGE' ? file.path : '',
    status: 'uploading',
    message: '上传中',
    type: file.type || getDefaultUploadType(fileType)
  }
}

function appendUploadFile(file: UploadFileItem, fileType: CollaborationFileType) {
  getUploadFileList(fileType).push(file)
}

function getUploadFileList(fileType: CollaborationFileType) {
  return fileType === 'GOODS_IMAGE' ? goodsImageFileList.value : attachmentFileList.value
}

function canAddUploadFile(fileList: UploadFileItem[]) {
  return fileList.length < MAX_UPLOAD_COUNT
}

function getRemainingUploadCount(fileList: UploadFileItem[]) {
  return Math.max(MAX_UPLOAD_COUNT - fileList.length, 0)
}

function showMaxUploadToast() {
  Taro.showToast({ title: `最多上传${MAX_UPLOAD_COUNT}个文件`, icon: 'none' })
}

function handleChooseFileError(error: unknown) {
  if (isCancelChooseError(error)) return
  Taro.showToast({ title: getErrorMessage(error) || '选择文件失败', icon: 'none' })
}

function isCancelChooseError(error: unknown) {
  return /cancel|取消/i.test(getErrorMessage(error))
}

function getErrorMessage(error: unknown) {
  if (error instanceof Error) return error.message
  return String((error as { errMsg?: string })?.errMsg || '')
}

function getPathFileName(path: string) {
  return path.split('/').pop() || '未命名文件'
}

function createUploadUid() {
  return `${Date.now()}-${Math.random().toString(16).slice(2)}`
}

function getDefaultUploadType(fileType: CollaborationFileType) {
  return fileType === 'GOODS_IMAGE' ? 'image' : 'file'
}

function markUploadedFile(fileType: CollaborationFileType, file: UploadFileItem, url: string) {
  const fileList = getUploadFileList(fileType)
  const index = findUploadFileIndex(fileList, file)
  if (index < 0) return
  fileList[index] = {
    ...fileList[index],
    url,
    status: 'success',
    message: '上传成功'
  }
}

function removeUploadFile(fileType: CollaborationFileType, file: UploadFileItem) {
  const fileList = getUploadFileList(fileType)
  const index = findUploadFileIndex(fileList, file)
  if (index >= 0) {
    fileList.splice(index, 1)
  }
}

function findUploadFileIndex(fileList: UploadFileItem[], file: UploadFileItem) {
  return fileList.findIndex(item => item.uid === file.uid)
}

function handleUploadError(options: { error: unknown; fileItem: UploadFileItem; fileType: CollaborationFileType }) {
  removeUploadFile(options.fileType, options.fileItem)
  Taro.showToast({ title: getErrorMessage(options.error) || '上传失败', icon: 'none' })
}

function toFileCommand(file, fileType: CollaborationFileType) {
  return {
    fileType,
    url: file.url,
    fileName: file.fileName,
    newFileName: file.newFileName,
    originalFilename: file.originalFilename
  }
}

function getFileName(file: CollaborationFileCommand) {
  return file.originalFilename || file.newFileName || '未命名文件'
}

function getFileUrl(file: CollaborationFileCommand) {
  return file.url || file.fileName || ''
}

async function submitRecord() {
  if (!validateRecord()) return
  const command = toCommand()
  if (form.recordId) {
    await updateCollaborationRecordApi({ ...command, recordId: form.recordId })
  } else {
    await addCollaborationRecordApi(command)
  }
  Taro.showToast({ title: '提交成功', icon: 'success' })
  returnToRecords()
}

function validateRecord() {
  if (!form.brand || !form.goods || !form.deadline) {
    Taro.showToast({ title: '请填写品牌、物品和预完成日期', icon: 'none' })
    activeTab.value = 0
    return false
  }
  return true
}

function toCommand(): AddCollaborationRecordCommand {
  return {
    ...form,
    imageReturnNum: Number(form.imageReturnNum || 1),
    purchasePrice: toNumber(form.purchasePrice),
    remuneration: toNumber(form.remuneration),
    tasks: form.tasks,
    expenditures: form.expenditures.map(toExpenditureCommand),
    settlements: form.settlements.map(toSettlementCommand),
    files: form.files.filter(item => item.url)
  }
}

function toNumber(value: string) {
  return value ? Number(value) : undefined
}

function toExpenditureCommand(item: RecordForm['expenditures'][number]) {
  return { ...item, amount: toNumber(item.amount) }
}

function toSettlementCommand(item: RecordForm['settlements'][number]) {
  return { ...item, income: toNumber(item.income) }
}

function returnToRecords() {
  if (Taro.getCurrentPages().length > 1) {
    Taro.navigateBack()
    return
  }
  Taro.reLaunch({ url: '/pages/collaboration/records/index' })
}
</script>

<style lang="scss">
.record-form-root {
  background: $bg-page;
}

.record-form-page {
  padding-bottom: calc($page-bottom-space + env(safe-area-inset-bottom));
  background: $bg-page;
}

.record-form-tabs {
  margin-bottom: $space-xl;
}

.record-form-tabs.at-tabs {
  height: auto;
  overflow: visible;
}

.record-form-tabs .at-tabs__body,
.record-form-tabs .at-tabs-pane--active {
  overflow: visible;
}

.tab-content {
  padding-top: $space-md;
}

.add-child-btn.at-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: $control-height;
  padding: 0;
  margin: $space-lg 0 0;
  font-size: $font-md;
  line-height: $control-height;
  color: $color-primary;
  background: $bg-page !important;
  border: 1px dashed $color-primary-border;
  border-radius: $radius-md;
}

.add-child-btn .at-button__icon {
  display: inline-flex;
  align-items: center;
  margin-right: 8px;
}

.file-list {
  width: 100%;
}

.image-upload-grid {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
}

.image-upload-trigger {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 144px;
  height: 144px;
  margin-right: 10px;
  margin-bottom: 10px;
  font-size: $font-sm;
  line-height: 32px;
  color: $text-disabled;
  background: $bg-page !important;
  border: 1px dashed $border-color-strong;
  border-radius: $radius-sm;
}

.image-upload-trigger text {
  margin-top: 8px;
}

.image-preview {
  position: relative;
  width: 144px;
  height: 144px;
  margin-right: 10px;
  margin-bottom: 10px;
  overflow: hidden;
  background: $bg-muted;
  border-radius: $radius-sm;
}

.image-preview-img {
  width: 100%;
  height: 100%;
}

.upload-delete-btn {
  position: absolute;
  top: 6px;
  right: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: rgb(0 0 0 / 55%);
  border-radius: 50%;
}

.upload-trigger-btn.at-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: $control-height;
  padding: 0;
  margin-top: $space-sm;
  font-size: $font-md;
  line-height: $control-height;
  color: $color-primary;
  background: $bg-page !important;
  border: 1px dashed $color-primary-border;
  border-radius: $radius-md;
}

.upload-trigger-btn .at-button__icon {
  display: inline-flex;
  align-items: center;
  margin-right: 8px;
}

.child-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  align-items: center;
}

.child-row-wrapper {
  margin-top: 0;
}

.child-row-wrapper + .child-row-wrapper {
  padding-top: $space-md;
  margin-top: $space-md;
}

.task-row {
  background: $bg-page !important;
}

.child-swipe-action {
  overflow: hidden;
  border-radius: $radius-md;
}

.child-swipe-action.at-swipe-action {
  background: transparent;
}

.child-swipe-action .at-swipe-action__content {
  overflow: hidden;
  background: $bg-page;
  border-radius: $radius-md;
}

.child-swipe-action .at-swipe-action__options {
  top: 0;
  bottom: 0;
  height: auto;
  padding-left: $space-xs;
}

.child-panel {
  display: grid;
  gap: 12px;
  padding: 0;
  background: transparent;
  border-radius: $radius-md;
}

.child-main {
  min-width: 0;
}

.line-form-row {
  align-items: center;
  overflow: visible;
}

.expenditure-row {
  grid-template-columns: minmax(0, 1fr);
}

.settlement-row {
  grid-template-columns: minmax(0, 1fr);
}

.small-empty {
  padding: 40px 0;
}

.submit-bar {
  position: fixed;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1000;
  padding: $space-md $space-xl calc(#{$space-md} + env(safe-area-inset-bottom));
  background: $bg-page;
  border-top: 1px solid $border-color;
}

.submit-btn.at-button {
  margin: 0;
}
</style>
