/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
 * 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.
 */

/* instrument ignore file */
import { LengthMetrics, LoadingDialog } from '@kit.ArkUI';
import promptAction from '@ohos.promptAction';
import { CustomContentDialog } from '@ohos.arkui.advanced.Dialog';
import { EventBus } from '@ohos/settings.common/src/main/ets/framework/common/EventBus';
import { LogUtil } from '@ohos/settings.common/src/main/ets/utils/LogUtil';
import { AppEntry } from '@ohos/settings.application/src/main/ets/AppModel';
import { AppCloneBadgeComponent } from '@ohos/settings.application/src/main/ets/components/AppCloneBadgeComponent';
import { SettingIconStyle, } from '@ohos/settings.common/src/main/ets/framework/model/SettingItemModel';
import { PADDING_16, PADDING_2, PADDING_6, } from '@ohos/settings.common/src/main/ets/constant/StyleConstant';
import { AppManager } from '@ohos/settings.application/src/main/ets/util/AppManager';
import { ResourceUtil } from '@ohos/settings.common/src/main/ets/utils/ResourceUtil';
import { UninstallResult } from '@ohos/settings.application/src/main/ets/model/UninstallResult';
import { AppEntryStorage } from '../constant/StorageConstant';
import { StorageSizeUtil } from '../utils/StorageSizeUtil';

const TAG: string = 'AppUninstallComponent';
const SELECT_UNINSTALL_APP_EVENT: string = 'change_chose_app_uninstall';
const MAX_STACK_IMAGE_SIZE: number = 3;

@Component
export struct AppUninstallComponent {
  iconStyle: SettingIconStyle = this.getIconStyle();
  private uninstallAppDialogController: CustomDialogController | undefined = undefined;
  @State private appList: AppEntry[] = [];
  private selectUninstallAppCallback = (selectedAppList: AppEntryStorage[]) => {
    this.appList = selectedAppList as AppEntry[];
    LogUtil.info(`${TAG} update select uninstall app length: ${this.appList?.length}`);
  };

  aboutToAppear(): void {
    EventBus.getInstance().on(SELECT_UNINSTALL_APP_EVENT, this.selectUninstallAppCallback);
  }

  aboutToDisappear(): void {
    EventBus.getInstance().detach(SELECT_UNINSTALL_APP_EVENT, this.selectUninstallAppCallback);
  }

  build() {
    Column() {
      Button({ type: ButtonType.Normal }) {
        Text(this.appList?.length <= 0 ? $r('app.string.uninstall') :
        ResourceUtil.getPluralStringValueSync($r('app.plural.delete_apps_selected'), this.appList.length))
          .fontFamily('HarmonyHeiTi')
          .fontWeight(FontWeight.Medium)
          .fontSize($r('sys.float.Body_L'))
          .fontColor($r('sys.color.ohos_id_color_warning'))
          .constraintSize({
            minHeight: 21,
          })
          .margin({
            top: $r('sys.float.padding_level5'),
            bottom: $r('sys.float.padding_level5'),
            left: $r('sys.float.padding_level8'),
            right: $r('sys.float.padding_level8'),
          })
          .maxLines(2)
          .ellipsisMode(EllipsisMode.END)
          .textOverflow({overflow: TextOverflow.Ellipsis})
      }
      .onClick(() => {
        this.openUninstallAppDialog();
      })
      .borderRadius($r('sys.float.corner_radius_level10'))
      .enabled(this.appList.length > 0)
      .width('100%')
      .backgroundColor($r('sys.color.comp_background_tertiary'))
    }
    .justifyContent(FlexAlign.End)
    .padding({
      bottom: $r('sys.float.padding_level10'),
      top: $r('sys.float.padding_level10'),
      left: $r('sys.float.padding_level10'),
      right: $r('sys.float.padding_level10'),
    })
  }

  @Builder
  BulkUninstallDialogBuilder(list: AppEntry[]) {
    Column() {
      if (list?.length === 1) {
        AppCloneBadgeComponent({
          iconStyle:{
            border: { width: '0px', color: '#00000000', radius: 0 },
            borderRadius: 0,
            width: 64,
            height: 64,
            mirrored: false,
            interpolation: ImageInterpolation.Medium,
            draggable: false
          } as SettingIconStyle,
          entry: list[0],
          isNeedEndPadding: false,
          iconSize: 64,
          bundleName: list[0]?.name
        })

        Text($r('app.string.is_delete_app', list[0]?.label))
          .fontFamily('HarmonyHeiTi')
          .fontWeight(FontWeight.Bold)
          .fontSize($r('sys.float.Title_S'))
          .maxFontScale(2)
          .fontColor($r('sys.color.font_primary'))
          .wordBreak(WordBreak.BREAK_WORD)
          .margin({ top: LengthMetrics.vp(16) })
      } else {
        Stack({ alignContent: Alignment.End }) {
          ForEach(this.getShowIconApps(list), (item: AppEntry, index: number) => {
            AppCloneBadgeComponent({
              iconStyle:{
                border: { width: '0px', color: '#00000000', radius: 0 },
                borderRadius: 0,
                width: 64,
                height: 64,
                mirrored: false,
                interpolation: ImageInterpolation.Medium,
                draggable: false
              } as SettingIconStyle,
              entry: list[index],
              isNeedEndPadding: false,
              iconSize: 64,
              bundleName: list[index]?.name
            })
              .zIndex(list?.length - index)
              .rotate({
                x: 0,
                y: 0,
                z: 1,
                centerX: '50%',
                centerY: '50%',
                angle: 10 * index
              })
          })
        }

        Text(ResourceUtil.getPluralStringValueSync($r('app.plural.is_delete_apps_number'), list?.length))
          .fontFamily('HarmonyHeiTi')
          .fontWeight(FontWeight.Bold)
          .fontSize($r('sys.float.Title_S'))
          .maxFontScale(2)
          .fontColor($r('sys.color.font_primary'))
          .wordBreak(WordBreak.BREAK_WORD)
          .margin({ top: LengthMetrics.vp(16) })
      }

      Text($r('app.string.after_delete'))
        .fontFamily('HarmonyHeiTi')
        .fontWeight(FontWeight.Medium)
        .fontSize($r('sys.float.Body_L'))
        .fontColor($r('sys.color.font_primary'))
        .wordBreak(WordBreak.BREAK_WORD)
        .margin({ top: LengthMetrics.vp(16) })
    }
    .width('100%')
  }

