/*
 * @Author: code4eat awesomedema@gmail.com
 * @Date: 2023-03-03 11:30:33
 * @LastEditors: code4eat awesomedema@gmail.com
 * @LastEditTime: 2024-09-06 13:57:10
 * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/index.tsx
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */



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

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


import { ActionType, ProFormDependency, ProFormInstance, ProFormText, ProFormSelect, ProFormDigit } from '@ant-design/pro-components';
import { ModalForm } from '@ant-design/pro-form'
import { ProColumns } from '@ant-design/pro-table';
import { Modal, message, Drawer, Tabs, Input, DatePicker,Popover } from 'antd';
import { Key, useEffect, useRef, useState } from 'react';
import * as XLSX from 'xlsx';
import { saveAs } from 'file-saver';
import moment from 'moment';
import 'moment/locale/zh-cn';
import locale from 'antd/es/date-picker/locale/zh_CN';



import { addData, computeProfitReq, copyDataToSelectedType, delData, editData, getReportDataReq, getReportProjectSettingList, getResponsibleCenters, saveReportRelation } from './service';

import './style.less';
import TableTransfer from './transform';
import React from 'react';
import { cleanTree, getStringWidth } from '@/utils/tooljs';
import { getDicDataBySysId } from '@/services/getDic';
import { KCIMLeftList } from '@/components/KCIMLeftList';
import { formatMoneyNumber } from '@/utils/format';
import { useModel } from '@umijs/max';



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

let currentRow: any = undefined;

function findAllParents(tree: any[]) {
    let parents: any[] = [];
    // 递归函数来遍历树并找到所有父节点
    function traverse(nodes: any[]) {
        for (const node of nodes) {
            // 检查节点是否有子节点
            if (node.children && node.children.length > 0) {
                parents.push(node); // 添加到父节点列表
                traverse(node.children); // 递归遍历子节点
            }
        }
    }

    traverse(tree); // 开始遍历树
    return parents; // 返回所有父节点的数组
}

function countLeafNodes(trees:any[]) {
    let leafCount = 0;

    // 遍历集合中的每棵树
    for (let i = 0; i < trees.length; i++) {
        leafCount += countLeafNodesRecursive(trees[i]);
    }

    return leafCount;
}

function countLeafNodesRecursive(node:any) {
    // 如果当前节点没有子节点，说明它是一个叶子节点
    if (!node.children || node.children.length === 0) {
        return 1;
    }

    let leafCount = 0;

    // 递归计算每个子节点的叶子节点数
    for (let i = 0; i < node.children.length; i++) {
        leafCount += countLeafNodesRecursive(node.children[i]);
    }

    return leafCount;
}


function searchTree(tree: any[], searchTerm: string) {
    // 定义结果数组
    let results = [];

    // 定义递归函数来搜索匹配的节点
    function searchNode(node: any) {
        // 创建一个变量来标记当前节点或其子节点是否匹配
        let isMatch = false;

        // 检查当前节点的 name 或 code 是否包含搜索词
        if (node.reportName.includes(searchTerm)) {
            isMatch = true;
        }

        // 复制当前节点，避免修改原始数据
        let newNode = { ...node, children: [] };

        // 如果有子节点，递归搜索每个子节点
        if (node.children) {
            for (let child of node.children) {
                let childMatch = searchNode(child);
                // 如果子节点或其子树匹配，添加到新节点的子节点数组中
                if (childMatch) {
                    newNode.children.push(childMatch);
                    isMatch = true;
                }
            }
        }

        // 如果当前节点或其任何子节点匹配，返回新节点
        // 如果children为空，则不包含children属性
        if (isMatch) {
            if (newNode.children.length === 0) {
                delete newNode.children;
            }
            return newNode;
        } else {
            return null;
        }
    }

    // 遍历树的每个顶级节点
    for (let node of tree) {
        let result = searchNode(node);
        if (result) {
            results.push(result);
        }
    }

    return results;
}

