/*
 * @Author: code4eat awesomedema@gmail.com
 * @Date: 2023-01-04 14:12:31
 * @LastEditors: code4eat awesomedema@gmail.com
 * @LastEditTime: 2024-11-15 14:31:22
 * @FilePath: /BudgetManaSystem/src/pages/budgetMana/oneBatch/index.tsx
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */


import { ActionType, ProColumns, ProFormText } from '@ant-design/pro-components';
import { Space, Dropdown, MenuProps, DatePicker } from 'antd';
import { useEffect, useRef, useState } from 'react';
import { getData, getRedirReportData, getSearchRowsReq } from './service';


import './style.less';


import { createFromIconfontCN, DownOutlined } from '@ant-design/icons';

import exportTableToExcel from '@/utils/tableToExcel';


import 'moment/locale/zh-cn';
import locale from 'antd/es/date-picker/locale/zh_CN';
import moment from 'moment';
import { formatMoneyNumber } from '@/utils/format';

import KCIMPagecontainer from '@/components/KCIMPageContainer';
import { KCIMTable } from '@/components/KCIMTable';
import { getStringWidth } from '@/utils/tooljs';

import ExportProgressModal from './ExportProgressModal';
import { getParamsDataBySysId } from '@/services/getDic';
import { useModel, useParams } from '@umijs/max';



const IconFont = createFromIconfontCN({
  scriptUrl: '',
});

interface Searchable {
  [key: string]: string;
}


let searchKeys: any[] = [];
let totalTableData: any[] = [];
let dataSource: any[] = [];
let tableDataSearchKeywords: undefined | string = undefined;
let currentPage = 0;
let maxFetchCount = 0;
let prevParams: any = null;



function multiAttributeSearchOptimized(dataArray: any[], keys: any[], keywords: any[]) {
  // 确保关键词为非空数组
  if (!Array.isArray(keywords) || keywords.length === 0) {
    return dataArray;
  }

  const lowerCaseKeywords = keywords.map(kw => kw.toLowerCase());

  return dataArray.filter((item: { [x: string]: any; }) => {
    // 对每一项数据进行指定属性的搜索
    return keys.some((key: string | number) => {
      const value = item[key];
      // 确保属性存在且为字符串类型
      if (typeof value === 'string') {
        // 遍历每一个关键词，判断是否存在匹配
        return lowerCaseKeywords.some(keyword => value.toLowerCase().includes(keyword));
      }
      return false;
    });
  });
}



