import React, { useEffect, useRef, useState } from "react";
import { Action, Api, SchemaNode } from '../../../types'
import { Button } from "../../../components";
import { RendererEnv } from '../../../env'

import { Tabs, Input, Select, Button as AntdButton, Checkbox, message } from 'antd';
import type { CheckboxChangeEvent } from 'antd/es/checkbox';
import Dialog from '../../../components/DragModal';
import './index.scss';
import { debounce } from "lodash";
interface IProps {
  action: Action
  render: (region: string, node: SchemaNode, props?: any) => JSX.Element
  container: HTMLElement | null;
  selectedList: any[];
  columns: any[];
  sqlStr: string;
  env: RendererEnv;
  store: any
}
interface ServerApiData {
  tableList: Api,
  updateSql: Api
}

interface TableNameItem {
  tableName: string
}
interface ColumnItem {
  columns: string[];
  primaryKey: string;
}
interface KeyColumnsItem {
  value: string;
  label?: string;
  type: string;
  checked?: boolean;
  /** 关键词匹配 */
  match?: boolean;
}
const SqlOptimize = (props: IProps) => {
  const { action, selectedList, sqlStr, env, store } = props;
  const [visible, setVisible] = useState(false);
  /** 生成语句后的数据源 */
  const [sqlData, setSqlData] = useState({});
  /** 表名列表 */
  const [tableList, setTableList] = useState([]);
  /** 表名数据 */
  const [tableName, setTableName] = useState<string | undefined>();
  /** 所有表 */
  const [allTable, setAllTable] = useState([]);
  /** 主键对应的columns */
  const [primaryKeyColumns, setPrimaryKeyColumns] = useState<KeyColumnsItem[]>([]);
  /** 更新字段对应的columns */
  const [updateKeyColumns, setUpdateKeyColumns] = useState<KeyColumnsItem[]>([]);
  /** 生成语句的loading */
  const [genLoading, setGenLoading] = useState(false);
  const mainTabRef = useRef<HTMLUListElement>(null);
  const reqMap: ServerApiData = {
    tableList: {
      data: {
        sql: "${sql}"
      },
      method: 'post',
      url: '/api/v1/db/tool/info'
    },
    updateSql: {
      data: {
        columns: "${columns}",
        wheres: "${wheres}",
        tableName: "${tableName}",
        data: "${data}"
      },
      method: 'post',
      url: '/api/v1/db/tool/script'
    }
  }
  const columnsMap = {
    primaryKey: primaryKeyColumns,
    updateKey: updateKeyColumns
  }
  const updateColumnsMap = {
    primaryKey: setPrimaryKeyColumns,
    updateKey: setUpdateKeyColumns
  }
  useEffect(() => {
    if (visible) {
      handleGetTableNameList();
    }
  }, [visible]);
  /** 获取表名列表 */
  const handleGetTableNameList = async () => {
    const params = { sql: sqlStr };
    const res = await env.fetcher(reqMap['tableList'], params);
    if (res.ok && res.data) {
      const tableNames = res.data.map((item: TableNameItem) => ({ label: item.tableName, value: item.tableName })).filter(Boolean);
      setAllTable(res.data);
      /** 配置表名列表与默认表名 */
      setTableName(tableNames[0]?.['value']);
      setTableList(tableNames);
      /** 初始化第一个表名 */
      handleGenColumns(res.data[0]);
    }
  }
  const handleToggleTable = (tableName: string) => {
    const targetItem = allTable.find((item: TableNameItem) => item.tableName === tableName);
    if (targetItem) {
      setTableName(tableName);
      handleGenColumns(targetItem);
    }
  }
  /** 初始化字段 */
  const handleGenColumns = (data: ColumnItem) => {
    const { columns, primaryKey = '' } = data;
    /** 配置主键列表 */
    const pKeyColumns: KeyColumnsItem[] = columns.map((item) => ({ label: item, value: item, type: 'primaryKey', checked: primaryKey.includes(item) }))
    const updateKeyColumns = columns.map((item: string) => ({ label: item, value: item, type: 'updateKey' }));

    setPrimaryKeyColumns(pKeyColumns);
    setUpdateKeyColumns(updateKeyColumns);
  }
  /** 选中 主键/更新字段 */
  const handleColumnChange = (column: KeyColumnsItem, e: CheckboxChangeEvent) => {
    const { type, value } = column;
    const { checked } = e.target;
    if (type === 'primaryKey') {
      setPrimaryKeyColumns((cols = []) => {
        const newCols = cols.map((item: KeyColumnsItem) => item.value === value ? ({ ...item, checked }) : item);
        return newCols;
      });
    } else {
      setUpdateKeyColumns((cols = []) => {
        const newCols = cols.map((item) => item.value === value ? ({ ...item, checked }) : item);
        return newCols;
      })
    }
  };
  /** 获取主键 */
  const handleGetPrimeKey = () => {
    const targetItem = allTable.find((item: TableNameItem) => item.tableName === tableName);
    if (targetItem) {
      const { primaryKey } = targetItem;
      // setPrimaryKeyColumns((cols) => {
      //   const newCols = cols.map((item) => ({ ...item, checked: item.value === primaryKey }))
      //   return newCols;
      // });
      debounceFilter(primaryKey, 'primaryKey', true);
    }
  }
  /** 生成语句 */
  const handleGenerateSql = async () => {
    try {
      setGenLoading(true);
      const updateColumns = updateKeyColumns.map((item) => item.checked ? item.value : undefined).filter(Boolean);
      const primaryKeys = primaryKeyColumns.map((item) => item.checked ? item.value : undefined).filter(Boolean);
      const params = {
        tableName: tableName,
        columns: updateColumns,
        wheres: primaryKeys,
        data: selectedList
      };
      const res = await env.fetcher(reqMap['updateSql'], params);
      if (res.ok && res.data) {
        message.success('已生成语句');
        setSqlData(res.data);
      } else {
        message.error(res.msg);
      }
    } finally {
      setGenLoading(false);
    }
  }


  /** 执行过滤 */
  const handleFilter = (searchValue: string = '', type: string, forceCheck?: boolean) => {
    const sortColumns: KeyColumnsItem[] = columnsMap[type];
    const updateColumns = updateColumnsMap[type];
    const trimVal = searchValue.trim();
    //匹配规则，1.全匹配 2.以关键字开头匹配 3.模糊匹配
    let target = sortColumns.find(item => item.label === trimVal);
    !target && (target = sortColumns.find(item => trimVal.length && item.label?.startsWith(trimVal)));
    !target && (target = sortColumns.find(item => trimVal.length && item.label?.includes(trimVal)));

    const { value } = target ?? {};
    updateColumns((columns: KeyColumnsItem[]) => {
      const newColumns = columns.map((item) => {
        return {
          ...item,
          match: item.value === value,
          // 如果是获取主键，则默认只勾选默认主键
          checked: forceCheck ? item.value === value : item.checked
        }
      });
      return newColumns;
    });
    if (target) {
      setTimeout(() => {
        requestAnimationFrame(() => {
          const boxDom = mainTabRef.current?.querySelector(`.columns-box.${type}`);
          const matchItem = boxDom?.querySelector('.column-item.match');
          matchItem?.scrollIntoView({ behavior: 'smooth', block: 'start' });
        });
      }, 100);
    }
  }
  /** 关键词过滤时触发 */
  const debounceFilter = debounce(handleFilter, 300);

  /** 切换选值 */
  const columnCheck = (checkType: string, columnType: string) => {
    const columnsMap = {
      'primaryKey': setPrimaryKeyColumns,
      'updateKey': setUpdateKeyColumns
    };
    columnsMap[columnType]?.((cols: KeyColumnsItem[]) => {
      let newColumns = cols;
      switch (checkType) {
        /** 全选 */
        case 'all':
          newColumns = cols.map((item) => ({ ...item, checked: true, match: false }));
          break;
        /** 反选 */
        case 'rebellion':
          newColumns = cols.map((item) => ({ ...item, checked: !item.checked, match: false }))
          break;
        /** 不选 */
        case 'clear':
          newColumns = cols.map((item) => ({ ...item, checked: false, match: false }));
          break;
      }
      return newColumns;
    });
  }
  /** 渲染主键/更新字段 */
  const columnTogglerRender = () => {
    const configs = [
      {
        label: '主键',
        type: 'primaryKey'
      },
      {
        label: '更新字段',
        type: 'updateKey'
      }
    ];

    const render = configs.map((item) => {
      const { type, label } = item;
      return (
        <div className={`tab-item ${type}`} key={type}>
          <div className="title-box">
            <div className="l">{label}</div>
            <div className="r">
              <AntdButton type="link" size="small" onClick={() => columnCheck('all', type)}>全选</AntdButton>
              <AntdButton type="link" size="small" onClick={() => columnCheck('rebellion', type)} >反选</AntdButton>
              <AntdButton type="link" size="small" onClick={() => columnCheck('clear', type)} >不选</AntdButton>
            </div>
          </div>
          <div className="filter-box">
            <Input className="filter-inp" placeholder="请输入关键词" onChange={(e) => debounceFilter(e.target.value, type)} allowClear />
          </div>
          <div className={`content columns-box ${type}`}>
            {
              (columnsMap[type]).map((column: KeyColumnsItem) => (
                <div className={`column-item ${column.match ? 'match' : ''}`} key={column.label}>
                  <Checkbox key={column.label} checked={column.checked} onChange={(e) => handleColumnChange(column, e)}>{column.label}</Checkbox>
                </div>
              ))
            }
          </div>
        </div>
      )
    })
    return render;
  }
  /** 主选项渲染 */
  const mainTabRenderer = () => {
    return (
      <div className="main-tab" ref={mainTabRef}>
        <div className="tab-item">
          <div className="title-box">
            <div className="l">表名</div>
            <div className="r"></div>
          </div>
          <div className="content">
            <Select className="table-select" placeholder="请选择表名" value={tableName} options={tableList} onChange={(e: string) => handleToggleTable(e)}></Select>

            <AntdButton block type="primary" onClick={handleGetPrimeKey}>获取主键</AntdButton>
            <AntdButton block onClick={handleGenerateSql} loading={genLoading}>生成语句</AntdButton>
          </div>
        </div>
        {columnTogglerRender()}

      </div>
    );
  }
  /** 新增/修改/删除 语句 */
  const updateSqlRenderer = (value = []) => {
    const newStr = value.join('\n');
    return (
      <div className="update-tab">
        <Input.TextArea value={newStr} autoSize={{ minRows: 6, maxRows: 22 }}></Input.TextArea>
      </div>
    )
  }
  const handleResetData = () => {
    setTableName(undefined);
    setPrimaryKeyColumns([]);
    setUpdateKeyColumns([]);
    setVisible(false);
  }
  const tabs = [
    {
      label: '选项',
      key: 'main-tab',
      children: mainTabRenderer()
    },
    {
      label: '新增语句',
      key: 'insert-tab',
      children: updateSqlRenderer(sqlData['insertSql'])

    },
    {
      label: '修改语句',
      key: 'update-tab',
      children: updateSqlRenderer(sqlData['updateSql'])

    },
    {
      label: '删除语句',
      key: 'del-tab',
      children: updateSqlRenderer(sqlData['deleteSql'])

    },
  ]
  return (
    <div className="sql-optimize-container">
      <Button onClick={() => setVisible(true)} className="open-btn">{action?.label}</Button>

      {visible && <Dialog
        className="sql-optimize-dialog"
        width={710}
        title="生成语句"
        dialogVisible={visible}
        setFixRight={false}
        resizeable={false}
        canClickBelowDom
        mask={false}
        centered
        setMaxSize={false}
        footer={false}
        getContainer={(env.container ?? env.getModalContainer) as () => HTMLElement}
        onCancel={() => handleResetData()}
      >
        <Tabs
          defaultActiveKey="main"
          type="card"
          items={tabs}
        ></Tabs>
      </Dialog>
      }
    </div>
  )
}
export default SqlOptimize;