function processTree(originalData: any[]) {
    return originalData.map(node => {
        // 深复制当前节点
        const newNode = JSON.parse(JSON.stringify(node));

        // 如果当前节点有profitList，处理它
        if (newNode.profitList && Array.isArray(newNode.profitList)) {
            newNode.profitList.forEach((profit: any) => {
                // 添加新的键值对到新节点
                newNode[`${profit.reportId}`] = formatMoneyNumber(profit.value);
            });
            // 如果不需要保留profitList，可以删除
            // delete newNode.profitList;
        }

        // 如果节点有子节点，递归处理子节点
        if (node.child && Array.isArray(node.child)) {
            newNode.children = processTree(node.child);
        }

        return newNode;
    });
}

// 递归函数，用于处理多层级标题
function generateColumns(item: any, titleIndex = 0) {
    const column: any = {
        title: item.reportName,
        dataIndex: `${item.reportId}`,
        key: `${item.reportId}`,
        // align: 'center',

    };

    if (item.childTitle && Array.isArray(item.childTitle) && item.childTitle.length > 0) {
        column.children = item.childTitle.map((a: any, aindex: number) => generateColumns(a, titleIndex + 1));
    }

    return column;
}

// 主函数，生成表格列
const generateTableColumns = (title: any[]) => {
    return title.map((item: any, titleIndex: number) => generateColumns(item, titleIndex));
};


