import { Button, Col, Form, Input, message, Row, Select, Table, Tag } from 'antd';
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import { isEmptyBol, regPriceNumber } from '~/utils/validateUtils';
import EditableCell from '~/components/EditableCell';
import { InterDataType, InterReqType } from '~/api/interface';
import { addMallGoodsType, mallGoodsDetailsType } from '~/api/interface/goodsType';
import { filterObjAttr } from '~/utils';

type EditableTableProps = Parameters<typeof Table>[0];
type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>;

//规格表单数据类型
type specificationFormListType = {
  optionList: { label: string; value: string }[];
  id: number;
  name: string;
  addSpecificationValueShow: boolean;
  specificationValueList: { name: string; id: number; specificationName: string }[];
};
//规格表格类型
type skuTableType = Exclude<InterReqType<addMallGoodsType>, undefined>['priceStock'][0] & {
  fileList: {
    id: number;
    name: string;
    uid: number;
    url: string;
  }[];
};
//商品详情-返回类型
type goodsDetailType = InterDataType<mallGoodsDetailsType>;

interface selfProps {
  ref: any;
  goodsDetailsInfo: goodsDetailType | undefined;
}

const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => {
  //规格项表单
  const [form] = Form.useForm<{ [x: string]: string }>();
  //可编辑表格表单
  const [skuValueForm] = Form.useForm<{ [x: string]: string }>();

  //表格数据
  const [tableData, setTableData] = useState<(skuTableType & { [key: string]: string })[]>([]);
  //销售价格正则校验
  const salePriceValidator = (_rules: any, value: number) => {
    if (!isEmptyBol(value)) {
      if (regPriceNumber(value.toString())) {
        if (value > 99999999 || value < 0) {
          return Promise.reject(new Error('价格最大为99999999且大于0'));
        }
        return Promise.resolve();
      } else {
        return Promise.reject(new Error('为整数且最多保留两位小数'));
      }
    } else {
      return Promise.reject(new Error('请输入销售价'));
    }
  };
  //渠道正则价格校验
  const channelPriceValidator = (_rules: any, value: number) => {
    if (!isEmptyBol(value)) {
      if (regPriceNumber(value.toString())) {
        if (value > 99999999 || value < 0) {
          return Promise.reject(new Error('价格最大为99999999且大于0'));
        }
        return Promise.resolve();
      } else {
        return Promise.reject(new Error('为整数且最多保留两位小数'));
      }
    } else {
      return Promise.resolve();
    }
  };
  //库存正则校验
  const stockPriceValidator = (_rules: any, value: number) => {
    if (!isEmptyBol(value)) {
      if (/^[+]{0,1}(\d+)$/.test(value.toString())) {
        if (value > 99999999 || value < 0) {
          return Promise.reject(new Error('库存最大为99999999且大于0'));
        }
        return Promise.resolve();
      } else {
        return Promise.reject(new Error('请输入正整数'));
      }
    } else {
      return Promise.resolve();
    }
  };
  //表格-列
  const [defaultColumns, setDefaultColumns] = useState<
    (ColumnTypes[number] & {
      editable?: boolean;
      dataIndex?: string;
      inputType?: string;
      radioOption?: { name: string; id: number }[];
      rules?: any;
      maxLength?: number;
      children?: any;
    })[]
  >([
    {
      title: '商品规格',
      align: 'center',
      children: [],
    },
    {
      title: '图片',
      align: 'center',
      editable: true,
      dataIndex: 'skuImage',
      inputType: 'uploader',
    },
    {
      title: 'sku编号',
      align: 'center',
      editable: true,
      dataIndex: 'skuNo',
      maxLength: 30,
    },
    {
      title: '销售价',
      align: 'center',
      editable: true,
      dataIndex: 'salePrice',
      rules: [{ required: true, validator: salePriceValidator }],
      inputType: 'number',
    },
    {
      title: '渠道价',
      editable: true,
      align: 'center',
      dataIndex: 'channelPrice',
      rules: [{ required: false, validator: channelPriceValidator }],
      inputType: 'number',
    },
    {
      title: '库存',
      editable: true,
      align: 'center',
      dataIndex: 'stock',
      rules: [{ required: false, validator: stockPriceValidator }],
      inputType: 'number',
    },
  ]);
  const covertColumns = () => {
    return defaultColumns.map((col) => {
      if (!col.editable) {
        return col;
      }
      return {
        ...col,
        onCell: (record: any) => ({
          record,
          dataIndex: col.dataIndex,
          title: col.title,
          editing: col.editable,
          radioOption: col.radioOption,
          inputType: col.inputType,
          uploadSuccess: col.inputType === 'uploader' ? uploadSuccess : undefined,
          rules: col.rules,
        }),
      };
    });
  };

  //规格表单数组
  const [specificationFormList, setSpecificationFormList] = useState<specificationFormListType[]>([
    {
      id: Math.random(),
      name: `specName`,
      optionList: [],
      specificationValueList: [],
      addSpecificationValueShow: false,
    },
  ]);

  useImperativeHandle(ref, () => ({
    submitSku,
    getForm: () => skuValueForm,
  }));

  //新增规格项目
  const addSpecificationClick = () => {
    setSpecificationFormList([
      ...specificationFormList,
      {
        id: Math.random(),
        name: `specName${specificationFormList.length + 1}`,
        optionList: [],
        specificationValueList: [],
        addSpecificationValueShow: false,
      },
    ]);
  };
  // 删除规格项目
  const deleteSpecificationClick = (index: number) => {
    specificationFormList.splice(index, 1);
    combineSpecificationValue();
    setSpecificationFormList([...specificationFormList]);
  };
  //规格项名称输入完成
  const specificationPressEnter = (e: any, index: number) => {
    specificationFormList[index].optionList = e.target.value
      ? [{ label: e.target.value, value: e.target.value }]
      : [];
    const obj = Object.create(null);
    obj[specificationFormList[index].name] = e.target.value || undefined;
    form.setFieldsValue(obj);
    setSpecificationFormList([...specificationFormList]);
  };
  //规格值添加
  const addSpecificationValueClick = (index: number) => {
    specificationFormList[index].addSpecificationValueShow = true;
    setSpecificationFormList([...specificationFormList]);
  };
  //存在
  const specificationValuePressEnter = (e: any, index: number) => {
    const isExist = specificationFormList[index].specificationValueList.some(
      (v) => v.name === e.target.value,
    );
    if (isExist) {
      return message.warning('该规格值已存在');
    }
    specificationFormList[index].specificationValueList.push({
      id: Math.random(),
      name: e.target.value,
      specificationName: specificationFormList[index].optionList[0].value,
    });
    combineSpecificationValue();
    setSpecificationFormList(specificationFormList);
    specificationValueCancel(index);
  };
  //规格值添加-取消
  const specificationValueCancel = (index: number) => {
    specificationFormList[index].addSpecificationValueShow = false;
    setSpecificationFormList([...specificationFormList]);
  };
  //规格值-删除
  const specificationValueDelete = (i: number, j: number) => {
    specificationFormList[i].specificationValueList.splice(j, 1);
    combineSpecificationValue();
    setSpecificationFormList([...specificationFormList]);
  };

  //组合数据
  const combineSpecificationValue = () => {
    let combineSpecificationList: any = [];
    let tableDataList: any = [];
    if (specificationFormList.length > 1) {
      const combineList = specificationFormList.reduce((pre: any, cur, currentIndex) => {
        //  首次组合两个数据
        if (currentIndex === 0 && specificationFormList.length > 1) {
          combineSpecificationList = combineEvent(
            cur.specificationValueList,
            specificationFormList[currentIndex + 1].specificationValueList,
          );
          //二维数组拆分为对象
          combineSpecificationList = getCombineObj(combineSpecificationList);
          //  两个数据以上的组合
        } else if (
          currentIndex < specificationFormList.length - 1 &&
          specificationFormList[currentIndex + 1].specificationValueList.length
        ) {
          //  上一次的组合作为下一次组合的参数
          combineSpecificationList = combineEvent(
            combineSpecificationList,
            specificationFormList[currentIndex + 1].specificationValueList,
          );
          //二维数组拆分为对象
          combineSpecificationList = getCombineObj(combineSpecificationList);
        }
        pre = combineSpecificationList;
        return pre;
      }, []);
      tableDataList = combineList.reduce((pre: any, cur: any) => {
        const tabCovertObj = cur.reduce((a: any, b: any, currentIndex: number) => {
          a['name' + (currentIndex + 1)] = b.name;
          a['specificationName' + (currentIndex + 1)] = b.specificationName;
          return a;
        }, {});
        //判断表格中是否已存在该条（缓存）
        const tableItemObj = tableData.find((i) =>
          Object.getOwnPropertyNames(tabCovertObj).every((key) => i[key] === tabCovertObj[key]),
        );
        pre.push({
          ...tabCovertObj,
          id: tableItemObj ? tableItemObj.id : Math.random(), //存在则用之前的id，不存在新建id
          fileList: tableItemObj ? tableItemObj.fileList : [],
        });
        return pre;
      }, []);
    } else {
      //当存在一个规格项时
      tableDataList = specificationFormList[0].specificationValueList.map((v) => {
        const obj = Object.create(null);
        obj['name1'] = v.name;
        obj['specificationName1'] = v.specificationName;
        //判断表格中是否已存在该条（缓存）
        const tableItemObj = tableData.find((i) =>
          Object.getOwnPropertyNames(obj).every((key) => i[key] === obj[key]),
        );
        obj['id'] = Math.random();
        return tableItemObj ? tableItemObj : obj; //存在则用之前的一条，不存在新建一条
      });
    }
    if (tableDataList.length) {
      //过滤规格值为空的
      const filterSpecificationFormList = specificationFormList.filter(
        (v) => v.specificationValueList.length,
      );
      setTableFormDefault(tableDataList);
      mergeTableRow(filterSpecificationFormList);
    }
    setTableData([...tableDataList]);
  };

  //组合数据拆分为对象
  const getCombineObj = (combineSpecificationList: any) => {
    return combineSpecificationList.reduce((pre: any, cur: any) => {
      pre.push(
        cur.reduce((a: any, b: any) => {
          if (Array.isArray(b)) {
            a.push(...b);
          } else {
            a.push({ ...b });
          }
          return a;
        }, []),
      );
      return pre;
    }, []);
  };

  //两数组排列组合（通用）
  const combineEvent = (list1: any, list2: any) => {
    return list1.reduce((pre: any, cur: any) => pre.concat(list2.map((v: any) => [cur, v])), []);
  };
  //表头拆分及合并列
  const mergeTableRow = (filterSpecificationFormList: specificationFormListType[]) => {
    const columns = filterSpecificationFormList.map((v, index) => ({
      title: v.optionList[0].value,
      dataIndex: 'name' + (index + 1),
      align: 'center',
      onCell: (_: any, i: number) => {
        //合并列
        if (index < filterSpecificationFormList.length - 1) {
          const count: number = filterSpecificationFormList
            .slice(index + 1, filterSpecificationFormList.length)
            .reduce((pre: number, cur) => {
              return pre * cur.specificationValueList.length;
            }, 1);
          return {
            rowSpan: count !== 1 ? ((i + 1) % count === 1 ? count : 0) : 1,
          };
        } else {
          return {
            rowSpan: 1,
          };
        }
      },
    }));
    defaultColumns[0].children = columns;
    setDefaultColumns([...defaultColumns]);
  };

  //规格值上传图片返回
  const uploadSuccess = (
    record: skuTableType,
    fileList: {
      id: number;
      name: string;
      uid: number;
      url: string;
    }[],
  ) => {
    const tableIndex: number = tableData.findIndex((v) => v.id === record.id);
    if (tableIndex !== -1) {
      tableData[tableIndex].fileList = fileList;
      const obj = Object.create(null);
      obj['skuImage' + record.id] = fileList.length ? fileList[0].url : undefined;
      skuValueForm.setFieldsValue(obj);
      setTableData([...tableData]);
    }
  };

  //提交验证
  const submitSku = () => {
    return new Promise((resolve, reject) => {
      form
        .validateFields()
        .then(() => {
          const specificationFormItemIndex = specificationFormList.findIndex(
            (v) => !v.specificationValueList.length,
          );
          if (specificationFormItemIndex !== -1) {
            return message.warning(`请为规格项${specificationFormItemIndex}添加规格值`);
          } else {
            //规格项数据转化
            const specAttrList = specificationFormList.map((v) => ({
              specName: v.optionList[0].value,
              id: goodsDetailsInfo
                ? goodsDetailsInfo.specAttrList.find((i) => i.id === v.id)?.id
                : undefined,
              specValuesList: v.specificationValueList.map((j) => ({
                specName: j.name,
                id: goodsDetailsInfo
                  ? goodsDetailsInfo.specAttrList
                      .find((i) => i.id === v.id)
                      ?.specValuesList.find((i) => i.id === j.id)?.id
                  : undefined,
              })),
            }));
            skuValueForm
              .validateFields()
              .then((value) => {
                //规格值数据转化
                const priceStock = tableData.reduce((pre: any, cur: any) => {
                  //规格名，规格值组合类型
                  const productSpec = specificationFormList.reduce(
                    (a: { [x: string]: string }, b, currentIndex) => {
                      a[b.optionList[0].value] = cur['name' + (currentIndex + 1)];
                      return a;
                    },
                    {},
                  );
                  pre.push({
                    ...Object.getOwnPropertyNames(value).reduce((a: any, b) => {
                      if (b.includes(cur.id)) {
                        a[b.replace(cur.id, '')] = value[b];
                      }
                      return a;
                    }, {}),
                    productSpec: JSON.stringify(productSpec),
                  });
                  return pre;
                }, []);
                resolve({ priceStock, specAttrList });
              })
              .catch((err) => {
                reject(err);
              });
          }
        })
        .catch((err) => {
          reject(err);
        });
    });
  };
  //排列组合规格值表单默认数据
  const setTableFormDefault = (tableDataList: (skuTableType & { [key: string]: string })[]) => {
    const tableFormDefault = tableDataList.reduce((pre: any, cur) => {
      return {
        ...pre,
        ...Object.getOwnPropertyNames(filterObjAttr(cur, ['id'])).reduce((a: any, b) => {
          a[b + cur.id] = cur[b];
          return a;
        }, {}),
      };
    }, {});
    skuValueForm.setFieldsValue(tableFormDefault);
  };

  useEffect(() => {
    if (goodsDetailsInfo) {
      //转化数据
      const covertSpecAttrList = goodsDetailsInfo.specAttrList.map((v, index) => ({
        id: v.id,
        name: 'specName' + index,
        optionList: [{ label: v.specName, value: v.specName }],
        specificationValueList: v.specValuesList.map((i) => ({
          id: i.id,
          name: i.specName,
          specificationName: v.specName,
        })),
        addSpecificationValueShow: false,
      }));
      //规格项表单数据默认数据
      const specFormDefault = goodsDetailsInfo.specAttrList.reduce(
        (pre: any, cur: any, currentIndex) => {
          pre['specName' + currentIndex] = cur.specName;
          return pre;
        },
        {},
      );
      form.setFieldsValue(specFormDefault);
      setSpecificationFormList([...covertSpecAttrList]);
      mergeTableRow(covertSpecAttrList);
      const tableDataList: (skuTableType & { [key: string]: string })[] =
        goodsDetailsInfo.priceStock.map((v) => ({
          id: v.id,
          salePrice: v.salePrice,
          skuImage: v.skuImage,
          skuNo: v.skuNo,
          stock: v.stock,
          channelPrice: v.channelPrice,
          fileList: v.skuImage
            ? [{ id: Math.random(), uid: Math.random(), url: v.skuImage, name: '规格图片' }]
            : [],
          ...Object.getOwnPropertyNames(JSON.parse(v.productSpec)).reduce(
            (pre: any, cur, currentIndex) => {
              pre['name' + (currentIndex + 1)] = JSON.parse(v.productSpec)[cur];
              pre['specificationName' + (currentIndex + 1)] = cur;
              return pre;
            },
            {},
          ),
        }));
      setTableFormDefault(tableDataList);
      setTableData(tableDataList);
    }
  }, [goodsDetailsInfo]);

  return (
    <div className='sku-info'>
      <Form wrapperCol={{ span: 5 }} labelCol={{ span: 1 }} form={form}>
        {specificationFormList.map((v, index) => (
          <>
            {/*  规格项*/}
            <Row key={v.id}>
              <Col span={7}>
                <Form.Item
                  label={'规格项' + (index + 1)}
                  wrapperCol={{ span: 18 }}
                  labelCol={{ span: 5 }}
                  name={v.name}
                  rules={[{ required: true, message: `请输入规格项${index + 1}` }]}
                >
                  <Select
                    placeholder='请输入规格项，按回车键完成'
                    dropdownRender={(menu) => (
                      <>
                        {v.optionList.length ? menu : ''}
                        <Input onPressEnter={(e) => specificationPressEnter(e, index)} />
                      </>
                    )}
                    options={v.optionList}
                  />
                </Form.Item>
              </Col>
              {index ? (
                <Col span={2}>
                  <Button
                    danger
                    icon={<DeleteOutlined />}
                    onClick={() => deleteSpecificationClick(index)}
                  >
                    删除
                  </Button>
                </Col>
              ) : (
                ''
              )}
            </Row>
            {/*规格值显示*/}
            {v.specificationValueList.length ? (
              <Row style={{ marginBottom: '10px' }}>
                <Col span={2}></Col>
                <Col span={4}>
                  <div>
                    {v.specificationValueList.map((v, i) => (
                      <Tag key={v.id} closable onClose={() => specificationValueDelete(index, i)}>
                        {v.name}
                      </Tag>
                    ))}
                  </div>
                </Col>
              </Row>
            ) : (
              ''
            )}

            {/*规格值操作*/}
            {v.optionList.length ? (
              <Row>
                <Col span={2}></Col>
                <Col span={4} style={{ marginBottom: '10px' }}>
                  {v.addSpecificationValueShow ? (
                    <Input
                      placeholder='请输入规格值，按回车键完成'
                      onPressEnter={(e) => specificationValuePressEnter(e, index)}
                    />
                  ) : (
                    <Button
                      type='link'
                      danger
                      icon={<PlusOutlined />}
                      onClick={() => addSpecificationValueClick(index)}
                    >
                      添加规格值
                    </Button>
                  )}
                </Col>
                {v.addSpecificationValueShow ? (
                  <Col>
                    <Button
                      type='primary'
                      style={{ marginLeft: '10px' }}
                      onClick={() => specificationValueCancel(index)}
                    >
                      取消
                    </Button>
                  </Col>
                ) : (
                  ''
                )}
              </Row>
            ) : (
              ''
            )}
          </>
        ))}
        <Row>
          <Col span={2}></Col>
          <Col>
            <Button type='primary' icon={<PlusOutlined />} onClick={addSpecificationClick}>
              添加规格
            </Button>
          </Col>
        </Row>
      </Form>
      {tableData.length ? (
        <Form form={skuValueForm}>
          <Table
            style={{ marginTop: '10px' }}
            rowKey='id'
            columns={covertColumns() as ColumnTypes}
            components={{
              body: {
                cell: EditableCell,
              },
            }}
            bordered
            dataSource={tableData}
            pagination={false}
            size='small'
          />
        </Form>
      ) : (
        ''
      )}
    </div>
  );
});
export default SkuInfo;
