import React, { Fragment, useCallback, useState } from 'react';
import { Button, Space } from '@easyv/antd';
import { Link, useLocation } from 'react-router-dom';
import { getTopScreenId } from 'utils/screen';
import { generateId } from 'utils/utils';
import {
  EasyNumber,
  EasyBoolean,
  EasySelect,
  FormItem,
  FormGroup,
  CollapseTabs,
  Icon,
  Input,
} from '@easyv/react-gui';
import message from 'components/message';
import styles from '../index.less';
import { Course } from 'models/course.types';
import { setPanelLimit } from 'utils/panelLimit';
import { QuestionCircleOutlined } from '@easyv/react-icons';
import EasyvTooltip from 'components/EasyvTooltip';
import { addPasswordScreenForPanel } from '@/services/screen';
import { updatePanelInfoByPanelId } from 'models/panel';
import { useDispatch } from 'react-redux';

const { TabPane } = CollapseTabs;
const { Col } = FormGroup;

function Config({
  user,
  id,
  name,
  states,
  course,
  config = {},
  type,
  screenConfig = [],
  resetSelect,
  hideDefault,
  screens,
  onChange,
  onBeforeScreenLink,
}: {
  user: {
    userInfo: {
      panelLimit?: {
        dynamicPanelCountLimit?: number;
        dynamicPanelLevelLimit?: number;
        dynamicPanelStateLimit?: number;
        referencePanelCountLimit?: number;
        referencePanelStateLimit?: number;
      };
    };
  };
  id: number;
  name: string;
  states: any;
  config: any;
  type: number;
  hideDefault: boolean;
  screens: any;
  course: {
    [key: string]: any;
  };
  screenConfig: { screenId: number; screenPassword: string }[];
  onChange: (param) => any;
  resetSelect: () => void;
  onBeforeScreenLink: (value) => any;
}): React.ReactElement {
  const dispatch = useDispatch();
  const [pathname] = window.location.pathname.split('/panel_');
  const isTerminal = /\/app\/edit\/[0-9]+\/[0-9]+/.test(pathname);
  const [statesWithKey, setStates] = useState(states.map((d, i) => ({ key: `${d}_${i}`, id: d })));
  const topScreenId = getTopScreenId();
  const location = useLocation();

  const {
    left,
    top,
    width,
    height,
    lock,
    allowScroll,
    autoCarousel,
    animateType = 'opacity',
    interval = 5,
  } = config;

  const screenIds = screens.map((d) => d.screenId); //未被删除的大屏ID集合
  const statesWithIds = statesWithKey.map((d) => d.id); //当前图层被选中的引用面板关联的所有大屏
  const newScreens = Array.from(new Set(screenIds.concat(statesWithIds)));
  const [reload, setReload] = useState(false);

  const screenOptions = newScreens.map((id) => {
    const item = screens.find((d) => d.screenId == id) || {};
    const { screenName, screenId, password } = item;
    let name = `${screenName}_${screenId}`,
      value = screenId,
      disabled = screenId === topScreenId;
    if (!screenId) {
      name = `${id}（该屏已被删除）`;
      value = id;
      disabled = true;
    }
    return { name, value, disabled, needPassword: !!password };
  }, []);

  // statesWithKey
  // screenOptions = screenOptions.map

  // 记录上一次跳转过来的地址
  const handleLink = () => {
    const from = JSON.parse(sessionStorage.getItem('linkFrom') || '[]');
    from.push(location.pathname);
    sessionStorage.setItem('linkFrom', JSON.stringify(from));
  };

  const handleStatesChange = (states) => {
    onChange({ states: states.reduce((all, item) => (item.id ? all.concat(+item.id) : all), []) });
  };

  const handleStateChange = async (index, value) => {
    const hide = message.loading('正在关联屏...', 0);
    const canScreenBeLinked = await onBeforeScreenLink(value);
    hide();

    if (canScreenBeLinked) {
      const newStates = statesWithKey.map((d, i) => (i === index ? { ...d, id: value } : d));

      setStates(newStates);

      handleStatesChange(newStates);
    } else {
      message.error('关联失败，确认屏之间是否存在相互引用');
    }
  };

  // 生成前端的key，保证应用引用变了，key不变
  const handleAdd = () => {
    if (setPanelLimit('referencePanelStateLimit', user, statesWithKey)) {
      message.error('单个引用面板的状态数已经到达上限');
      return;
    }
    const randomKey = generateId();
    setStates(statesWithKey.concat({ key: randomKey }));
    return randomKey;
  };

  // 删除传给后端的需要删除前端生成的key，以及添加了未选中引用的key
  const handleDelete = (activeKey) => {
    const newStates = statesWithKey.filter((d) => d.key !== activeKey);
    setStates(newStates);

    handleStatesChange(newStates);
  };

  const handleSort = ({ oldIndex, newIndex }) => {
    const newStates = statesWithKey.concat();
    const oldState = newStates.splice(oldIndex, 1)[0];
    newStates.splice(newIndex, 0, oldState);
    setStates(newStates);

    handleStatesChange(newStates);
  };

  const panelUrl = isTerminal
    ? `${pathname.replace(BASENAME, '')}/panel_${id}/${states[0]}`
    : `/create/${topScreenId}/panel_${id}/${states[0]}`;

  const courseItem = course[type === 1 ? Course.REF : Course.PANEL];

  const PanelScreenPasswordInput = useCallback(
    ({ d }) => {
      const curPassword = screenConfig.find((o) => o.screenId === d.id)?.screenPassword;
      return d.id && screenOptions.find((o) => o.value === d.id)?.needPassword ? (
        <FormItem
          label={
            <Space size={4}>
              <span>应用密码</span>
              <EasyvTooltip placement="top" title="正确填入密码后，预览、发布访问应用时无需解密">
                <QuestionCircleOutlined className={styles.qs_icon} />
              </EasyvTooltip>
            </Space>
          }>
          <Input
            defaultValue={curPassword}
            placeholder="请输入应用密码"
            onBlur={async (e) => {
              if (e.target.value === curPassword || !e.target.value.trim()) {
                setReload(!reload);
                return;
              }
              await addPasswordScreenForPanel({
                screenId: d.id,
                panelId: id,
                screenPassword: e.target.value,
              })
                .then((res) => {
                  if (res) message.success('修改成功');
                  dispatch(updatePanelInfoByPanelId(id));
                })
                .catch((e) => {
                  message.error('修改失败');
                });
            }}
          />
        </FormItem>
      ) : null;
    },
    // WARING 尽管这段代码没有依赖statesWithKey，但是视图渲染层依赖了
    [screenConfig, id, screenOptions, statesWithKey, reload],
  );
  return (
    <div>
      <div className={styles.title}>{type === 1 ? '引用面板' : '动态面板'}配置</div>
      <div className={styles.nameBox}>
        <div className={styles.name} title={`${name}_${id}`}>
          {name}_{id}
        </div>
        {courseItem ? (
          <a target="_blank" href={courseItem.courseUrl} className={styles.course}>
            查看教程
          </a>
        ) : null}
      </div>

      <div className={styles.content}>
        <FormItem label="位置">
          <FormGroup>
            <Col span={11}>
              <EasyNumber
                min={Number.MIN_SAFE_INTEGER}
                value={left}
                onChange={(value) => onChange({ left: value })}
                suffix="X"
                showStep={false}
              />
            </Col>
            <Col span={2} />
            <Col span={11}>
              <EasyNumber
                min={Number.MIN_SAFE_INTEGER}
                value={top}
                onChange={(value) => onChange({ top: value })}
                suffix="Y"
                showStep={false}
              />
            </Col>
          </FormGroup>
        </FormItem>
        <FormItem label="尺寸">
          <FormGroup>
            <Col span={11}>
              <EasyNumber
                min={1}
                value={width}
                onChange={(value) => {
                  if (lock && width && height) {
                    const scale = width / height;
                    onChange({ width: value, height: Math.round(value / scale) });
                  } else {
                    onChange({ width: value });
                  }
                }}
                suffix="W"
                showStep={false}
              />
            </Col>
            <Col span={2}>
              <Icon
                type={lock ? 'lock_on' : 'lock_off'}
                style={{ fontSize: 20, marginLeft: -6, cursor: 'pointer' }}
                onClick={() => onChange({ lock: !lock })}
              />
            </Col>
            <Col span={11}>
              <EasyNumber
                min={1}
                value={height}
                onChange={(value) => {
                  if (lock && width && height) {
                    const scale = width / height;
                    onChange({ height: value, width: Math.round(value * scale) });
                  } else {
                    onChange({ height: value });
                  }
                }}
                suffix="H"
                showStep={false}
              />
            </Col>
          </FormGroup>
        </FormItem>
        <FormItem label="默认隐藏">
          <EasyBoolean value={hideDefault} onChange={(value) => onChange({ hideDefault: value })} />
        </FormItem>
        <FormItem label="启用滚动">
          <EasyBoolean value={allowScroll} onChange={(value) => onChange({ allowScroll: value })} />
        </FormItem>
        <FormItem label="自动轮播">
          <EasyBoolean
            value={autoCarousel}
            onChange={(value) => onChange({ autoCarousel: value, animateType, interval })}
          />
        </FormItem>

        {autoCarousel && (
          <Fragment>
            <FormItem label="动画类型">
              <EasySelect
                value={animateType}
                options={[
                  { name: '无', value: 'none' },
                  { name: '渐隐渐现', value: 'opacity' },
                ]}
                onChange={(value) => onChange({ animateType: value })}
              />
            </FormItem>
            <FormItem label="更新时间">
              <EasyNumber
                value={interval}
                onChange={(value) => onChange({ interval: value })}
                suffix="s"
                showStep={false}
              />
            </FormItem>
          </Fragment>
        )}

        {type === 1 ? (
          <div>
            <CollapseTabs
              header={<span style={{ flex: 1 }}>引用列表</span>}
              defaultCollapsed={false}
              onAdd={handleAdd}
              onDelete={handleDelete}
              onSort={handleSort}>
              {statesWithKey.map((d, i) => (
                <TabPane key={d.key} tab={`应用${i + 1}`}>
                  <FormItem label="应用选择">
                    <EasySelect
                      value={d.id || ''}
                      options={screenOptions}
                      onChange={(value) => {
                        if (screenOptions.find((o) => o.value === value)?.needPassword) {
                          message.warning('应用已加密，请输入密码');
                        }
                        handleStateChange(i, value);
                      }}
                    />
                  </FormItem>
                  <PanelScreenPasswordInput d={d} />
                  <div style={{ marginBottom: 20, padding: 12 }}>
                    提示：所选应用必须为已发布状态
                  </div>
                  {d.id && (
                    <div className={styles.btn} style={{ paddingLeft: 12, paddingRight: 12 }}>
                      <Button type="primary" style={{ width: '100%' }}>
                        <Link to={`/create/${d.id}`} onClick={handleLink}>
                          编辑引用应用
                        </Link>
                      </Button>
                    </div>
                  )}
                </TabPane>
              ))}
            </CollapseTabs>
          </div>
        ) : (
          <div className={styles.btn} style={{ margin: '0 12px' }}>
            <Button type="primary" style={{ width: '100%' }} onClick={resetSelect}>
              <Link to={panelUrl}>编辑动态面板</Link>
            </Button>
          </div>
        )}
      </div>
    </div>
  );
}

export default Config;
