import {AlertComponent, attachmentAdpator, makeTranslator, render, type Schema, ToastComponent} from 'amis'
import 'amis/lib/themes/antd.css'
import 'amis/lib/helper.css'
import 'amis/sdk/iconfont.css'
import '@fortawesome/fontawesome-free/css/all.min.css'
import axios from 'axios'
import {isEqual} from 'es-toolkit'

export const commonInfo = {
  debug: isEqual(import.meta.env.MODE, 'development'),
  baseUrl: isEqual(import.meta.env.MODE, 'development') ? 'http://localhost:27891' : '',
}

const __ = makeTranslator('zh')

const responseAdaptor = () => (response: any) => {
  let payload = response.data || {} // blob 下可能会返回内容为空？
  if (payload.hasOwnProperty('errno')) {
    payload.status = payload.errno
    payload.msg = payload.errmsg
  } else if (payload.hasOwnProperty('no')) {
    payload.status = payload.no
    payload.msg = payload.error
  }
  return {
    ...response,
    data: payload,
  }
}

export const amisRender = (schema: Schema, data: Record<any, any> = {}) => {
  const theme = 'antd'
  const locale = 'zh-CN'
  return (
    <>
      <ToastComponent
        theme={theme}
        key="toast"
        position={'top-right'}
        locale={locale}
      />
      <AlertComponent theme={theme} key="alert" locale={locale}/>
      {render(
        schema,
        {
          data: {
            ...commonInfo,
            ...data,
          },
          theme: theme,
        },
        {
          enableAMISDebug: commonInfo.debug,
          fetcher: async (api: any) => {
            let {url, method, data, responseType, config, headers} = api
            config = config || {}
            config.url = url
            config.withCredentials = true
            responseType && (config.responseType = responseType)

            if (config.cancelExecutor) {
              config.cancelToken = new (axios as any).CancelToken(
                config.cancelExecutor,
              )
            }

            config.headers = headers || {}
            config.method = method
            config.data = data

            if (method === 'get' && data) {
              config.params = data
            } else if (data && data instanceof FormData) {
              // config.headers['Content-Type'] = 'multipart/form-data';
            } else if (
              data &&
              typeof data !== 'string' &&
              !(data instanceof Blob) &&
              !(data instanceof ArrayBuffer)
            ) {
              data = JSON.stringify(data)
              config.headers['Content-Type'] = 'application/json'
            }

            // 支持返回各种报错信息
            config.validateStatus = function () {
              return true
            }

            let response = await axios(config)
            response = await attachmentAdpator(response, __, api)
            response = responseAdaptor()(response)

            if (response.status >= 400) {
              if (response.data) {
                // 主要用于 raw: 模式下，后端自己校验登录，
                if (
                  response.status === 401 &&
                  response.data.location &&
                  response.data.location.startsWith('http')
                ) {
                  location.href = response.data.location.replace(
                    '{{redirect}}',
                    encodeURIComponent(location.href),
                  )
                  return new Promise(() => {
                  })
                } else if (response.data.msg) {
                  throw new Error(response.data.msg)
                } else {
                  throw new Error(
                    'System.requestError' + JSON.stringify(response.data, null, 2),
                  )
                }
              } else {
                throw new Error(
                  `${'System.requestErrorStatus'} ${response.status}`,
                )
              }
            }

            return response
          },
          isCancel: (value: any) => (axios as any).isCancel(value),
        },
      )}
    </>
  )
}

export function horizontalFormOptions() {
  return {
    mode: 'horizontal',
    horizontal: {
      leftFixed: 'sm',
    },
  }
}

export function crudCommonOptions() {
  return {
    affixHeader: false,
    stopAutoRefreshWhenModalIsOpen: true,
    resizable: false,
    syncLocation: false,
    silentPolling: true,
    columnsTogglable: false,
  }
}

export function readOnlyDialogOptions() {
  return {
    actions: [],
    showCloseButton: false,
    closeOnEsc: true,
    closeOnOutside: true,
    disabled: true,
  }
}

