/*
 * 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.
 */

import common from '@ohos.app.ability.common';
import commonEventManager from '@ohos.commonEventManager';
import relationalStore from '@ohos.data.relationalStore';
import { HiSysRdbEventGroup } from '../systemEvent/BehaviorEventConsts';
import { HiSysEventUtil } from '../systemEvent/HiSysEventUtil';
import { LogUtil } from '../utils/LogUtil';
import DatabaseManager from './DatabaseManager';
import { DEVICE_USAGE_HISTORY_TABLE, DeviceUsageHistory, SQL_CREATE_DEVICE_USAGE_TABLE, } from './DeviceUsageDataType';

/* instrument ignore file */
const TAG: string = 'DeviceUsageDataManager:';
const RDB_CORRUPTION_ERROR_CODE: number = 14800011;

export const DEVICE_USAGE_DATA_LOADING: string = 'DeviceUsageDataLoading';

// RDB 数据库的初始化配置
export const STORE_CONFIG: relationalStore.StoreConfig = {
  name: 'SettingsApp.db',
  securityLevel: relationalStore.SecurityLevel.S1,
  encrypt: false,
  isSearchable: true,
  haMode: relationalStore.HAMode.MAIN_REPLICA, //配置为双写备份
  allowRebuild: true
};

export class DeviceUsageManager extends DatabaseManager {
  public rdbStore: relationalStore.RdbStore | undefined;

  /**
   * 获取关系数据库存储对象
   * 如果已初始化过,则直接返回之前获取的对象
   * 如果没有初始化过,则使用接口获取对象,并执行数据库建表命令,如果表未创建,则会创建一张新的表
   *
   * @return 关系数据库存储对象
   */
  async getRdb(context: common.Context): Promise<relationalStore.RdbStore | undefined> {
    if (this.rdbStore) {
      return this.rdbStore;
    }
    try {
      LogUtil.info(`${TAG} getRdbStore start.`);
      let rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG);
      await rdbStore.executeSql(SQL_CREATE_DEVICE_USAGE_TABLE);
      this.rdbStore = rdbStore;
      LogUtil.info(`${TAG} getRdbStore success. rdbStoreBattery.version:${this.rdbStore?.version}`);
    } catch (error) {
      LogUtil.error(`${TAG} getRdbStore error. code:${error?.code} message:${error?.message}`);
      if (error.code === RDB_CORRUPTION_ERROR_CODE) {
        HiSysEventUtil.reportDefaultFaultEvent(HiSysRdbEventGroup.EVENT_NAME,
          HiSysRdbEventGroup.SETTINGS_DATA_RDB_CORRUPTION);
        await super.restoreRdb();
      }
    }
    return this.rdbStore;
  }

  /**
   * 设备使用时长数据库 - 插入数据
   */
  async batchInsertDeviceUsageHistoryData(context: common.Context,
    itemInfoList?: relationalStore.ValuesBucket[]): Promise<void> {
    if (itemInfoList) {
      const rdbStore = await this.getRdb(context);
      let transaction: relationalStore.Transaction | undefined;
      try {
        transaction = await rdbStore?.createTransaction();
        if (transaction) {
          const predicates = new relationalStore.RdbPredicates(DEVICE_USAGE_HISTORY_TABLE);
          LogUtil.info(`${TAG} deleteDeviceUsageHistoryData start.`);
          // 先删除保证时序
          let deleteNum: number = await transaction.delete(predicates);
          LogUtil.info(`${TAG} batchInsertDeviceUsageHistoryData start. deleted num: ${deleteNum}, need insert num: ${itemInfoList?.length}`);
          let insertNum: number = await transaction.batchInsert(DEVICE_USAGE_HISTORY_TABLE, itemInfoList);
          LogUtil.info(`${TAG} batchInsertDeviceUsageHistoryData success, insertNum: ${insertNum}`);
          await transaction.commit();
          LogUtil.info(`${TAG} commit device usage data success`);
          this.sendBarChartRefresh();
        }
      } catch (error) {
        LogUtil.error(`${TAG} batchInsertDeviceUsageHistoryData error. code: ${error?.code} message: ${error?.message}`);
        if (error.code === RDB_CORRUPTION_ERROR_CODE) {
          HiSysEventUtil.reportDefaultFaultEvent(HiSysRdbEventGroup.EVENT_NAME,
            HiSysRdbEventGroup.SETTINGS_DATA_RDB_CORRUPTION);
          await super.restoreRdb();
        }
        if (transaction) {
          transaction?.rollback();
        }
      }
    }
  }

  /**
   *  查询所有数据
   */
  async queryDeviceUsageHistoryData(context: common.Context): Promise<DeviceUsageHistory[]> {
    const rdbStore = await this.getRdb(context);
    let resultSet: relationalStore.ResultSet | undefined = undefined;
    let deviceUsageHistoryList: DeviceUsageHistory[] = [];
    try {
      const predicates = new relationalStore.RdbPredicates(DEVICE_USAGE_HISTORY_TABLE);
      predicates.orderByDesc('timestamp');
      LogUtil.info(`${TAG} queryDeviceUsageHistoryData start.`);
      resultSet = await rdbStore?.query(predicates);
      if (!resultSet) {
        LogUtil.warn(`${TAG} queryDeviceUsageHistoryData failed.`);
        return deviceUsageHistoryList;
      }
      LogUtil.info(`${TAG} queryDeviceUsageHistoryData success. resultSet.rowCount: ${resultSet.rowCount}.`);
      while (resultSet.goToNextRow()) {
        const timestamp = resultSet.getLong(resultSet.getColumnIndex('timestamp'));
        const screenOnTime = resultSet.getLong(resultSet.getColumnIndex('screenOnTime'));
        const screenOffActivityTime = resultSet.getLong(resultSet.getColumnIndex('screenOffActivityTime'));
        deviceUsageHistoryList.push({
          timestamp,
          screenOnTime,
          screenOffActivityTime,
        });
      }
    } catch (error) {
      LogUtil.error(`${TAG} queryDeviceUsageHistoryData error. code:${error?.code} message:${error?.message}`);
      if (error.code === RDB_CORRUPTION_ERROR_CODE) {
        HiSysEventUtil.reportDefaultFaultEvent(HiSysRdbEventGroup.EVENT_NAME,
          HiSysRdbEventGroup.SETTINGS_DATA_RDB_CORRUPTION);
        await super.restoreRdb();
      }
    } finally {
      resultSet?.close();
    }
    return deviceUsageHistoryList;
  }

  /**
   * 通知电池柱状图图重新查数据库来刷新数据
   */
  sendBarChartRefresh(): void {
    try {
      commonEventManager.publish(DEVICE_USAGE_DATA_LOADING, () => {
      });
    } catch (error) {
      LogUtil.error(`commonEventManager createSubscriber error: ${error?.code} ${error?.message}`);
    }
  }
}

export default new DeviceUsageManager();