  private getShowIconApps(list: AppEntry[]): AppEntry[] {
    let apps: AppEntry[] = [];
    if (!list) {
      return apps;
    }
    let maxIndex: number = Math.min(list.length, MAX_STACK_IMAGE_SIZE);
    for (let i = 0; i < maxIndex; i++) {
      apps.push(list[i]);
    }
    return apps;
  }

  private openUninstallAppDialog(): void {
    LogUtil.info(`${TAG} onUninstallAppDialog`);
    this.uninstallAppDialogController = new CustomDialogController({
      builder: CustomContentDialog({
        contentBuilder: () => {
          this.BulkUninstallDialogBuilder(this.appList);
        },
        buttons: [{
          value: $r('app.string.dialog_cancel'),
          action: () => {
            this.uninstallAppDialogController?.close();
          }
        },
          {
            value: $r('app.string.app_info_uninstall'),
            action: () => {
              LogUtil.info(`${TAG} onDialogConfirm`);
              this.uninstallAppDialogController?.close();
              this.uninstallApp(this.appList);
            },
            fontColor: $r('sys.color.ohos_id_color_warning')
          }]
      }),
      autoCancel: false,
      alignment: DialogAlignment.Center,
    });
    this.uninstallAppDialogController.open();
  }

  private async uninstallApp(uninstallList: AppEntry[]): Promise<void> {
    let dialogController = new CustomDialogController({
      builder: LoadingDialog({
        content: $r('app.string.deleting'),
      })
    });
    try {
      dialogController.open();
      let uninstallFailedApps: AppEntry[] = [];
      let allAppSize: number = 0;
      LogUtil.info(`${TAG} uninstall start `)
      for (let i = 0; i < uninstallList.length; i++) {
        let item = uninstallList[i];
        let result: UninstallResult = await AppManager.getInstance().uninstallApp(item?.name ?? '', item?.appIndex ?? 0);
        LogUtil.info(`${TAG} uninstall ${item?.name} result:${result.isSuccess}`);
        if (result.isSuccess) {
          allAppSize += Number(item?.totalSize);
        } else {
          uninstallFailedApps.push(item);
        }
      }
      dialogController.close();
      LogUtil.info(`${TAG} uninstall completed`);
      this.appList = uninstallFailedApps;
      LogUtil.info(`${TAG} ShowToastOptions`);
      const options: promptAction.ShowToastOptions = {
        message: $r('app.string.freed_memory_apps_number', String(StorageSizeUtil.formatDataIntl(allAppSize, 0, true))),
        duration: 2000,
      };
      try {
        promptAction.showToast(options);
      } catch (error) {
        LogUtil.error(`${TAG} showToast error code is ${error?.code}, message is ${error?.message}`);
      }
    } catch (error) {
      LogUtil.error(`${TAG} uninstallApp List error: ${error?.message}`)
    }
  }

  private getIconStyle(): SettingIconStyle {
    // 接入了HDS之后,图标不需要主动做描边处理
    let style: SettingIconStyle = {
      border: { width: '0px', color: '#00000000', radius: 0 },
      borderRadius: 0,
      width: 64,
      height: 64,
      mirrored: false,
      interpolation: ImageInterpolation.Medium
    };
    return style;
  }
}

@Extend(Image)
function iconStyle(style: SettingIconStyle) {
  .width(style.width)
  .height(style.height)
  .objectFit(style.objectFit)
  .borderRadius(style.borderRadius || $r('sys.float.corner_radius_level6'))
  .draggable(style.draggable)
  .interpolation(style.interpolation)
  .edgeAntialiasing(style.edgeAntialiasing)
  .border(style.border)
  .clip(style.clip)
  .syncLoad(true)
  .matchTextDirection(style.mirrored)
  .accessibilityText(style?.accessibilityText)
  .accessibilityLevel(style?.accessibilityLevel)
}