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, isNil} from 'es-toolkit'
// @ts-ignore
import type {ColumnSchema} from 'amis/lib/renderers/Table2'
import {toNumber} from 'es-toolkit/compat'

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

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 {
    type: 'tpl',
    tpl: `\${IF(${field}, DATETOSTR(${field}, 'YYYY-MM-DD HH:mm:ss'), '/')}`,
  }
}

export function date(field: string) {
  return {
    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}`,
  }
}

const formatFinanceNumber = (value: number): string => {
  if (isNil(value)) {
    return '-'
  }

  const isNegative = value < 0
  const absoluteValue = Math.abs(value)

  let formatted: string
  if (absoluteValue >= 100000000) {
    formatted = (absoluteValue / 100000000).toFixed(2) + '亿'
  } else if (absoluteValue >= 10000) {
    formatted = (absoluteValue / 10000).toFixed(2) + '万'
  } else {
    formatted = absoluteValue.toLocaleString()
  }

  return isNegative ? `-${formatted}` : formatted
}

const formatDaysNumber = (value: number): string => {
  if (isNil(value)) {
    return '-'
  }
  return `${value.toFixed(0)}天`
}

const formatPercentageNumber = (value: number): string => {
  if (isNil(value)) {
    return '-'
  }
  return `${(value * 100).toFixed(2)}%`
}

type FinanceType = 'PERCENTAGE' | 'FINANCE' | 'DAYS'

const financePropertyLabel = (idField: string, label: string, type: FinanceType, field: string): Schema => {
  let formatter: (value: number) => string
  switch (type) {
    case 'PERCENTAGE':
      formatter = formatPercentageNumber
      break
    case 'FINANCE':
      formatter = formatFinanceNumber
      break
    case 'DAYS':
      formatter = formatDaysNumber
      break
    default:
      formatter = (v: number) => v.toFixed(2)
  }
  return {
    type: 'wrapper',
    size: 'none',
    body: [
      {
        visibleOn: `\${!${idField}}`,
        type: 'tpl',
        tpl: label,
      },
      {
        visibleOn: `\${${idField}}`,
        className: 'text-current font-bold',
        type: 'action',
        label: label,
        level: 'link',
        tooltip: '这是什么？',
        tooltipPlacement: 'top',
        actionType: 'dialog',
        dialog: {
          title: '',
          size: 'lg',
          ...readOnlyDialogOptions(),
          actions: [
            {
              type: 'action',
              label: '新页面打开',
              icon: 'fa fa-solid fa-arrow-up-right-from-square',
              actionType: 'url',
              url: `https://zh.wikipedia.org/wiki/${label}`,
              blank: true,
            },
          ],
          body: {
            type: 'iframe',
            src: `https://zh.wikipedia.org/wiki/${label}`,
            height: 800,
          },
        },
      },
      {
        className: 'text-secondary',
        type: 'action',
        label: '',
        icon: 'fa fa-eye',
        level: 'link',
        size: 'xs',
        tooltip: '查看五年趋势',
        tooltipPlacement: 'top',
        actionType: 'dialog',
        dialog: {
          title: `${label}五年趋势`,
          size: 'lg',
          bodyClassName: 'p-0',
          ...readOnlyDialogOptions(),
          body: {
            type: 'chart',
            api: `get:${commonInfo.baseUrl}/stock/finance/\${${idField}}/${field}`,
            height: 500,
            config: {
              tooltip: {
                trigger: 'axis',
                backgroundColor: 'rgba(255, 255, 255, 0.9)',
                borderColor: '#ccc',
                borderWidth: 1,
                textStyle: {
                  color: '#333',
                },
                padding: [10, 15],
                formatter: (params: any) => {
                  const item = params[0]
                  return `${item.name}<br/>${item.marker}${formatter(item.value)}`
                },
              },
              grid: {
                left: '5%',
                right: '5%',
                top: '10%',
                bottom: '15%',
                containLabel: true,
              },
              xAxis: {
                type: 'category',
                data: '${xList || []}',
                axisLine: {
                  lineStyle: {
                    color: '#e0e0e0',
                  },
                },
                axisLabel: {
                  color: '#666',
                  fontWeight: 'bold',
                },
                axisTick: {
                  show: false,
                },
              },
              yAxis: {
                type: 'value',
                show: true,
                splitLine: {
                  lineStyle: {
                    type: 'dashed',
                    color: '#f0f0f0',
                  },
                },
                axisLine: {
                  show: false,
                },
                axisLabel: {
                  color: '#999',
                  fontSize: 12,
                  formatter: (value: number) => {
                    return formatter(value)
                  },
                },
                axisTick: {
                  show: false,
                },
              },
              series: [
                {
                  data: '${yList || []}',
                  type: 'line',
                  smooth: true,
                  showSymbol: true,
                  symbolSize: 6,
                  lineStyle: {
                    width: 3,
                    color: '#4096ff',
                    shadowColor: 'rgba(64, 150, 255, 0.3)',
                    shadowBlur: 5,
                    shadowOffsetY: 2,
                  },
                  itemStyle: {
                    color: '#4096ff',
                    borderWidth: 2,
                    borderColor: '#fff',
                  },
                  areaStyle: {
                    color: {
                      type: 'linear',
                      x: 0,
                      y: 0,
                      x2: 0,
                      y2: 1,
                      colorStops: [{
                        offset: 0, color: 'rgba(64, 150, 255, 0.2)',
                      }, {
                        offset: 1, color: 'rgba(64, 150, 255, 0.01)',
                      }],
                    },
                  },
                  label: {
                    show: true,
                    position: 'top',
                    color: '#333',
                    fontWeight: 'bold',
                    fontSize: 12,
                    formatter: (params: any) => {
                      return formatter(params.value)
                    },
                  },
                },
              ],
            },
          },
        },
      },
    ],
  }
}

