import { AppModelService, GetModelService, Util } from '@ibizstudio-ex/runtime';
import { IPSDEFormDetailPreview, acc } from '@ibizstudio/api';
import { generateOrderValue } from 'qx-util';
import { LayoutUtil } from '../../utils';
import { DesignItemBase } from '../design-item/design-item-base';
import { message, Modal } from 'ant-design-vue';
import './drag-design-item-base.less';
import { IMaterialItem } from '../../interface';

/**
 * 表单设计项基类
 *
 * @export
 * @class DragDesignItemBase
 * @extends {DesignItemBase<T>}
 * @template T
 */
export class DragDesignItemBase extends DesignItemBase {
  /**
   * 布局工具
   *
   * @memberof DragDesignItemBase
   */
  layoutUtil = LayoutUtil.getInstance();

  /**
   * 样式
   *
   * @type {*}
   * @memberof DragDesignItemBase
   */
  style: any;

  /**
   * 是否为flex布局
   *
   * @memberof DragDesignItemBase
   */
  isFlexStyle = false;

  /**
   * 应用消息订阅
   *
   * @type {string[]}
   * @memberof DragDesignItemBase
   */
  accSubs: string[] = [];

  /**
   * 视图部件服务
   */
  viewCtrlService: any = '';

  /**
   * 视图部件数据
   */
  viewCtrlData: any = [];

  /**
   * 部件控件删除模式
   */
  ctrlPosDeleteMode: string = '';

  /**
   * 模型服务
   *
   * @author zhanghengfeng
   * @date 2023-03-14 19:03:29
   * @type {AppModelService}
   */
  modelService!: AppModelService;

  /**
   * 容器类型
   *
   * @author zhanghengfeng
   * @date 2023-05-18 14:05:54
   */
  static containerType = ['FORMPAGE', 'TABPAGE', 'GROUPPANEL'];

  /**
   * 子项类型
   *
   * @author zhanghengfeng
   * @date 2023-05-18 15:05:05
   * @static
   */
  static childType = ['FORMITEM', 'RAWITEM', 'BUTTON', 'IFRAME', 'FORMITEMEX', 'DRUIPART', 'MDCTRL'];

  /**
   * 监听素材项双击
   *
   * @author zhanghengfeng
   * @date 2023-05-18 14:05:13
   * @param {IMaterialItem} [item]
   */
  onItemDblClick(item?: IMaterialItem): void {
    if (this.active && item && item.data && this.data && Array.isArray(this.list)) {
      const type = this.data.detailtype;
      if (type) {
        if (DragDesignItemBase.containerType.includes(type)) {
          this.list.push(item.data);
          this.add({
            element: item.data,
            newIndex: this.list.length - 1,
          });
        } else if (DragDesignItemBase.childType.includes(type)) {
          this.ctx.ctrl.itemEvt?.emit('child-item-dblclick', {
            item,
            child: this.data,
          });
        }
      }
    }
  }

  /**
   * 监听子项触发的素材项双击
   *
   * @author zhanghengfeng
   * @date 2023-05-18 14:05:36
   * @param {{ item: IMaterialItem; child: IPSDEFormDetailPreview }} [args]
   */
  onChildItemDblClick(args?: { item: IMaterialItem; child: IPSDEFormDetailPreview }): void {
    if (args) {
      const { item, child } = args;
      if (item && item.data && child && this.data && Array.isArray(this.list)) {
        const id = this.data.psdeformdetailid;
        const parentId = child.ppsdeformdetailid;
        const childId = child.psdeformdetailid;
        if (id && parentId && childId && id === parentId) {
          const index = this.list.findIndex(data => {
            const dataId = data.psdeformdetailid;
            return dataId && dataId === childId;
          });
          if (index !== -1) {
            this.list.splice(index + 1, 0, item.data);
            this.add({
              element: item.data,
              newIndex: index + 1,
            });
          }
        }
      }
    }
  }