export default function DepartmentCostCalc() {

    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>({ reportType: 0 });
    const tableRef = useRef<ActionType>();
    const formRef = useRef<ProFormInstance>();
    const [tabs, set_tabs] = useState<any[]>([]);

    const { initialState,setInitialState } = useModel('@@initialState');
    const [computeDate, set_computeDate] = useState<string>(initialState?initialState.computeDate:'');
    const [responsibleCenters, set_responsibleCenters] = useState<any[]>([]);
    const [currentTabKey, set_currentTabKey] = useState<any | undefined>(undefined);
    const [currentTab, set_currentTab] = useState<any | undefined>(undefined);
    const [currentSelectedRespon, set_currentSelectedRespon] = useState<any | undefined>(undefined);
    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState('');
    const [allParentsKeys, set_allParentsKeys] = useState<Key[]>([]);
    const [drawerTableVisible, set_drawerTableVisible] = useState(false);
    const [dataSource, set_dataSource] = useState<any[]>([]);
    const [tableColumns, set_tableColumns] = useState<any[]>([]);
    const columns: ProColumns[] = [

        {
            title: '报表项目名称',
            dataIndex: 'reportName',
            width: '50%',
            renderText(text, record, index, action) {
                const {description} = record;
                return description?<Popover content={description}><span style={{cursor:'pointer'}}>{text}</span><IconFont className="hover-icon" style={{fontSize:16,color:'#17181a',paddingLeft:4,position:'relative',top:1}} type={'iconshuoming'} /></Popover>:text
            },
        },
        {
            title: '金额(元)',
            align:'right',
            dataIndex: 'amount',
            renderText(num,record) {
                if (record.children) {
                    return <React.Fragment></React.Fragment>
                }else{
                    return formatMoneyNumber(num);
                } 
            },
        },
        {
            title: '占比',
            align:'right',
            dataIndex: 'percent',
            renderText(num,record) {
                if (record.children) {
                    return <React.Fragment></React.Fragment>
                }else{
                    return `${((num * 100).toFixed(2))}%`
                } 
                
            },
        },
    ]


    const getTableData = async (params: any) => {
        const { responsibilityCode, filter = undefined } = params;
        if (!responsibilityCode) return []
        const resp = await getReportProjectSettingList({ ...params });

        if (resp) {
            if (filter) {
                const filterData = searchTree(resp, filter);
                const allParents = findAllParents(filterData);

                set_allParentsKeys([...(allParents.map((a: any) => a.id))])
                return {
                    data: filterData,
                    success: true,
                }
            }
            const allParents = findAllParents(resp);
            set_allParentsKeys([...(allParents.map((a: any) => a.id))])
            return {
                data: resp,
                success: true,
            }
        }
        return []
    }




    const onTabChanged = (key: Key) => {
        set_currentTabKey(key);
        const needItem = tabs.filter((a) => a.key == key);
        if (needItem.length > 0) set_currentTab(needItem[0])
    }

    const getTabs = async () => {

        const { systemId } = JSON.parse((localStorage.getItem('currentSelectedTab')) as string)
        const resp = await getDicDataBySysId(systemId, 'PROFIT_REPORT_TYPE');
        if (resp) {
            const { dataVoList } = resp;
            const tempArr = dataVoList.map((a: any) => ({ label: a.name, key: Number(a.code), value: a.value }));
            const arr = (tempArr.filter((a: any) => a.value != '2'));
            set_tabs([...arr]);
            set_currentTabKey(arr[0].key);
            set_currentTab(arr[0]);
        }
    }

    const getResponsibleCenterList = async (reportType: string) => {
        const resp = await getResponsibleCenters(reportType);
        if (resp) {
            set_responsibleCenters(resp);
        }
    }

    const onLeftChange = (currentSelected: any) => {
        set_currentSelectedRespon(currentSelected);
    }

    const tableDataSearchHandle = (paramName: string) => {

        set_tableDataFilterParams({
            ...tableDataFilterParams,
            [`${paramName}`]: tableDataSearchKeywords
        })
    }

    const computeProfitHandle = async () => {

        Modal.confirm({
            title: '注意',
            content: '计算操作会覆盖当月已计算的数据，是否继续操作？',
            okText: '确定',
            cancelText: '取消',
            onOk: async (...args) => {

                const resp = await computeProfitReq(computeDate, currentTabKey);
                if (resp) {
                    message.success('操作成功！');
                    tableRef.current?.reload();
                }
            },
        })
    }

    const openTableDataDrawer = async () => {
        set_drawerTableVisible(true);
        const resp = await getReportDataReq(currentTabKey, computeDate);
        if (resp) {
            const { title = [], data = [] } = resp;
            const defaultColumns = [{
                title: '科室名称',
                dataIndex: 'responsibilityName',
                key: 'responsibilityName',
                width: 220,
                fixed: 'left'
            }];

            const tableColumns = generateTableColumns(title);

            const dataSource = processTree(data);
            set_tableColumns([...defaultColumns, ...tableColumns]);

            set_dataSource(dataSource);
            
            // console.log({ columns: [...defaultColumns, ...tableColumns], dataSource })

        }

    }


const getHeaderRows = (columns: any[], level = 0, headerRows:any[] = [], maxLevel = 0) => {
    headerRows[level] = headerRows[level] || [];
    columns.forEach((col: { title: any; children: any; }) => {
        const colSpan = getColSpan(col);
        headerRows[level].push({ title: col.title, colSpan, rowSpan: col.children ? 1 : maxLevel - level });
        if (col.children) {
            getHeaderRows(col.children, level + 1, headerRows, maxLevel);
        } else {
            // 填充空白单元格
            for (let i = level + 1; i < maxLevel; i++) {
                headerRows[i] = headerRows[i] || [];
                headerRows[i].push({ title: '', colSpan: 1, rowSpan: 1 });
            }
        }
    });
    return headerRows;
};

const getColSpan:any = (col: { children: any[]; }) => {
    if (!col.children) return 1;
    return col.children.reduce((sum, child) => sum + getColSpan(child), 0);
};

const getMaxLevel = (col: any) => {
    if (!col.children) return 1;
    return 1 + Math.max(...col.children.map(getMaxLevel));
};

const extractLeafColumns = (columns: any[]) => {
    let leafColumns: any[] = [];
    columns.forEach(col => {
        if (col.children) {
            leafColumns = leafColumns.concat(extractLeafColumns(col.children));
        } else {
            leafColumns.push(col);
        }
    });
    return leafColumns;
};

const addRowWithIndentation = (record: any, level: number, leafColumns: any[], worksheetData: any[]) => {
    const row = leafColumns.map(col => record[col.dataIndex] ?? '');
    row[0] = ' '.repeat(level * 4) + row[0]; // 在第一列前添加缩进空格以表示层级
    worksheetData.push(row);
    if (record.children) {
        record.children.forEach((child: any) => addRowWithIndentation(child, level + 1, leafColumns, worksheetData));
    }
};

const handleExport = () => {
    try {
        const workbook = XLSX.utils.book_new();
        const worksheetData: any[] = [];

        // 获取最大层级
        const maxLevel = tableColumns.reduce((max, col) => Math.max(max, getMaxLevel(col)), 0);

        // 生成多层级表头
        const headerRows = getHeaderRows(tableColumns, 0, [], maxLevel);

        // 构建表头行
        headerRows.forEach((row: any, rowIndex) => {
            const rowData: string[] = [];
            row.forEach((cell: { title: any; colSpan: number; rowSpan: number; }) => {
                rowData.push(cell.title);
                for (let i = 1; i < cell.colSpan; i++) {
                    rowData.push('');
                }
            });
            worksheetData.push(rowData);
        });

        // 填充单层表头的空白行
        if (maxLevel > 1) {
            const numColumns = headerRows[0].reduce((sum: any, cell: { colSpan: any; }) => sum + cell.colSpan, 0);
            for (let i = 1; i < maxLevel; i++) {
                while (worksheetData[i].length < numColumns) {
                    worksheetData[i].push('');
                }
            }
        }

        // 提取最内层表头列
        const leafColumns = extractLeafColumns(tableColumns);

        // 添加数据并处理树结构
        dataSource.forEach(record => addRowWithIndentation(record, 0, leafColumns, worksheetData));

        const worksheet = XLSX.utils.aoa_to_sheet(worksheetData);

        // 初始化合并单元格数组
        worksheet['!merges'] = worksheet['!merges'] || [];

        // 合并单元格
        headerRows.forEach((row: any, rowIndex) => {
            let colIndex = 0;
            row.forEach((cell: { colSpan: number; rowSpan: number; }) => {
                if (cell.colSpan > 1 || cell.rowSpan > 1) {
                    worksheet['!merges'].push({
                        s: { r: rowIndex, c: colIndex },
                        e: { r: rowIndex + cell.rowSpan - 1, c: colIndex + cell.colSpan - 1 }
                    });
                }
                colIndex += cell.colSpan;
            });
        });

        // 设置单元格对齐方式
        Object.keys(worksheet).forEach(cell => {
            if (cell[0] !== '!') {
                worksheet[cell].s = {
                    alignment: { vertical: 'center', horizontal: 'center' }
                };
            }
        });

        XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');

        const wbout = XLSX.write(workbook, { bookType: 'xlsx', type: 'binary' });
        const s2ab = (s: string) => {
            const buf = new ArrayBuffer(s.length);
            const view = new Uint8Array(buf);
            for (let i = 0; i < s.length; i++) view[i] = s.charCodeAt(i) & 0xFF;
            return buf;
        };

        saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), currentTab ? `${currentTab.label}.xlsx` : 'table_data.xlsx');
    } catch (error) {
        console.error('Export failed:', error);
    }
};

















    useEffect(() => {
        if (computeDate && currentTabKey != undefined) {
            getResponsibleCenterList(currentTabKey);
        }
    }, [computeDate, currentTabKey]);

    useEffect(() => {
        if (currentSelectedRespon) {
            set_tableDataFilterParams({
                ...tableDataFilterParams,
                responsibilityCode: currentSelectedRespon.responsibilityCode,
                reportType: currentTabKey,
                computeDate: computeDate
            })
        }
    }, [currentSelectedRespon])


    useEffect(() => {
        getTabs();
    }, [])

    return (
        <KCIMPagecontainer className='DepartmentCostCalc' title={false}>

            <Drawer className='drawerTable' contentWrapperStyle={{}} bodyStyle={{ padding: 16 }} title={false} open={drawerTableVisible} width={1000} headerStyle={{ display: 'none' }}>
                <div className='header'>
                    <div className='title'>{currentTab ? currentTab.label : ''}（单位：元）</div>
                    <div className='btns'>
                        <span onClick={() => set_drawerTableVisible(false)}>关闭</span>
                        <span className='close'  onClick={() => handleExport()}>导出</span>
                   
                    </div>
                </div>
                <KCIMTable loading={dataSource.length == 0} expandable={{ defaultExpandAllRows: true }} className='departmentCostCalcReportTable' dataSource={dataSource} bordered pagination={false} scroll={{ x:countLeafNodes(tableColumns) * 120, y:`calc(100vh - 198px)` }} columns={tableColumns as ProColumns[]} rowKey='responsibilityCode' /> 
            </Drawer>

            <div className='header'>
                <div className="search">
                    <span>核算年月：</span>
                    <DatePicker
                        onChange={(data, dateString) => {
                            set_computeDate(dateString);
                            setInitialState((s:any)=>({...s,computeDate: dateString,}))
                            set_tableDataFilterParams({
                                ...tableDataFilterParams,
                                computeDate: dateString,
                            });
                        }}
                        picker="month"
                        locale={locale}
                        defaultValue={moment(computeDate, 'YYYY-MM')}
                        format="YYYY-MM"
                        placeholder="选择年月"
                    />
                </div>
            </div>
            <div className='content'>
                <Tabs
                    defaultActiveKey={tabs.length > 0 ? tabs[0].key : undefined}
                    items={tabs}
                    key={'key'}
                    onChange={(key) => onTabChanged(key)}
                />
                <div className='inner'>
                    <div className='left'>
                        <KCIMLeftList
                            fieldNames={{ title: 'responsibilityName', key: 'responsibilityCode', children: 'children' }}
                            rowKey={'responsibilityCode'}
                            dataSource={responsibleCenters} searchKey={'responsibilityName'}
                            onChange={onLeftChange}
                            contentH={`100%`}
                            // placeholder={leftListSearchPlaceHolder} 
                            listType={'tree'}

                        />
                    </div>
                    <div className='right'>
                        <div className='toolBar'>
                            <div className='filterItem' style={{ width: 228 }}>
                                <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索：</span>
                                <Input placeholder={'报表项目代码/名称'} allowClear
                                    suffix={
                                        <IconFont type="iconsousuo" style={{ color: '#99A6BF' }} onClick={() => tableDataSearchHandle('filter')} />
                                    }
                                    onChange={(e) => {
                                        set_tableDataSearchKeywords(e.target.value);
                                        if (e.target.value.length == 0) {
                                            set_tableDataFilterParams({
                                                ...tableDataFilterParams,
                                                filter: ''
                                            });
                                        }
                                    }}
                                    onPressEnter={(e) => {
                                        set_tableDataFilterParams({
                                            ...tableDataFilterParams,
                                            filter: ((e.target) as HTMLInputElement).value
                                        });
                                    }}

                                />
                            </div>
                            <div className='btnGroup'>
                                <span className='btn' onClick={() => openTableDataDrawer()}>报表数据</span>
                                <span className='calc' onClick={() => computeProfitHandle()}>计算</span>
                            </div>
                        </div>
                        <KCIMTable pagination={false} 
                        rowClassName={(record) => (record.children ? 'has-children hover-row' : 'hover-row')}
                        expandable={{
                            defaultExpandAllRows: true, expandedRowKeys: allParentsKeys,
                            onExpand(expanded, record) {
                                const { id } = record;
                                if (!expanded) {
                                    const expandedKeys = allParentsKeys.filter(a => a != id);
                                    set_allParentsKeys([...expandedKeys]);
                                } else {
                                    set_allParentsKeys([...allParentsKeys, id]);
                                }
                            },
                        }} columns={columns as ProColumns[]} scroll={{ y: `calc(100vh - 302px)` }} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
                    </div>
                </div>


            </div>
        </KCIMPagecontainer>
    )
}
