import React, { useCallback, useMemo, useRef, useState } from 'react'
import classNames from 'classnames'
import dayjs from 'dayjs'
import { useInfo } from '../InfoContext'
import { Cascader, DatePicker, Input, Radio, Select } from 'antd'
import TextArea from 'antd/es/input/TextArea'

const { RangePicker } = DatePicker

const PAGE_SIZE = 20

/** 可搜索+分页的远程 Select，用于 SelectSearch 类型 */
function SelectSearchRemote({
  item,
  isLook,
  infoRes,
  dataChangeFu,
  value
}: {
  item: any
  isLook: boolean
  infoRes: any
  dataChangeFu: (val: any, item: any) => void
  value: any
}) {
  const [options, setOptions] = useState<{ label: string; value: number }[]>([])
  const [loading, setLoading] = useState(false)
  const [pageNum, setPageNum] = useState(1)
  const [total, setTotal] = useState(0)
  const [searchKey, setSearchKey] = useState('')
  const fetchRef = useRef(0)

  const api = item.api
  const labelKey = item.labelKey || 'name'
  const valueKey = item.valueKey || 'id'
  const searchParam = item.searchParam || 'searchKey'
  const hasMore = options.length < total

  const fetchList = useCallback(
    async (page: number, keyword: string, append: boolean) => {
      if (!api) return
      const current = ++fetchRef.current
      setLoading(true)
      try {
        const res = await api({
          pageNum: page,
          pageSize: PAGE_SIZE,
          [searchParam]: keyword || undefined
        })
        if (current !== fetchRef.current) return
        const records = res?.data?.records || []
        const totalRes = res?.data?.total || 0
        setTotal(totalRes)
        setOptions(prev => (append ? [...prev, ...records] : records))
      } finally {
        if (current === fetchRef.current) setLoading(false)
      }
    },
    [api, searchParam]
  )

  const onSearch = useCallback(
    (val: string) => {
      setSearchKey(val)
      setPageNum(1)
      fetchList(1, val, false)
    },
    [fetchList]
  )

  const onPopupScroll = useCallback(
    (e: React.UIEvent<HTMLDivElement>) => {
      const { scrollTop, scrollHeight, clientHeight } = e.currentTarget
      if (scrollHeight - scrollTop - clientHeight < 50 && hasMore && !loading) {
        const next = pageNum + 1
        setPageNum(next)
        fetchList(next, searchKey, true)
      }
    },
    [fetchList, hasMore, loading, pageNum, searchKey]
  )

  const onDropdownVisibleChange = useCallback(
    (open: boolean) => {
      if (open && options.length === 0 && !loading) {
        fetchList(1, '', false)
      }
    },
    [fetchList, options.length, loading]
  )

  const opts = useMemo(() => {
    const list = options.map((r: any) => ({
      label: r[labelKey] ?? r.name,
      value: r[valueKey] ?? r.id
    }))
    // 编辑回显：有 value 但不在列表中时，用 optionLabel 补充
    const optionLabel =
      typeof item.optionLabel === 'function' ? item.optionLabel(infoRes) : item.optionLabel
    if (value != null && value !== '' && !list.some((o: any) => o.value === value) && optionLabel) {
      list.unshift({ label: optionLabel, value })
    }
    return list
  }, [options, item, infoRes, value, labelKey, valueKey])

  return (
    <Select
      disabled={isLook}
      showSearch
      filterOption={false}
      placeholder={(isLook ? '（空）' : item.placeholder) || '请选择'}
      value={value}
      onChange={e => dataChangeFu(e, item)}
      options={opts}
      allowClear={!item.must}
      loading={loading}
      onSearch={onSearch}
      onPopupScroll={onPopupScroll}
      onDropdownVisibleChange={onDropdownVisibleChange}
      notFoundContent={loading ? '加载中...' : '暂无数据'}
    />
  )
}

type Props = {
  item: any
  isLook: boolean
  isTow?: boolean //是否是第二个模块
}