export function stockListColumns(idField: string = 'id', extraColumns: Array<ColumnSchema> = []) {
  return [
    {
      name: 'code',
      label: '编号',
      width: 150,
    },
    {
      name: 'name',
      label: '简称',
      width: 100,
    },
    {
      name: 'fullname',
      label: '全名',
    },
    {
      name: 'market',
      label: '市场',
      width: 100,
      align: 'center',
      ...remoteMappings('stock_market', 'market'),
    },
    {
      name: 'industry',
      label: '行业',
      width: 80,
    },
    {
      label: '上市日期',
      width: 100,
      align: 'center',
      ...date('listedDate'),
    },
    ...extraColumns,
    {
      type: 'operation',
      label: '操作',
      width: 100,
      buttons: [
        {
          type: 'action',
          label: '详情',
          level: 'link',
          actionType: 'dialog',
          dialog: {
            title: '股票详情',
            size: 'full',
            ...readOnlyDialogOptions(),
            body: [
              {
                type: 'property',
                items: [
                  {label: '编码', content: '${code}'},
                  {label: '名称', content: '${name}'},
                  {label: '全名', content: '${fullname}'},
                  {
                    label: '市场',
                    content: {
                      ...remoteMappings('stock_market', 'market'),
                      value: '${market}',
                    },
                  },
                  {label: '行业', content: '${industry}'},
                  {label: '上市日期', content: '${listedDate}'},
                ],
              },
              {type: 'divider'},
              {
                type: 'service',
                api: `get:${commonInfo.baseUrl}/stock/finance/\${${idField}}`,
                body: [
                  '资产负债表',
                  {
                    className: 'my-2',
                    type: 'property',
                    column: 4,
                    items: [
                      {
                        label: financePropertyLabel(idField, '总资产', 'FINANCE', 'totalAssets'),
                        content: '${balanceSheet.totalAssets}',
                        span: 2,
                      },
                      {
                        label: financePropertyLabel(idField, '总负债', 'FINANCE', 'totalLiabilities'),
                        content: '${balanceSheet.totalLiabilities}',
                        span: 2,
                      },
                      {
                        label: financePropertyLabel(idField, '流动资产', 'FINANCE', 'currentAssets'),
                        content: '${balanceSheet.currentAssets}',
                      },
                      {
                        label: financePropertyLabel(idField, '流动资产占比', 'PERCENTAGE', 'currentAssetsToTotalAssetsRatio'),
                        content: '${balanceSheet.currentAssetsRatio}',
                      },
                      {
                        label: financePropertyLabel(idField, '流动负债', 'FINANCE', 'currentLiabilities'),
                        content: '${balanceSheet.currentLiabilities}',
                      },
                      {
                        label: financePropertyLabel(idField, '流动负债占比', 'PERCENTAGE', 'currentLiabilitiesToTotalAssetsRatio'),
                        content: '${balanceSheet.currentLiabilitiesRatio}',
                      },
                      {
                        label: financePropertyLabel(idField, '非流动资产', 'FINANCE', 'fixedAssets'),
                        content: '${balanceSheet.fixedAssets}',
                      },
                      {
                        label: financePropertyLabel(idField, '非流动资产占比', 'PERCENTAGE', 'fixedAssetsToTotalAssetsRatio'),
                        content: '${balanceSheet.fixedAssetsRatio}',
                      },
                      {
                        label: financePropertyLabel(idField, '非流动负债', 'FINANCE', 'longTermLiabilities'),
                        content: '${balanceSheet.longTermLiabilities}',
                      },
                      {
                        label: financePropertyLabel(idField, '非流动负债占比', 'PERCENTAGE', 'longTermLiabilitiesToTotalAssetsRatio'),
                        content: '${balanceSheet.longTermLiabilitiesRatio}',
                      },
                    ],
                  },
                  '利润表',
                  {
                    className: 'my-2',
                    type: 'property',
                    items: [
                      {
                        label: financePropertyLabel(idField, '营业收入', 'FINANCE', 'operatingRevenue'),
                        content: '${income.operatingRevenue}',
                      },
                      {
                        label: financePropertyLabel(idField, '营业成本', 'FINANCE', 'operatingCost'),
                        content: '${income.operatingCost}',
                      },
                      {
                        label: financePropertyLabel(idField, '营业利润', 'FINANCE', 'operatingProfit'),
                        content: '${income.operatingProfit}',
                      },
                    ],
                  },
                  '现金流量表',
                  {
                    className: 'my-2',
                    type: 'property',
                    items: [
                      {
                        label: financePropertyLabel(idField, '净利润', 'FINANCE', 'netProfit'),
                        content: '${cashFlow.netProfit}',
                        span: 3,
                      },
                      {
                        label: financePropertyLabel(idField, '营业活动现金流量', 'FINANCE', 'cashFlowFromOperatingActivities'),
                        content: '${cashFlow.cashFlowFromOperatingActivities}',
                      },
                      {
                        label: financePropertyLabel(idField, '投资活动现金流量', 'FINANCE', 'cashFlowFromInvestingActivities'),
                        content: '${cashFlow.cashFlowFromInvestingActivities}',
                      },
                      {
                        label: financePropertyLabel(idField, '筹资活动现金流量', 'FINANCE', 'cashFlowFromFinancingActivities'),
                        content: '${cashFlow.cashFlowFromFinancingActivities}',
                      },
                    ],
                  },
                  '财务指标',
                  {
                    className: 'my-2',
                    type: 'property',
                    column: 4,
                    items: [
                      {
                        label: financePropertyLabel(idField, '流动比率', 'FINANCE', 'currentRatio'),
                        content: '${indicate.currentRatio}',
                      },
                      {
                        label: financePropertyLabel(idField, '速动比率', 'FINANCE', 'quickRatio'),
                        content: '${indicate.quickRatio}',
                      },
                      {
                        label: financePropertyLabel(idField, 'ROE', 'FINANCE', 'returnOnEquity'),
                        content: '${indicate.roe}',
                      },
                      {
                        label: financePropertyLabel(idField, 'ROA', 'FINANCE', 'returnOnAssets'),
                        content: '${indicate.roa}',
                      },
                      {
                        label: financePropertyLabel(idField, '应收账款周转率', 'FINANCE', 'accountsReceivableTurnover'),
                        content: '${indicate.accountsReceivableTurnover}',
                      },
                      {
                        label: financePropertyLabel(idField, '应收账款周转天数', 'DAYS', 'daysAccountsReceivableTurnover'),
                        content: '${indicate.daysAccountsReceivableTurnover}',
                      },
                      {
                        label: financePropertyLabel(idField, '存货周转率', 'FINANCE', 'inventoryTurnover'),
                        content: '${indicate.inventoryTurnover}',
                      },
                      {
                        label: financePropertyLabel(idField, '存货周转天数', 'DAYS', 'daysInventoryTurnover'),
                        content: '${indicate.daysInventoryTurnover}',
                      },
                      {
                        label: financePropertyLabel(idField, '固定资产周转率', 'FINANCE', 'fixedAssetsTurnover'),
                        content: '${indicate.fixedAssetsTurnover}',
                      },
                      {
                        label: financePropertyLabel(idField, '固定资产周转天数', 'DAYS', 'daysFixedAssetsTurnover'),
                        content: '${indicate.daysFixedAssetsTurnover}',
                      },
                      {
                        label: financePropertyLabel(idField, '总资产周转率', 'FINANCE', 'totalAssetsTurnover'),
                        content: '${indicate.totalAssetsTurnover}',
                      },
                      {
                        label: financePropertyLabel(idField, '总资产周转天数', 'DAYS', 'daysTotalAssetsTurnover'),
                        content: '${indicate.daysTotalAssetsTurnover}',
                      },
                    ],
                  },
                ],
              },
              {type: 'divider'},
              {
                type: 'service',
                api: `get:${commonInfo.baseUrl}/stock/daily/current/\${${idField}}`,
                body: [
                  "现价 (${date})",
                  {
                    className: 'my-2',
                    type: 'property',
                    column: 4,
                    items: [
                      {label: '开盘价', content: '${open}'},
                      {label: '收盘价', content: '${close}'},
                      {label: '最高价', content: '${high}'},
                      {label: '最低价', content: '${low}'},
                    ],
                  },
                ],
              },
              {
                type: 'chart',
                title: '100日线数据',
                height: 500,
                api: `get:${commonInfo.baseUrl}/stock/daily/\${${idField}}`,
                config: {
                  title: {
                    text: '100日线数据',
                    subtext: '后复权数据',
                  },
                  backgroundColor: '#fff',
                  animation: true,
                  animationDuration: 1000,
                  tooltip: {
                    trigger: 'axis',
                    axisPointer: {
                      type: 'cross',
                    },
                    backgroundColor: 'rgba(0, 0, 0, 0.7)',
                    borderColor: '#333',
                    borderWidth: 1,
                    textStyle: {
                      color: '#fff',
                      fontSize: 12,
                    },
                    padding: 12,
                    formatter: function (params: any) {
                      const param = params[0]
                      const open = toNumber(param.data[1]).toFixed(2)
                      const close = toNumber(param.data[2]).toFixed(2)
                      const lowest = toNumber(param.data[3]).toFixed(2)
                      const highest = toNumber(param.data[4]).toFixed(2)

                      return `<div class="text-center font-bold mb-2">${param.name}</div>
                        <div class="text-center">
                          <span>开盘:</span>
                          <span class="font-bold ml-4">${open}</span>
                        </div>
                        <div class="text-center">
                          <span>收盘:</span>
                          <span class="font-bold ml-4">${close}</span>
                        </div>
                        <div class="text-center">
                          <span>最低:</span>
                          <span class="font-bold ml-4">${lowest}</span>
                        </div>
                        <div class="text-center">
                          <span>最高:</span>
                          <span class="font-bold ml-4">${highest}</span>
                        </div>`
                    },
                  },
                  grid: {
                    left: '2%',
                    right: '2%',
                    top: '15%',
                    bottom: '15%',
                    containLabel: true,
                  },
                  xAxis: {
                    data: '${xList || []}',
                    axisLine: {
                      lineStyle: {
                        color: '#e0e0e0',
                      },
                    },
                    axisLabel: {
                      color: '#666',
                      fontWeight: 'bold',
                    },
                    splitLine: {
                      show: false,
                    },
                    axisTick: {
                      show: false,
                    },
                  },
                  yAxis: {
                    scale: true,
                    axisLine: {
                      lineStyle: {
                        color: '#e0e0e0',
                      },
                    },
                    axisLabel: {
                      color: '#666',
                      fontWeight: 'bold',
                      formatter: function (value: number) {
                        return value.toFixed(2)
                      },
                    },
                    splitLine: {
                      lineStyle: {
                        type: 'dashed',
                        color: '#f0f0f0',
                      },
                    },
                    axisTick: {
                      show: false,
                    },
                  },
                  dataZoom: [
                    {
                      type: 'inside',
                      start: 0,
                      end: 100,
                    },
                    {
                      show: true,
                      type: 'slider',
                      top: '90%',
                      start: 0,
                      end: 100,
                    },
                  ],
                  series: [
                    {
                      type: 'candlestick',
                      data: '${yList || []}',
                      itemStyle: {
                        color: '#eb5454',
                        color0: '#4aaa93',
                        borderColor: '#eb5454',
                        borderColor0: '#4aaa93',
                        borderWidth: 1,
                      },

                    },
                  ],
                },
              },
            ],
          },
        },
      ],
    },
  ]
}