const ReportExport = ({ reportCode, propsParams, tableScrollH }: { reportCode: string, propsParams: any, tableScrollH: number }) => {

  const { reportCode: urlReportCode } = reportCode ? { reportCode } : useParams();

  const [tableColumn, set_tableColumn] = useState<ProColumns[] | any[]>([]);

  const [tableScrollX, set_tableScrollX] = useState<number>(1000);

  const { initialState, setInitialState } = useModel('@@initialState');
  const [currentComputeDate, set_currentComputeDate] = useState<string | undefined>(propsParams ? propsParams.compute_date : (initialState ? initialState.computeDate : undefined));

  const [breadCrumbList, set_breadCrumbList] = useState<any[]>([]);

  const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>(propsParams ? { parameter: propsParams } : undefined);

  const tableRef = useRef<ActionType>();

  const [loading, set_loading] = useState(true);

  const [tableH, set_tableH] = useState(tableScrollH ? tableScrollH : 0);

  const [step, set_step] = useState(0);

  const [reportName, set_reportName] = useState('');

  const [pageSize, set_pageSize] = useState(20);
  const [openProcessModal, set_openProcessModal] = useState(false);
  const [searchRows, set_searchRows] = useState<any[]>([]);
  const [tableData, set_tableData] = useState<any[]>([]);
  const [searchType, set_searchType] = useState(0);
  const [pagination, set_pagination] = useState<any>(null);


  const reportJumphandle = (reportData: any) => {
    set_loading(true);
    set_searchRows([]);
    let parameter: { [key: string]: any } = {};
    const { redirectParameter = undefined } = reportData;
    const _step = step + 1;

    if (redirectParameter) {
      const tempArr = redirectParameter.split('|');
      tempArr.forEach((element: string) => {
        parameter[`${element}`] = reportData[`${element}`]
      });
    }

    set_breadCrumbList(
      [...breadCrumbList,
      {
        index: _step,
        name: reportData[`report_name`] || reportData[`redirectReportName`],
        params: {
          reportCode: reportData.redirectReportCode,
          parameter: {
            ...parameter
          }
        }
      }
      ]
    );

    set_step(_step);
    getSearchRows(reportData.redirectReportCode, parameter);

    totalTableData = [];
    currentPage = 0;
    dataSource = [];
  }

  const getSearchRows = async (code: string, others?: any) => {
    const resp = await getSearchRowsReq(code);

    if (resp) {
      const rows = resp.reportIndex ? resp.reportIndex : [];
      set_searchType(resp.indexType);
      set_searchRows(rows);
      const searchObject = rows.reduce((acc: { [x: string]: any; }, curr: { columnIndex: string | number; value: any; }) => {
        acc[curr.columnIndex] = '';
        return acc;
      }, {});
      set_tableDataFilterParams({ ...tableDataFilterParams, reportCode: code, parameter: { ...others, compute_date: currentComputeDate, ...searchObject, ...(reportCode ? tableDataFilterParams?.parameter : {}) } });
    }
  }


  const getTableData = async (params: any) => {

    if (!openProcessModal) {
      set_loading(true);
    }
  

    if (!params.reportCode || (JSON.stringify(prevParams) === JSON.stringify(params))) {
      // 参数相同，不执行请求
      return;
    }

    const { systemId } = JSON.parse(localStorage.getItem('currentSelectedTab') as string)
    const paramsData = await getParamsDataBySysId(systemId, '1806523783696224256');
    const pageSize = paramsData.value ? Number(paramsData.value) : 100;
    set_pageSize(pageSize);
    const { parameter = {}, current, reportCode } = params;
    searchKeys = [];
    let resp: any = undefined;


    if (step != 0) {
      //报表跳转
      resp = await getRedirReportData(
        { pageSize, current },
        reportCode,
        { ...parameter, compute_date: currentComputeDate, }
      );
    }

    if (step == 0) {
      //首次获取表格数据
      resp = await getData(
        { pageSize, current },
        urlReportCode as string,
        { ...parameter, compute_date: currentComputeDate, }
      );
    }

    if (resp) {
      prevParams = params;
      const { title, data: assignmentData, reportName, current, totalCount, totalPage, pageSize } = resp;
      set_reportName(reportName);

      let scrollX = 0;
      const columns: ProColumns[] = title.map((item: any, index: number) => {

        if (item.search) {
          searchKeys.push({ name: item.name, key: item.columnName });
        }
        const wid = (item.name.length * 17) > 100 ? (item.name.length * 17) : 100;
        scrollX = scrollX + wid;

        return {
          title: item.name,
          dataIndex: `${item.columnName}`,
          key: `${item.columnName}`,
          width: wid,
          ellipsis: true,
          fixed: item.freeze ? true : false,
          hideInTable: item.hide,
          align: (item.dataType == 3 || item.dataType == 2) ? 'right' : 'left',
          sorter: item.sortStatus ? (a: any, b: any) => {
            if (item.dataType == 3) {
              //数值
              return b[`${item.columnName}`] - (a[`${item.columnName}`]);
            } else {
              return b[`${item.columnName}`]?.localeCompare(a[`${item.columnName}`]);
            }
          } : undefined,
          renderText: (_: string | number, record: any) => {

            if (item.redirect) {
              if (item.redirectData && item.redirectData.length > 1) {

                const items: MenuProps['items'] = [
                  ...(item.redirectData.map((a: any, index: number) => ({
                    key: index,
                    label: (
                      <a onClick={() => reportJumphandle({ ...item, ...record, ...a })}>
                        {a.redirectReportName}
                      </a>
                    ),
                  })))
                ];

                return <Dropdown menu={{ items }}>
                  <a onClick={(e) => e.preventDefault()}>
                    <Space>
                      {(item.dataType && item.dataType == 3 && _) && formatMoneyNumber(Number(Number(_).toFixed(item.decimalPlace ? item.decimalPlace : 2)))}
                      {(item.dataType && item.dataType == 2 && _ && typeof _ == 'number') && `${(_ * 100).toFixed(item.decimalPlace ? item.decimalPlace : 2)}%`}
                      {(item.dataType != 2 && item.dataType != 3) && _}
                      <DownOutlined />
                    </Space>
                  </a>
                </Dropdown>
              } else {
                return <a className='active' onClick={() => reportJumphandle({ ...item.redirectData[0], ...record })}>
                  {(item.dataType && item.dataType == 3 && _) && formatMoneyNumber(Number(Number(_).toFixed(item.decimalPlace ? item.decimalPlace : 2)))}
                  {(item.dataType && item.dataType == 2 && _ && typeof _ == 'number') && `${(_ * 100).toFixed(item.decimalPlace ? item.decimalPlace : 2)}%`}
                  {(item.dataType != 2 && item.dataType != 3) && _}
                </a>
              }
            }

            return <span >
              {(item.dataType && item.dataType == 3 && _) && formatMoneyNumber(Number(Number(_).toFixed(item.decimalPlace ? item.decimalPlace : 2)))}
              {(item.dataType && item.dataType == 2 && _ && typeof _ == 'number') && `${(_ * 100).toFixed(item.decimalPlace ? item.decimalPlace : 2)}%`}
              {(item.dataType != 2 && item.dataType != 3) && _}
            </span>
          }

        }
      });

      set_tableColumn([...columns]);
      set_tableScrollX(scrollX);

      const data = assignmentData.map((item: any) => {

        let rowData: { [key: string]: any } = {};

        item.forEach((b: any) => {
          const needTitle = title.filter((a: any) => a.code == b.code);
          if (needTitle.length > 0) {
            rowData[`${needTitle[0].columnName}`] = b.value
          }
        });


        return { ...item, ...rowData, id: Math.random(), columns }
      });

      const exportdata = assignmentData.map((item: any) => {

        let rowData: { [key: string]: any } = {};

        item.forEach((b: any) => {
          const needTitle = title.filter((a: any) => a.code == b.code);
          if (needTitle.length > 0) {
            if (needTitle[0].dataType == 2 && typeof b.value == 'number') {
              rowData[`${needTitle[0].columnName}`] = `${(b.value * 100).toFixed(needTitle[0].decimalPlace ? needTitle[0].decimalPlace : 2)}%`
            } else {
              rowData[`${needTitle[0].columnName}`] = b.value
            }
          }
        });


        return { ...item, ...rowData, id: Math.random(), columns }
      });


      if (openProcessModal) {
        totalTableData = [...totalTableData, ...exportdata];
        return {
          currentCount: totalTableData.length,
          totalCount,
          totalPage
        }
      }

      if (!openProcessModal) {
        set_tableData(data);
        dataSource = data;
        set_pagination({
          current,
          total: totalCount,
          pageSize: pageSize,
          totalPage: totalPage,
        })

      }

    } else {
      prevParams = undefined;
      if (!openProcessModal) {
        set_tableData([]);
        dataSource = [];
        set_pagination(false)
      }

    }
    if (!openProcessModal) {
      set_loading(false);
    }
    return openProcessModal ? { currentCount: 0, totalCount: 0 } : []
  }



  const handleResize = (e: any) => {
    const wH = e.target.innerHeight;
    const tableHeight = wH - 290;
    if (!reportCode) {
      set_tableH(tableHeight);
    }
  }

  function doResize() {
    setTimeout(() => {
      const ev: any = new Event('resize');
      window.dispatchEvent(ev);
    }, 0)
  }

  const exportHandle = () => {
    // set_openProcessModal(true);

    let headers: { [key: string]: any } = {};
    let data: any[] = [];

    tableColumn.forEach(a => {
      if (a.hideInTable != 1) {
        headers[`${a.dataIndex}`] = a.title;
      }
    });

    totalTableData.forEach(b => {
      let _temp: { [key: string]: any } = {};
      Object.keys(headers).forEach(key => {
        _temp[`${key}`] = b[`${key}`]
      });
      data.push(_temp);
    });

    //console.log({tableColumn,headers,tableData,data});
    const excelTableData = [
      ...data
    ];

    const _columns = tableColumn.filter(a => a.hideInTable != 1);

    exportTableToExcel(excelTableData, _columns as any[], reportName);
    currentPage = 0;
    maxFetchCount = 0;
    totalTableData = [];
    // tableRef.current?.reload();
  }


  const fetchExportData = async () => {

    currentPage = currentPage + 1;

    const resp: any = await getTableData({ ...tableDataFilterParams, current: currentPage });

    if (resp) {
      const { currentCount = 0, totalCount = 0, totalPage } = resp;

      maxFetchCount = totalPage;
      return { currentCount, totalCount };
    } else {
      return { currentCount: 0, totalCount: 0 };
    }
  };

  const handleCompletion = () => {
    set_openProcessModal(false);
    exportHandle();

  }


  //面包屑跳转
  const switchHandle = (data: any) => {
    set_loading(true);
    set_step(data.index);
    const _breadCrumbList = breadCrumbList.filter((a: any) => a.index <= data.index);
    set_breadCrumbList([..._breadCrumbList]);
    getSearchRows(data.params.reportCode);
  }



  const handleSearchChange = (e: any, node: any, index: number) => {
    const { value } = e.target;

    // 更新搜索内容
    set_searchRows((prevSearchRows) => {
      const updatedSearchRows = [...prevSearchRows];
      updatedSearchRows[index] = { ...updatedSearchRows[index], value };
      return updatedSearchRows;
    });

  };

  const handleReset = () => {
    set_searchRows((prevSearchRows) => {
      const newObj = prevSearchRows.map((row) => ({ ...row, value: '' }))
      const searchObject = newObj.reduce((acc, curr) => {
        acc[curr.columnIndex] = curr.value ? curr.value : '';
        return acc;
      }, {});

      set_tableDataFilterParams({ ...tableDataFilterParams, parameter: { ...( tableDataFilterParams.parameter), ...searchObject } });

      return newObj
    }

    );

  };

  const tableDataSearchHandle = () => {

    const searchObject = searchRows.reduce((acc, curr) => {
      acc[curr.columnIndex] = curr.value ? curr.value : '';
      return acc;
    }, {});
    set_tableDataFilterParams({
      ...tableDataFilterParams,
      parameter: { ...(tableDataFilterParams.parameter), ...searchObject }
    });

  }

  const tableDataColumnSearchHandle = () => {

    if (tableDataSearchKeywords) {
      // 确保 searchKeys 不为空
      if (searchKeys.length === 0) {
        set_tableData(dataSource);
        return;
      }

      const keys = searchKeys.map(a => a.key);
      const result = multiAttributeSearchOptimized(tableData, keys, [tableDataSearchKeywords as string]);
      set_tableData(result);
    } else {
      // 恢复到初始数据
      set_tableData(dataSource);
    }
  };


  useEffect(() => {
    // 在这里处理路由参数变化的逻辑
    set_loading(true);
    set_tableDataFilterParams(undefined);
    set_breadCrumbList([{
      name: '首页',
      index: 0,
      params: { reportCode: urlReportCode, parameter: { ...(reportCode ? tableDataFilterParams?.parameter : {}), compute_date: currentComputeDate } }
    }]);

    urlReportCode && getSearchRows(urlReportCode);

  }, [urlReportCode]);


  useEffect(() => {

    if (currentComputeDate) {
      const searchObject = searchRows.reduce((acc: { [x: string]: any; }, curr: { columnIndex: string | number; value: any; }) => {
        acc[curr.columnIndex] = '';
        return acc;
      }, {});
      set_tableDataFilterParams({ ...tableDataFilterParams, parameter: { ...(reportCode ? tableDataFilterParams?.parameter : {}), compute_date: currentComputeDate,...searchObject } });
    }
  }, [currentComputeDate]);


  useEffect(() => {
    if (tableDataFilterParams) {
      getTableData(tableDataFilterParams);
    }
  }, [tableDataFilterParams]);





  useEffect(() => {

    window.addEventListener('resize', (e) => handleResize(e)) //监听窗口大小改变
    doResize();

    return () => {
      window.removeEventListener('resize', (e) => handleResize(e))
    }
  }, [])


  return (
    <KCIMPagecontainer className='ReportTemplate' title={false} style={reportCode ? { border: 'none' } : {}}>

      <ExportProgressModal
        visible={openProcessModal}
        onCancel={() => set_openProcessModal(false)}
        fetchData={fetchExportData}
        onCompletion={handleCompletion}
      />

      {
        breadCrumbList.length > 1 && <div className='breadcrumb'>
          {
            breadCrumbList.map((item: any, index: number) => {
              return (
                <>
                  <span className={index != step ? 'tab' : 'tab actived'} key={index} onClick={() => { index != step && switchHandle(item) }}>{item.name}</span>{index == breadCrumbList.length - 1 ? '' : <span style={{ color: '#7A8599' }}> / </span>}
                </>
              )
            })
          }
        </div>
      }
      <div className='contentWrap' style={reportCode ? { padding: 0 } : {}}>
        <div className='toolbar'>
          {(currentComputeDate && !reportCode) && (<div className='search'>
            <span>核算年月：</span>
            <DatePicker
              disabled={breadCrumbList.length>1}
              onChange={(data, dateString) => {
                set_currentComputeDate(dateString);
                setInitialState((s: any) => ({ ...s, computeDate: dateString }))
              }}
              allowClear={false}
              picker='month'
              locale={locale}
              autoComplete="off"
              value={moment(currentComputeDate, 'YYYY-MM')}
              format='YYYY-MM' placeholder="请选择核算年月" />

            <div style={{ display: (searchType == 1 && searchKeys.length > 0) ? 'flex' : 'none', flexDirection: 'row', alignItems: 'center', marginLeft: 16 }}>
              <span style={{ whiteSpace: 'nowrap' }}>检索：</span>
              <ProFormText
                noStyle
                // style={{width:(searchKeys.length)*20}}
                width={((searchKeys.length) * 100) > 675 ? 675 : (searchKeys.length) * 100}
                placeholder={searchKeys.reduce((prev, cur) => `${prev.length > 0 ? prev + '/' : prev}${cur.name}`, '')}
                fieldProps={{
                  suffix:
                    < IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataColumnSearchHandle()} />
                  ,
                  onChange: (e) => {
                    if (e.target.value) {
                      tableDataSearchKeywords = e.target.value
                    } else {
                      tableDataSearchKeywords = undefined;
                      tableDataColumnSearchHandle();
                    }
                  },
                  onPressEnter: (e) => tableDataColumnSearchHandle()
                }}
              />
            </div>

            <div style={{ display: (searchRows && searchRows.length > 0) ? 'flex' : 'none', flexDirection: 'row', alignItems: 'center', marginLeft: 8 }}>
              {/* <span style={{ whiteSpace: 'nowrap' }}>检索：</span> */}
              {
                (searchRows ? searchRows : []).map((node, index) => {
                  return (
                    <ProFormText
                      key={index}
                      noStyle
                      width={150}
                      // allowClear={false}
                      style={{ marginRight: 8 }}
                      placeholder={`${node.tips}`}
                      fieldProps={{
                        style: { marginRight: 8 },
                        value: node.value,
                        // suffix:
                        //   < IconFont type="iconsousuo" style={{ color: '#99A6BF' }} 

                        //   />
                        // ,
                        onChange: (e) => {
                          handleSearchChange(e, node, index)
                        },

                      }}
                    />
                  )
                })
              }
            </div>

          </div>)}
          {!reportCode && <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
            {searchType == 2 && <div className='searchBtn' onClick={() => handleReset()}>重置</div>}
            {searchType == 2 && <div className='searchBtn' onClick={() => tableDataSearchHandle()}>查询</div>}
            <div className='export' onClick={() => set_openProcessModal(true)}>导出</div>
          </div>}
        </div>



        <div className='ReportTemplateContent' style={reportCode ? { paddingTop: 0 } : {}}>

          {/* {(currentComputeDate&&(searchType == 0||searchType == 2) ) && <KCIMTable actionRef={tableRef} rowKey='id' columns={tableColumn as ProColumns[]}
            params={tableDataFilterParams}
            scroll={{ x: tableScrollX, y: tableH }}
            loading
            pagination={{ pageSizeOptions: [10, 20, 50, 100, 1000], showSizeChanger: true, pageSize }}
            request={(params, sort, filter) => getTableData(params)}
          />} */}

          {(currentComputeDate) && <KCIMTable actionRef={tableRef} rowKey='id' columns={tableColumn as ProColumns[]}
            // params={tableDataFilterParams}
            loading={loading}
            scroll={{ x: tableScrollX, y: tableH }}
            dataSource={tableData}
            pagination={searchType == 1 ? { pageSizeOptions: [10, 20, 50, 100, 1000], showSizeChanger: true, pageSize } : {
              ...pagination,
              onChange(page, pageSize) {
                getTableData({ ...tableDataFilterParams, current: page, pageSize });
              },
            }}
          />}
        </div>
      </div>
    </KCIMPagecontainer>
  )
}

export default ReportExport