  async componentCreated() {
    if (this.data && this.data.itemtype && Object.is(this.data.itemtype, 'CTRLPOS')) {
      this.viewCtrlService = await ___ibz___.gs.getPSDEViewCtrlService();
      this.loadViewCtrl();
    }
    this.subAcc();
    this.deletePanel = this.deletePanel.bind(this);
    const event: any = (this.ctrl as any).evt;

    if (event) {
      event.on('removePanel', this.deletePanel);
    }
    this.modelService = await GetModelService(this.ctx.context);
    if (this.ctx.ctrl.itemEvt) {
      this.onItemDblClick = this.onItemDblClick.bind(this);
      this.ctx.ctrl.itemEvt.on('item-dblclick', this.onItemDblClick);
      const type = this.data?.detailtype;
      if (type && DragDesignItemBase.containerType.includes(type)) {
        this.onChildItemDblClick = this.onChildItemDblClick.bind(this);
        this.ctx.ctrl.itemEvt.on('child-item-dblclick', this.onChildItemDblClick);
      }
    }
  }

  async componentMounted() {
    this.service = this.ctx.ctrl.itemService;
    if (this.ctx.ctrl.previewService) {
      this.previewService = this.ctx.ctrl.previewService;
    } else {
      this.previewService = this.ctx.ctrl.itemService;
    }
    this.load();
  }

  componentDestroyed() {
    this.accSubs.forEach(str => acc.unsubscribeLocal(str));
    const event: any = (this.ctrl as any).evt;
    if (event) {
      event.off('removePanel', this.deletePanel);
    }
    if (this.ctx.ctrl.itemEvt) {
      this.ctx.ctrl.itemEvt.off('item-dblclick', this.onItemDblClick);
      this.ctx.ctrl.itemEvt.off('child-item-dblclick', this.onChildItemDblClick);
    }
  }

  /**
   * 订阅应用中心消息
   *
   * @memberof DragDesignItemBase
   */
  subAcc(): void {
    const entityName = this.ctx.ctrl.itemEntity?.codeName?.toUpperCase();
    this.accSubs.push(
      acc.commandLocal(
        (data: any) => {
          if (!this.isAcc) {
            return;
          }
          this.accCreated(data);
        },
        'create',
        entityName,
      ),
    );
    this.accSubs.push(
      acc.commandLocal(
        (data: any) => {
          if (!this.isAcc) {
            return;
          }
          this.accRemove(data);
        },
        'remove',
        entityName,
      ),
    );
    this.accSubs.push(
      acc.commandLocal(
        (data: any) => {
          if (!this.isAcc) {
            return;
          }
          this.accUpdate(data);
        },
        'update',
        entityName,
      ),
    );

    if (this.viewCtrlService) {
      this.accSubs.push(
        ...acc.commandLocals(
          (data: any) => {
            if (Object.is(this.context.psdeviewbase, data.psdeviewbaseid)) {
              this.loadViewCtrl();
            }
          },
          ['create', 'remove'],
          this.viewCtrlService.APPDENAME.toUpperCase(),
        ),
      );
    }
  }

  accCreated(data: any): void {
    if (this.data?.srfkey === data.srfpkey || !data.srfpkey) {
      this.load();
    }
  }

  accRemove(data: any): void {
    if (this.data?.srfkey === data.srfpkey || !data.srfpkey) {
      this.load();
    }
  }

  accUpdate(data: any): void {
    if (this.data?.srfkey === data.srfkey && this.data.srftempdate !== data.srftempdate) {
      this.reloadData();
    } else if (this.data?.srfkey === data.srfpkey) {
      this.load();
    }
  }

  /**
   * 加载数据
   *
   * @author chitanda
   * @date 2021-04-15 10:04:34
   * @return {*}  {Promise<any>}
   */
  async load(): Promise<any> {}

  /**
   * 加载视图部件数据
   *
   * @memberof CollapseList
   */
  async loadViewCtrl() {
    const res = await this.viewCtrlService.FetchDefault(this.ctx.context);
    if (res && res.data.length > 0) {
      this.viewCtrlData = res.data;
    }
  }

  /**
   * 删除项
   *
   * @param {string} srfKey
   * @return {*}  {Promise<any>}
   * @memberof DragDesignItemBase
   */
  async remove(srfKey: string): Promise<any> {
    const tab = this.list.find((item: any) => {
      return item.srfkey === srfKey;
    });
    const res = await this.service.RemoveTemp(this.ctx.context, tab);
    if (res.ok === false) {
      message.error(res.statusText || '');
      return res;
    }
    return res;
  }