export function paginationCommonOptions(perPage = true, maxButtons = 5) {
  let option = {
    type: 'pagination',
    layout: [
      'pager',
    ],
    maxButtons: maxButtons,
    showPageInput: false,
    perPageAvailable: [10, 15, 20, 50, 100, 200],
  }
  if (perPage) {
    option.layout.push('perPage')
  }
  return option
}

export function paginationTemplate(perPage = 20, maxButtons = 5, extraHeaders: Array<Schema | string> = [], extraFooters: Array<Schema | string> = []) {
  return {
    perPage: perPage,
    headerToolbar: [
      'reload',
      paginationCommonOptions(true, maxButtons),
      ...extraHeaders,
    ],
    footerToolbar: [
      'statistics',
      paginationCommonOptions(true, maxButtons),
      ...extraFooters,
    ],
  }
}

export function copyField(field: string, tips = '复制', ignoreLength = 0) {
  let tpl = ignoreLength === 0 ? `\${${field}}` : `\${TRUNCATE(${field}, ${ignoreLength})}`
  return {
    type: 'wrapper',
    size: 'none',
    body: [
      {
        type: 'tpl',
        className: 'mr-1',
        tpl: tpl,
      },
      {
        type: 'action',
        level: 'link',
        label: '',
        icon: 'fa fa-copy',
        size: 'xs',
        actionType: 'copy',
        content: `\$${field}`,
        tooltip: `${tips}`,
      },
    ],
  }
}

export function mappingItem(label: string, value: string, color = 'bg-info') {
  return {
    label: label,
    value: value,
    color: color,
  }
}

export function mappingField(field: string, mapping: Array<Record<string, string>>) {
  let mapData: Record<string, string> = {
    '*': `<span class='label bg-gray-300'>\${${field}}</span>`,
  }
  mapping.forEach(item => {
    mapData[item['value']] = `<span class='label ${item['color']}'>${item['label']}</span>`
  })
  return {
    type: 'mapping',
    value: `\${${field}}`,
    map: mapData,
  }
}

export function filterableField(mapping: Array<Record<string, any>>, multiple = false) {
  return {
    multiple: multiple,
    options: [
      ...mapping,
    ],
  }
}

export function time(field: string) {
  return {
    width: 150,
    align: 'center',
    type: 'tpl',
    tpl: `\${IF(${field}, DATETOSTR(${field}, 'YYYY-MM-DD HH:mm:ss'), '/')}`,
  }
}

export function date(field: string) {
  return {
    width: 150,
    align: 'center',
    type: 'tpl',
    tpl: `\${IF(${field}, DATETOSTR(${field}, 'YYYY-MM-DD'), '/')}`,
  }
}

export function pictureFromIds(field: string) {
  return `\${ARRAYMAP(${field},id => '${commonInfo.baseUrl}/upload/download/' + id)}`
}

export const formInputFileStaticColumns = [
  {
    name: 'filename',
    label: '文件名',
  },
  {
    type: 'operation',
    label: '操作',
    width: 140,
    buttons: [
      {
        type: 'action',
        label: '预览',
        level: 'link',
        icon: 'fas fa-eye',
      },
      {
        type: 'action',
        label: '下载',
        level: 'link',
        icon: 'fa fa-download',
        actionType: 'ajax',
        // api: {
        // ...apiGet('${base}/upload/download/${id}'),
        // responseType: 'blob',
        // }
      },
    ],
  },
]

export function formInputSingleFileStatic(field: string, label: string) {
  return {
    visibleOn: '${static}',
    type: 'control',
    label: label,
    required: true,
    body: {
      type: 'table',
      source: `\${${field}|asArray}`,
      columns: formInputFileStaticColumns,
    },
  }
}

export function formInputMultiFileStatic(field: string, label: string) {
  return {
    visibleOn: '${static}',
    type: 'input-table',
    label: label,
    name: field,
    required: true,
    resizable: false,
    columns: formInputFileStaticColumns,
  }
}

export function remoteOptions(type: string = 'select', name: string) {
  return {
    type: type,
    source: `get:${commonInfo.baseUrl}/constants/options/${name}`,
  }
}

export function remoteMappings(name: string, field: string) {
  return {
    type: 'mapping',
    source: `get:${commonInfo.baseUrl}/constants/mappings/${name}/${field}`,
  }
}
