/**
 * Copyright (c) 2025-2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { formHost } from '@kit.FormKit';
import { BuilderNode, NodeController, UIContext } from '@kit.ArkUI';
import { CheckEmptyUtils, Logger, LogDomain } from '@ohos/basicutils';
import {
  FormBasicParams,
  CardNodeControllerManager,
  FormOccupyParams,
  CardNodeOption,
} from '../manager/CardNodeControllerManager';
import { FormCommonUtil } from '../utils/FormCommonUtil';
import CardLockManager from '../manager/CardLockManager';
import { CommonConstants } from '../constants/CommonConstants';

const TAG: string = 'CardNodeController';
const log: Logger = Logger.getLogHelper(LogDomain.FORM);
const HEXADECIMAL_VALUE: number = 36;
const PREFIX: string = 'cNode';

// 普通卡片
@Builder
function cardBuilder(params: FormBasicParams) {
  FormComponent({
    id: FormCommonUtil.transformCardId(params.basicData.cardId),
    name: params.basicData.cardName,
    bundle: params.basicData.bundleName,
    ability: params.basicData.abilityName,
    module: params.basicData.moduleName,
    dimension: params.basicData.cardDimension,
    want: params.basicData.want,
  })
    .id(params.basicData.compId)
    .borderRadius(params.basicData.borderRadius)
    .width(params.basicData.width)
    .height(params.basicData.height)
    .hoverEffect(params.basicData.hoverEffect ?? HoverEffect.Auto)
    .allowUpdate(true)
    .onAcquired((form: FormCallbackInfo) => {
      log.showInfo(TAG, `acquried card FormCallbackInfo is = ${form}, cardId = ${params.basicData.cardId};`);
      if (CheckEmptyUtils.isEmpty(form)) {
        log.showError(TAG, 'form item onAcquired formCallbackInfo invalid!');
        return;
      }
      if (CardNodeControllerManager.getCardController(params.basicData.cardId)) {
        const controller = CardNodeControllerManager.getCardController(params.basicData.cardId) as CardNodeController;
        // 记录formInfo
        controller.formInfo = form;
        // 需要更新节点缓存
        CardNodeControllerManager.updateCardNode(params.basicData.cardId, form.idString);
        CardNodeControllerManager.updateCardController(params.basicData.cardId, form.idString);
        // 记录新ID、报错删卡需要删除缓存节点
        params.basicData.cardId = form.idString;
        log.showInfo(TAG, `acquried card id is = ${form.idString}`);
        // 更新cardId
        if (controller.formParams instanceof FormBasicParams) {
          controller.formParams.basicData.cardId = form.idString;
        }
        let prev = controller.prev as CardNodeController;
        while(prev) {
          if (prev.formParams instanceof FormBasicParams) {
            prev.formParams.basicData.cardId = form.idString;
            prev.formInfo = form;
          }
          prev = prev.prev as CardNodeController;
        }
        let next = controller.next as CardNodeController;
        while(next) {
          if (next.formParams instanceof FormBasicParams) {
            next.formParams.basicData.cardId = form.idString;
            next.formInfo = form;
          }
          next = next.next as CardNodeController;
        }
      }
      if (!form['isLocked']) { //sdk未更新、绕过TS校验
        CardLockManager.getInstance().addReleasedForm(params.basicData.bundleName, form.idString);
      }
      // 执行回调
      params.basicEvent.onAcquired?.(form);
    })
    .onRouter(() => {
      params.basicEvent.onRouter?.();
    })
    .onLoad(() => {
      params.basicEvent.onLoad?.();
    })
    .onError((error) => {
      // 报错 都要移除节点緩存
      CardNodeControllerManager.destroyFormNodeByCardId(params.basicData.cardId);
      params.basicEvent.onError?.(error);
    })
    .onUninstall((form: FormCallbackInfo) => {
      // 删卡 移除节点緩存
      CardNodeControllerManager.destroyFormNodeByCardId(params.basicData.cardId);
      params.basicEvent.onUninstall?.(form);
    })
    .onTouch((event: TouchEvent) => {
      params.basicEvent.onTouch?.(event);
    })
}

function createCard(uiContext: UIContext, controller: CardNodeController):
  BuilderNode<[FormBasicParams]> | null {
  const params: FormBasicParams = controller.formParams as FormBasicParams;
  const cardNode : BuilderNode<[FormBasicParams]> | null =
    new BuilderNode<[FormBasicParams]>(uiContext);
  cardNode.build(wrapBuilder(cardBuilder), params);
  return cardNode;
}

function getOrCreateCard(uiContext: UIContext, controller: CardNodeController):
  BuilderNode<[FormBasicParams]> | null {
  const params: FormBasicParams | FormOccupyParams = controller.formParams;
  const controllerId: string = controller.uuid;
  if (params instanceof FormBasicParams) {
    const getFn: Function = params instanceof FormBasicParams ?
      CardNodeControllerManager.getCardNode : CardNodeControllerManager.getCardNode;
    const setFn: Function = params instanceof FormBasicParams ?
      CardNodeControllerManager.setCardNode : CardNodeControllerManager.setCardNode;
    let ret: BuilderNode<[FormBasicParams]> | null | undefined =
      getFn(params.basicData.cardId);
    if (!ret) { // 创建节点
      ret = createCard(uiContext, controller);
      log.showInfo(TAG, `${controllerId} createNode; cardId = ${controller.getCardId()}; from = ${controller.from}; node = ${ret}`);
      setFn(params.basicData.cardId, ret);
    } else { // 更新节点
      log.showInfo(TAG, `${controllerId} reuseNode; cardId = ${controller.getCardId()}; from = ${controller.from}; node = ${ret}; controller.formInfo = ${controller.formInfo}`);
      if (params instanceof FormBasicParams && controller.formInfo) {
        // 触发生命周期(普通卡片才有)
        log.showInfo(TAG, `reuse node acquire lifecycle done`);
        params.basicEvent.onAcquired?.(controller.formInfo);
        params.basicEvent.onLoad?.();
      }
      ret.update(params);
      if (params instanceof FormBasicParams && !FormCommonUtil.isCardIdInvalid(params.basicData.cardId)) {
        // 更新want
        FormCommonUtil.requestFormWithParams(params.basicData.cardId, params.basicData.want.parameters as
          Record<string, Object>);
        if (params.basicData.updateLocation) {
          // 更新location
          const location: number = (params.basicData.want?.parameters?.[CommonConstants.FORM_LOCATION_KEY] as number);
          log.showInfo(TAG, `update location = ${location}`);
          // 更新location
          try {
            formHost.updateFormLocation(params.basicData.cardId, location);
          } catch (error) {
            log.showError(TAG, `updateFormLocation error, code: ${error?.code}, message: ${error?.message}`);
          }
        }
      }
    }
    return ret;
  } else {
    const getFn: Function = CardNodeControllerManager.getCardNode;
    const node: BuilderNode<[FormBasicParams]> | null = getFn(params.cardId);
    log.showInfo(TAG, `${controllerId} occupyNode; cardId = ${controller.getCardId()}; from = ${controller.from} ;node = ${node}`);
    return node;
  }
}

export class CardNodeController extends NodeController {
  private isShow: boolean = true;
  private isDestroyed: boolean = false;
  public formParams: FormBasicParams | FormOccupyParams = new FormOccupyParams('');
  public cardNodeOption: CardNodeOption = new CardNodeOption();
  public from: string = ''; // 来源
  public formInfo: FormCallbackInfo | null = null; // 卡片框架返回的结果
  public uuid: string = ''; // 身份标识
  // 链表
  public prev: CardNodeController | null = null; // 前一个节点
  public next: CardNodeController | null = null; // 后一个节点
  constructor(params: FormBasicParams | FormOccupyParams, from: string,
    cardNodeOption = new CardNodeOption()) {
    super();
    this.uuid = PREFIX + '_' + Math.random().toString(HEXADECIMAL_VALUE).substring(2);
    this.formParams = params;
    this.from = from;
    this.cardNodeOption = cardNodeOption;
  }

  getCardId(): string {
    let cardId = '';
    if (this.formParams instanceof FormBasicParams) {
      cardId = this.formParams.basicData.cardId;
    } else {
      cardId = this.formParams.cardId;
    }
    return cardId;
  }

  onWillBind(): void {
    // makeNode方法调用之前会调用
    this.log();
    const params = this.formParams;
    let setFn: Function = () => {};
    let cardId: string = this.getCardId();
    let current: CardNodeController | null = null;
    if (params instanceof FormBasicParams || params instanceof FormBasicParams) {
      setFn = params instanceof FormBasicParams ?
        CardNodeControllerManager.setCardController : CardNodeControllerManager.setCardController;
      // 普通卡片、卡片ID不能为空
      if (FormCommonUtil.isCardIdInvalid(params.basicData.cardId)) {
        params.basicData.cardId = FormCommonUtil.getCardUUID();
        cardId = params.basicData.cardId;
      }
    } else {
      // 参数为FormOccupyParams、表示抢占节点、堆叠展开场景
      const getFn = CardNodeControllerManager.getCardController;
      setFn = CardNodeControllerManager.setCardController;
      current = getFn(cardId) as CardNodeController; // 当前节点挂载的controller
    }
    const cur: string = current?.uuid ?? '';
    log.showInfo(TAG, `current = ${cur}; current.isDestroyed = ${current?.isDestroyed}`);
    if (current?.formInfo) { // 记录formInfo
      this.formInfo = current.formInfo;
    }
    const controllerId: string = this.uuid;
    if (current && !current.isDestroyed) { // 先销毁的、等待别人来挂载节点不需要记录
      if (!current.cardNodeOption.highestPriority || this.cardNodeOption.highestPriority) {
        // 当前节点的优先级非最高、or this的优先级最高、抢占节点
        current.toHide();
        log.showInfo(TAG, `set controller and take node; cardId = ${cardId}; controllerId = ${controllerId}`);
        setFn(cardId, this);
      } else { // 不抢占节点
        this.isShow = false;
      }
      while(current.next) { // 找到最后一个节点
        current = current.next as CardNodeController;
      }
      // 挂载链表
      this.prev = current;
      current.next = this;
    } else {
      log.showInfo(TAG, `set controller cardId = ${cardId}; controllerId = ${controllerId}`);
      setFn(cardId, this);
    }
  }

  onWillUnbind(): void {
    const cardId: string = this.getCardId();
    const cur: string = this.uuid;
    log.showInfo(TAG, `${cur} unBind: cardId = ${cardId}; from = ${this.from}; this.isShow = ${this.isShow}`);
    let setFn: Function = CardNodeControllerManager.setCardController;
    if (this.isShow) {
      // 归还节点
      this.isShow = false;
      this.rebuild();
      log.showInfo(TAG,`${cur} return Node done`);
      // 优先找next
      if (this.next) { // 找到最后一个节点归还
        let next = this.next;
        while(next.next) {
          next = next.next as CardNodeController;
        }
        setFn(cardId, next);
        next.toShow();
      } else if (this.prev) {
        setFn(cardId, this.prev);
        this.prev.toShow();
      }
    }
    const prev: string = this.prev?.uuid ?? '';
    const next: string = this.next?.uuid ?? '';
    log.showInfo(TAG, `${cur} prev = ${prev}; next = ${next}; destroyImmediately = ${this.cardNodeOption.destroyImmediately}`);
    if (!this.next && !this.prev) {
      // FormComponent节点没有任何controller承载、检测缓存中是否还有相同CardId的数据、若没有则销毁
      Promise.resolve().then(() => {
        if (CardNodeControllerManager.cardIdInCache(cardId) && !this.cardNodeOption.destroyImmediately) {
          log.showInfo(TAG,`isolate FormComponent Node; cardId = ${cardId}`);
          // 清除桌面撤销卡片按钮
          AppStorage.setOrCreate('undoDragFormVisible', false);
          // 清除节点引用外部变量、防止内存泄漏
          let params: (FormBasicParams | undefined | FormOccupyParams) = this.formParams;
          if (params instanceof FormOccupyParams) {
            params = params?.formParams;
          }
          if (params) {
            CardNodeControllerManager.getCardNode(cardId)?.update(params);
            if (AppStorage.get<boolean>('isInTestEndPhrase')) {
              CardNodeControllerManager.destroyNodeByCardId(cardId);
            }
          }
          this.isDestroyed = true;
        } else {
          if (this.formParams instanceof FormBasicParams ||
            (this.formParams instanceof FormOccupyParams && !this.formParams.isAiCard)) {
            // FC 或者FC的抢占节点 只删除FC节点
            CardNodeControllerManager.destroyFormNodeByCardId(cardId);
          } else {
            CardNodeControllerManager.destroyNodeByCardId(cardId);
          }
          setFn(cardId, null);
        }
      });
    }
    // 解除绑定
    if (this.next) {
      this.next.prev = this.prev;
    }
    if (this.prev) {
      this.prev.next = this.next;
    }
    this.prev = null;
    this.next = null;
  }

  makeNode(uiContext: UIContext): FrameNode | null {
    const cur: string = this.uuid;
    if (!this.isShow) {
      log.showInfo(TAG, `${cur} makeNode: cardId = ${this.getCardId()};isShow = ${this.isShow};from = ${this.from}; node = null`);
      return null;
    }
    const node: FrameNode | null | undefined = getOrCreateCard(uiContext, this)?.getFrameNode();
    log.showInfo(TAG, `${cur} makeNode: cardId = ${this.getCardId()};isShow = ${this.isShow};from = ${this.from};node = ${node}`);
    return node || null;
  }

  toHide(): void {
    this.isShow = false;
    this.rebuild();
  }

  toShow(): void {
    this.isShow = true;
    this.rebuild();
  }

  log() {
    const formKeys: string[] = CardNodeControllerManager.getFormKey();
    let detail = 'FORMS: ';
    for (let i = 0; i < formKeys.length; i++) {
      const key: string = formKeys[i];
      const controller = CardNodeControllerManager.getCardController(key) as CardNodeController;
      detail += `#${key}/${controller?.from};`;
    }
    log.showInfo(TAG, 'will bind: current = #%{public}s/%{public}s; size = %{public}d; %{public}s', this.getCardId(), this.from, CardNodeControllerManager.getNodeCacheSize(), detail);
  }
}