  /**
   * 新增表单项
   *
   * @param {any} entity
   * @return {*}  {(Promise<any>)}
   * @memberof DragDesignItemBase
   */
  async create(entity: any): Promise<any> {
    const res: any = await this.service.CreateTemp(this.ctx.context, entity);
    if (res.ok) {
      this.setSelect(res.data);
      return res.data;
    }
  }

  /**
   * 更新表单项
   *
   * @param {any} entity
   * @return {*}  {(Promise<any>)}
   * @memberof DragDesignItemBase
   */
  update(entity: any): Promise<any> {
    return this.service.UpdateTemp(this.ctx.context, entity);
  }

  /**
   * 获取表单项
   *
   * @param {string} srfkey
   * @return {*}  {(Promise<any>)}
   * @memberof DragDesignItemBase
   */
  get(srfkey: string): Promise<any> {
    return this.previewService.getLocal(this.ctx.context, srfkey);
  }

  /**
   * @description 获取内容样式
   * @param {*} data
   * @return {*}
   * @memberof DragDesignItemBase
   */
  getContentStyle(data: any) {
    if (data && data.rawcssstyle) {
      const res = data.rawcssstyle.split('\n');
      const target: string[] = [];
      for (let i = 0; i < res.length; i++) {
        target.push(...res[i].split(';').filter((value: string) => value));
      }
      return target
        .filter((value: string) => {
          return value.split(':').length === 2;
        })
        .join(';');
    }
  }

  /**
   * 获取默认值
   *
   * @param {any} data
   * @return {*}  {(Promise<any>)}
   * @memberof DragDesignItemBase
   */
  async getDraft(data: any): Promise<any> {
    const res = await this.service.GetDraftTemp({ ...this.ctx.context, [this.ctx.ctrl.itemEntity?.codeName?.toLowerCase()]: this.data?.srfkey }, data);
    if (res.ok && res.data) {
      return res.data;
    }
    return {};
  }

  /**
   * 重新加载当前数据
   *
   * @memberof DragDesignItemBase
   */
  async reloadData() {
    const data = await this.get(this.data.srfkey);
    if (data) {
      this.data._reset(data);
      this.$forceUpdate();
    }
  }

  /**
   * 新增子项
   *
   * @param {{ element: any; newIndex: number }} opt
   * @memberof DragDesignItemBase
   */
  async add(opt: { element: any; newIndex: number }) {
    const { element, newIndex } = opt;
    await this.updateOrderValue(newIndex + 1);
    this.list.splice(newIndex, 1);
    let data: any = await this.get(element.srfkey);
    if (data == null) {
      data = await this.getDraft(element);
      data.ordervalue = generateOrderValue(newIndex);
      data.srfordervalue = data.ordervalue;
      data.formtype = this.ctx.context.formtype;
      await this.create(data);
    } else {
      data.ordervalue = generateOrderValue(newIndex);
      data.srfordervalue = data.ordervalue;
      if (!this.data || this.data.itemtype == 'PSSysViewPanel') {
        data.srfpkey = null;
        data.srfpmajortext = null;
      } else {
        data.srfpkey = this.data.srfkey;
        data.srfpmajortext = this.data.srfmajortext;
      }
      await this.update(data);
      if (!this.data || this.data.itemtype == 'PSSysViewPanel') {
        const panelCtrl: any = (this.ctrl.ctx as any)?.panelCtrl || this.ctrl;
        if (panelCtrl.evt) {
          panelCtrl.evt.emit('refreshPanel');
        }
      }
    }
  }

  /**
   * 激活数据点击
   *
   * @param {MouseEvent} event
   * @param {any} data
   * @memberof DragDesignItemBase
   */
  onActiveClick(event: MouseEvent, data: any): void {
    if (event) {
      event.stopPropagation();
    }
    this.setSelect(data);
  }