function EditInput({ item, isLook, isTow }: Props) {
  const { info, info2, setInfoFu } = useInfo()

  const infoRes = useMemo(() => {
    return isTow ? info2 : info
  }, [info, info2, isTow])

  // 数据改变
  const dataChangeFu = useCallback(
    (val: any, item: any) => {
      const type = item.type
      const key = item.key

      if (type === 'DatePicker') {
        setInfoFu({ ...infoRes, [key]: dayjs(val).format('YYYY-MM-DD') }, isTow)
      } else if (['TextArea', 'Input'].includes(type)) {
        const varRes = item.noNull ? val.replace(/\s+/g, '') : val
        setInfoFu(
          {
            ...infoRes,
            [key]: varRes
          },
          isTow
        )
      } else if (type === 'Cascader') {
        setInfoFu({ ...infoRes, dictIdApply: val ? val.join(',') : '' }, isTow)
      } else if (['Select', 'SelectSearch'].includes(type)) {
        setInfoFu({ ...infoRes, [key]: val }, isTow)
      } else if (type === 'DatePicker2') {
        const keys = Array.isArray(key) ? key : [key]
        const modeKey = item.modeKey
        if (val?.type === 'longterm') {
          const update: any = { [keys[0]]: '', [keys[1]]: '' }
          if (modeKey) update[modeKey] = 'longterm'
          setInfoFu({ ...infoRes, ...update }, isTow)
        } else if (val?.type === 'range') {
          const [start, end] = val?.dates || [null, null]
          const update: any = {
            [keys[0]]: start ? dayjs(start).format('YYYY-MM-DD') : '',
            [keys[1]]: end ? dayjs(end).format('YYYY-MM-DD') : ''
          }
          if (modeKey) update[modeKey] = 'range'
          setInfoFu({ ...infoRes, ...update }, isTow)
        }
      }
    },
    [infoRes, isTow, setInfoFu]
  )

  return (
    <div className={classNames('Edtop1row', item.full ? 'Edtop1rowFull' : '')}>
      <div className='Edtop1ll'>
        {item.must ? <span>* </span> : null}
        <i dangerouslySetInnerHTML={{ __html: item.name + '：' }}></i>
      </div>

      <div className='Edtop1rr'>
        {item.type === 'txt' ? (
          <>
            {dayjs(infoRes.createTime).format('YYYY年MM月DD日')}-{infoRes.deptName}-
            {infoRes.creatorName}
          </>
        ) : item.type === 'DatePicker' ? (
          <DatePicker
            disabled={isLook}
            allowClear={!item.must}
            value={dayjs(infoRes[item.key as 'date'])}
            onChange={e => dataChangeFu(e, item)}
            disabledDate={current => current && current > dayjs().endOf('day')}
          />
        ) : item.type === 'Input' ? (
          <Input
            readOnly={isLook}
            placeholder={isLook ? '（空）' : '请输入'}
            value={infoRes[item.key as 'date']}
            onChange={e => dataChangeFu(e.target.value, item)}
            maxLength={item.maxLength || 30}
            showCount
          />
        ) : item.type === 'Cascader' ? (
          <Cascader
            disabled={isLook}
            changeOnSelect
            options={item.options}
            placeholder={isLook ? '（空）' : '请选择'}
            fieldNames={{ label: 'name', value: 'id', children: 'children' }}
            allowClear={!item.must}
            value={
              infoRes[item.key as 'date'] ? (infoRes[item.key as 'date'] as string).split(',') : []
            }
            onChange={e => dataChangeFu(e, item)}
          />
        ) : item.type === 'TextArea' ? (
          <TextArea
            readOnly={isLook}
            placeholder={isLook ? '（空）' : '请输入'}
            value={infoRes[item.key as 'date']}
            onChange={e => dataChangeFu(e.target.value, item)}
            maxLength={item.maxLength || 500}
            showCount
          />
        ) : item.type === 'Select' ? (
          <Select
            disabled={isLook}
            showSearch // 启用搜索功能
            filterOption={(input: any, option: any) =>
              (option?.label ?? '').toLowerCase().includes(input.toLowerCase())
            }
            placeholder={(isLook ? '（空）' : item.placeholder) || '请选择'}
            value={infoRes[item.key as 'date']}
            onChange={e => dataChangeFu(e, item)}
            options={item.options}
            allowClear={!item.must}
          />
        ) : item.type === 'SelectSearch' ? (
          <SelectSearchRemote
            item={item}
            isLook={isLook}
            infoRes={infoRes}
            dataChangeFu={dataChangeFu}
            value={(infoRes as any)[item.key]}
          />
        ) : item.type === 'DatePicker2' ? (
          (() => {
            const keys = Array.isArray(item.key) ? item.key : [item.key]
            const modeKey = item.modeKey as string | undefined
            const startVal = infoRes[keys[0] as keyof typeof infoRes]
            const endVal = infoRes[keys[1] as keyof typeof infoRes]
            const modeVal = modeKey ? infoRes[modeKey as keyof typeof infoRes] : null
            const isLongterm = modeVal === 'longterm' || (!modeVal && !startVal && !endVal)
            const rangeValue = startVal && endVal ? [dayjs(startVal), dayjs(endVal)] : null
            return (
              <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                <Radio.Group
                  disabled={isLook}
                  value={isLongterm ? 'longterm' : 'range'}
                  onChange={e => {
                    const v = e.target.value
                    dataChangeFu(
                      v === 'longterm'
                        ? { type: 'longterm' }
                        : { type: 'range', dates: [null, null] },
                      item
                    )
                  }}
                >
                  <Radio value='longterm'>长期</Radio>
                  <Radio value='range'>定期</Radio>
                </Radio.Group>
                {!isLongterm && (
                  <RangePicker
                    disabled={isLook}
                    allowClear={!item.must}
                    value={rangeValue as [dayjs.Dayjs, dayjs.Dayjs]}
                    onChange={dates =>
                      dataChangeFu({ type: 'range', dates: dates || [null, null] }, item)
                    }
                  />
                )}
              </div>
            )
          })()
        ) : null}
      </div>
    </div>
  )
}

const MemoEditInput = React.memo(EditInput)

export default MemoEditInput