  /**
   * 计算当前布局是否为Flex
   *
   * @param {*} node
   * @memberof DragDesignItemBase
   */
  calcLayoutMode(): void {
    if (this.parentData && Object.is(this.parentData.layoutmode, 'FLEX')) {
      this.isFlexStyle = true;
    } else {
      this.isFlexStyle = false;
    }
  }

  /**
   * 计算当前项样式
   *
   * @memberof DragDesignItemBase
   */
  calcStyle() {
    this.calcLayoutMode();
    this.style = this.layoutUtil.formatStyle(this.data, this.parentData, this.isFlexStyle);
  }

  /**
   * 计算栅格布局样式
   *
   * @param {*} item
   * @returns {*}
   * @memberof DragDesignItemBase
   */
  calcColClass(item: any): any {
    return this.layoutUtil.calcColClass(item, this.parentData, this.isFlexStyle);
  }

  /**
   * 绘制其他内容
   *
   * @returns {*}
   * @memberof DragDesignItemBase
   */
  renderOther(): any {
    return [this.renderHandle(), this.renderActions()];
  }

  /**
   * 绘制拖拽节点
   *
   * @returns {*}
   * @memberof DragDesignItemBase
   */
  renderHandle(): any {
    // 视图设计中表单预览不允许移动编辑
    if (!(this.ctx.ctrl as any).isViewDesign) {
      return (
        <div class='drag-handle'>
          <a-icon type='drag' />
        </div>
      );
    }
  }

  /**
   * 绘制行为
   *
   * @returns {*}
   * @memberof DragDesignItemBase
   */
  renderActions(): any {
    return (
      <div class='drag-item-actions'>
        <ul>{this.renderActionItems()}</ul>
      </div>
    );
  }

  /**
   * 删除当前数据
   *
   * @param {MouseEvent} e
   * @return {*}  {Promise<void>}
   * @memberof DragDesignItemBase
   */
  async deleteHandle(e: MouseEvent): Promise<void> {
    e.stopPropagation();
    if (Object.is(this.data.itemtype, 'CTRLPOS')) {
      this.deletePromptMessage(e);
      return;
    }
    this.removeDesingItem(e);
  }

  /**
   * 删除占位控件
   * @param {MouseEvent} e
   *
   */
  async removeDesingItem(e: MouseEvent) {
    if ((this.ctrl as any)?.isDefaultLayout) {
      this.userOperationTips(e);
    } else {
      const res = await this.service.RemoveTemp(this.ctx.context, this.data);
      if (res.ok === false) {
        message.error(res.statusText || '');
        return;
      }
      this.setSelect(this.parentData);
    }
  }

  /**
   * @description 删除当前面板
   * @param {*} data
   * @memberof DragDesignItemBase
   */
  async deletePanel(data: any) {
    if (this.data.srfpkey && Object.is(this.data.srfpkey, data.srfkey)) {
      const res = await this.service.RemoveTemp(this.ctx.context, this.data);
      if (res.ok === false) {
        message.error(res.statusText || '');
        return;
      }
    }
  }

  /**
   * 拷贝当前表单项数据
   *
   * @param {MouseEvent} e
   * @return {*}  {Promise<void>}
   * @memberof DragDesignItemBase
   */
  async copyHandle(e: MouseEvent): Promise<void> {
    e.stopPropagation();
    const res = await (this.service as any).DeepCopy(this.ctx.context, this.data);
    if (res.ok) {
      console.log(res);
    }
  }

  /**
   * @description 保存为自定义部件
   * @param {MouseEvent} e
   * @return {*}  {Promise<void>}
   * @memberof DragDesignItemBase
   */
  async saveHandle(e: MouseEvent): Promise<void> {
    e.stopPropagation();
    //todo 待补充
  }

  /**
   * @description 编辑部件
   * @param {MouseEvent} e
   * @return {*}  {Promise<void>}
   * @memberof DragDesignItemBase
   */
  async editorHandle(event: MouseEvent): Promise<void> {
    event.stopPropagation();
    if (!Object.is(this.data.itemtype, 'CTRLPOS')) {
      return;
    }

    const evt: any = (this.ctrl as any).evt;
    const curCtrl = this.getActiveCtrl();
    if (curCtrl && evt) {
      Object.assign(curCtrl, { linktype: curCtrl.psdeviewctrltype });
      evt.emit('itemClick', { tag: 'redirectctrldesign', param: curCtrl });
    } else {
      const ctrlCtrl = (this.ctrl.ctx.ctrl as any)?.ctrlCtrl;
      if (ctrlCtrl && evt && ctrlCtrl.deUIActionItems.length > 0) {
        evt.emit('addCtrl', {
          event,
          item: ctrlCtrl.deUIActionItems[0],
          callback: (_data: any) => {
            if (_data.codename) {
              const result = {
                caption: _data.psctrlname,
                psdeviewctrltype: _data.psctrltypename,
                pssysviewpanelitemname: _data.codename,
                [`psde${_data.psctrltypename?.toLowerCase()}id`]: _data.psctrlid,
                srfkey: this.data.srfkey,
              };
              const data = Object.assign(Util.deepCopy(this.data), result);
              this.update(data);
            }
          },
        });
      }
    }
  }

  /**
   * @description 获取激活部件
   * @return {*}
   * @memberof DragDesignItemBase
   */
  public getActiveCtrl() {
    const data: any = this.ctrl.ctx.ctrl.select.data;
    if (data) {
      return Object.is(data.psdeviewctrlname, this.data.pssysviewpanelitemname) ? data : null;
    }
  }

  /**
   * 绘制删除占位提示信息
   * @param {MouseEvent} e
   */
  deletePromptMessage(e: MouseEvent) {
    this.ctrlPosDeleteMode = '';
    const modal: any = Modal.confirm({
      class: 'delete-prompt-message-main',
      mask: true,
      centered: true,
      icon: 'info-circle',
      width: 400,
      cancelText: '取消',
      okText: '确定',
      title: '请确认是否删除控件占位元素',
      okButtonProps: {
        props: {
          disabled: !this.ctrlPosDeleteMode,
        },
      },
      content: () => {
        return (
          <div>
            <a-radio-group v-model={this.ctrlPosDeleteMode}>
              <a-radio value='synchroDeleteViewCtrl' onClick={() => deletePlaceholderPro('synchroDeleteViewCtrl')}>
                是，同步删除已加入视图部件
              </a-radio>
              <a-radio value='onlyDeletePlaceholder' onClick={() => deletePlaceholderPro('onlyDeletePlaceholder')}>
                是，仅删除控件占位元素
              </a-radio>
            </a-radio-group>
          </div>
        );
      },
      onOk: async () => {
        if (Object.is(this.ctrlPosDeleteMode, 'synchroDeleteViewCtrl')) {
          // 筛选删除部件数据
          await this.viewCtrlData.find((item: any) => {
            return Object.is(item.psdeviewctrlname.toUpperCase(), this.data.pssysviewpanelitemname.toUpperCase());
          });
          const res = await this.viewCtrlService.RemoveTemp(this.ctx.context, this.data);
          if (res.ok === false) {
            message.error(res.statusText || '');
            return;
          }
        }
        await this.removeDesingItem(e);
      },
      onCancel: () => {},
    });

    const deletePlaceholderPro = (model: any) => {
      this.ctrlPosDeleteMode = model;
      modal.update({
        okButtonProps: {
          props: {
            disabled: !this.ctrlPosDeleteMode,
          },
        },
      });
    };
  }

  /**
   * 打开动态逻辑设计界面
   *
   * @author zhanghengfeng
   * @date 2023-03-14 18:03:19
   */
  async openFormItemLogicView() {
    const entity = this.ctx.ctrl.itemEntity;
    if (entity && this.data) {
      const codeName = entity.codeName?.toLowerCase();
      const key = entity.getKeyPSAppDEField()?.codeName?.toLowerCase();
      const majorKey = entity.getMajorPSAppDEField()?.codeName?.toLowerCase();
      if (codeName && key && majorKey) {
        const tempContext = Util.deepCopy(this.ctx.context);
        tempContext.viewpath = 'PSSYSAPPS/FormDesign/PSAPPDEVIEWS/PSDEFormDetailFDLogicEditView.json';
        tempContext.srfparentdemapname = entity.getPSDEName();
        tempContext[codeName] = this.data[key];
        const viewparams = {
          [key]: this.data[key],
          [majorKey]: this.data[majorKey],
        };
        const parentObj = {
          srfparentdename: codeName,
          srfparentkey: tempContext[codeName],
        };
        Object.assign(tempContext, parentObj);
        Object.assign(viewparams, parentObj);
        const type = this.data.detailtype;
        if (type === 'FORMITEM' || type === 'FORMITEMEX') {
          tempContext.viewpath = 'PSSYSAPPS/FormDesign/PSAPPDEVIEWS/PSDEFormDetailFDLogic2EditView.json';
        }
        const appView = await this.modelService.getPSAppView(tempContext.viewpath);
        const view = {
          viewname: 'app-view-shell',
          height: appView.height,
          width: appView.width,
          title: this.$tl(appView.getCapPSLanguageRes()?.lanResTag, appView.caption),
          placement: appView.openMode,
        };
        const container = this.$appdrawer.openDrawer(view, Util.getViewProps(tempContext, viewparams, [this.data]));
        container.subscribe((result: Record<string, unknown> | null) => {
          if (!result || !Object.is(result.ret, 'OK')) {
            return;
          }
        });
      }
    }
  }

  /**
   * 绘制行为项
   *
   * @param {*} h
   * @returns {*}
   * @memberof DragDesignItemBase
   */
  renderActionItems(): any {
    return [
      Object.is(this.data.itemtype, 'CTRLPOS') ? (
        <li v-show={this.active}>
          <el-tooltip effect='dark' enterable={false} content='编辑' placement='top' open-delay={300}>
            <a-icon type='form' on-click={(e: any) => this.editorHandle(e)} />
          </el-tooltip>
        </li>
      ) : null,
      // <li>
      //     <el-tooltip effect='dark' enterable={false} content='保存为自定义部件' placement='top' open-delay={300}>
      //         <a-icon type='save' on-click={(e: any) => this.saveHandle(e)} />
      //     </el-tooltip>
      // </li>,
      // <li>
      //     <el-tooltip effect='dark' enterable={false} content='拷贝' placement='top' open-delay={300}>
      //         <a-icon type='copy' on-click={(e: any) => this.copyHandle(e)} />
      //     </el-tooltip>
      // </li>,
      <li class={['form-item-logic-btn', this.data?.fdlogiccount ? '' : 'hidden']} on-click={() => this.openFormItemLogicView()}>
        <el-tooltip effect='dark' enterable={false} content='表单项逻辑' placement='top' open-delay={300}>
          <ion-icon icon={'./assets/svg/lightning.svg'} />
        </el-tooltip>
      </li>,
      <li v-show={this.active}>
        <el-tooltip effect='dark' enterable={false} content='删除' placement='top' open-delay={300}>
          <a-icon type='delete' on-click={(e: any) => this.deleteHandle(e)} />
        </el-tooltip>
      </li>,
    ];
  }

  /**
   * 根据项类型绘制
   *
   * @param {any} item
   * @return {*}
   * @memberof DragDesignItemBase
   */
  renderChildItem(item: any) {
    return this.ctx.ctrl.renderChildItem(this.$createElement, this.ctx, item, this.data);
  }

  /**
   * 绘制子数据
   *
   * @return {*}  {any[]}
   * @memberof DragDesignItemBase
   */
  renderChild(): any[] {
    return this.list.map(item => this.renderChildItem(item));
  }

  /**
   * 绘制内容
   *
   * @return {*}  {*}
   * @memberof DragDesignItemBase
   */
  renderContent(): any {}

  render() {
    const { srfkey } = this.data;
    this.calcStyle();
    return (
      <div
        id={srfkey}
        key={srfkey}
        style={this.style}
        class={{
          'layout-item-container': true,
          ...this.calcColClass(this.data),
        }}
        on-click={(e: any) => this.onActiveClick(e, this.data)}
        on-dblclick={(e: any) => this.editorHandle(e)}
      >
        {this.renderContent()}
        {this.renderOther()}
      </div>
    );
  }
}
