/**
 * Copyright (c) 2024 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 { BusinessError } from '@kit.BasicServicesKit';
import { calendarManager } from '@kit.CalendarKit'
import common from '@ohos.app.ability.common';
import bundleManager from '@ohos.bundle.bundleManager';
import DataColumns from '../common/data/DataColumns';
import LogUtils from '../common/utils/LogUtils';
import RawContactsColumns from '../common/data/RawContactsColumns';
import relationalStore from '@ohos.data.relationalStore';
import { ValuesBucket } from '@ohos.data.ValuesBucket';
import { abilityAccessCtrl } from '@kit.AbilityKit';
import SettingsColumns from '../common/data/SettingsColumns';
import { StringUtil } from '../common/utils/StringUtil';
import { contactRdbHelper } from '../common/helperUtils/ContactsRdbHelperForCloudSync';
import DbConstants from '../common/DbConstants';

const TAG = 'BirthdayManager';
const EVENT_TYPE_ID: number = 11;
const BIRTHDAY_TYPE: string[] = ['1', '2', '1.0', '2.0'];
const BIRTHDAY_NOT_SYNC_DIRTY: number = 0;
const BIRTHDAY_NOT_SYNC_SUCCEED: number = 1;
const BIRTHDAY_NOT_SYNC_FAILED: number = 2;
const BIRTHDAY_NOT_SYNC_INVALID: number = 3;
const BIRTHDAY_TYPE_LUNAR: string = '2';
const BIRTHDAY_TYPE_LUNAR_POINT: string = '2.0';
const NORMAIL_CONTACT: number = 0;
const columns = [DataColumns.DETAIL_INFO, RawContactsColumns.DISPLAY_NAME, RawContactsColumns.CONTACT_ID,
    DataColumns.CUSTOM_DATA, DataColumns.CALENDAR_EVENT_ID, DataColumns.RAW_CONTACT_ID];
export default class BirthdayManager {
  private context: common.Context | undefined = undefined;
  private calendar: calendarManager.Calendar | undefined = undefined;
  private calendarManager: calendarManager.CalendarManager | null = null;
  private static singleInstance: BirthdayManager;
 
  /**
   *  单例
   * @returns BirthdayManager
   */
  public static getInstance(): BirthdayManager {
    if (BirthdayManager.singleInstance == null) {
      BirthdayManager.singleInstance = new BirthdayManager();
    }
    return BirthdayManager.singleInstance;
  }
 
  /**
   * 初始化方法
   * @param context context
   */
  public init(context: common.Context) {
    this.context = context;
  }
 
  /**
   * 查询是否有读写日历的权限
   */
  public async isHaveCalendarPermission(): Promise<Boolean> {
    let info = await bundleManager.getApplicationInfo('com.ohos.contactsdataability',
      bundleManager.ApplicationFlag.GET_APPLICATION_INFO_WITH_PERMISSION);
    if (info) {
      let hasPermission: number = abilityAccessCtrl.createAtManager().
        verifyAccessTokenSync(info.accessTokenId, 'ohos.permission.WRITE_CALENDAR');
      LogUtils.i(TAG, `isHaveCalendarPermission hasPermission = ${hasPermission}`);
      return hasPermission === 0;
    }
    return false;
  }
 
  /**
   * 生成calendar对象
   */
  public async createCalendar(): Promise<boolean> {
    let isHaveCalendarPermission = await this.isHaveCalendarPermission();
    if (!isHaveCalendarPermission) {
      LogUtils.i(TAG, `createCalendar failed, no calendar permission.`);
      return false;
    }
    this.calendarManager = calendarManager.getCalendarManager(this.context!);
    if (!this.calendarManager || this.calendarManager === undefined) {
      return false;
    }
    // 日历账号,联系人数据库的日历账号
    const calendarAccount: calendarManager.CalendarAccount = {
      name: bundleManager?.getBundleInfoForSelfSync(
        bundleManager?.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION).name,
      type: calendarManager?.CalendarType?.BIRTHDAY
    };
    try {
      this.calendar = await this.calendarManager?.getCalendar(calendarAccount);
      return (this.calendar && this.calendar !== undefined);
    } catch (err) {
      LogUtils.e(TAG, `Failed to get calendar. Code: ${err.code}, message: ${err.message}`);
      if (err) {
        try {
          this.calendar = await this.calendarManager?.createCalendar(calendarAccount);
          LogUtils.i(TAG, `Succeeded in creating calendar`);
          if (this.calendar) {
            this.calendarSetConfig(this.calendar);
            return true;
          }
        } catch (error) {
          LogUtils.e(TAG, `Failed to create calendar. Code: ${error.code}, message: ${error.message}`);
        }
      }
    };
    return false;
  }
 
  /**
   * 检查calendar对象
   * @returns 
   */
  private async checkCalendarObject(): Promise<boolean> {
    if (!this.calendar || this.calendar === undefined) {
      return await this.createCalendar();
    }
    return true;
  }
 
  /**
   * 通过raw_contact_id列表查询view_contact_data表中生日信息,用于删除日历中生日
   * @param rawIdList 
   * @returns eventIds
   */
  public async queryEventId(rawIdList: number[]): Promise<number[]> {
    LogUtils.i(TAG, `queryEventId eventInfo ->${rawIdList}`);
    const eventIds: number[] = [];
    if (!rawIdList || rawIdList.length <= 0) {
      return eventIds;
    }
    let resultSet: relationalStore.ResultSet | null | undefined = null;
    try {
      const rdbStore = await contactRdbHelper.initDB(this.context!);
      if (!rdbStore) {
        throw new Error(`initDb fail`);
      }
      const predicate: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('view_contact_data');
      predicate.in(DataColumns.RAW_CONTACT_ID, rawIdList);
      predicate.and();
      predicate.equalTo(DataColumns.TYPE_ID, EVENT_TYPE_ID);
      predicate.and();
      predicate.in(DataColumns.CUSTOM_DATA, BIRTHDAY_TYPE); //只有生日插入日历数据库
      const columns = [DataColumns.CALENDAR_EVENT_ID];
      resultSet = await rdbStore.query(predicate, columns);
      if (!resultSet || resultSet.rowCount <= 0) {
        return eventIds;
      }
      let calendarEventId: String = '';
      if (resultSet.goToFirstRow()) {
        do {
          calendarEventId = resultSet.getString(resultSet.getColumnIndex(DataColumns.CALENDAR_EVENT_ID));
          LogUtils.w(TAG, `buildEvents calendarEventId ->${calendarEventId}`);
          if (calendarEventId) {
            eventIds.push(Number(calendarEventId));
          }
        } while (resultSet.goToNextRow());
      }
    } catch (error) {
      LogUtils.e(TAG, `Failed to queryEventId. Code: ${error.code}, message: ${error.message}`);
    } finally {
      if (resultSet && !resultSet.isClosed) {
        resultSet.close();
      }
    }
    return eventIds;
  }
 
  /**
   * 查询view_contact_data视图中所有未同步到日历中的生日信息,即
   * IS_SYNC_BIRTHDAY_TO_CALENDAR = 0的
   * @returns 
   */
  private async handleInsertAndUpdateBirthday() {
    let resultSet: relationalStore.ResultSet | null | undefined = null;
    try {
      LogUtils.i(TAG, `handleInsertAndUpdateBirthday start.`);
      const rdbStore = await contactRdbHelper.initDB(this.context!);
      if (!rdbStore) {
        LogUtils.e(TAG, `handleInsertAndUpdateBirthday initDB failed.`);
        return;
      }
      const predicate: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('view_contact_data');
      predicate.equalTo(DataColumns.TYPE_ID, EVENT_TYPE_ID);
      predicate.and();
      predicate.in(DataColumns.CUSTOM_DATA, BIRTHDAY_TYPE); //只有生日插入日历数据库
      predicate.and();
 
      //只有IS_SYNC_BIRTHDAY_TO_CALENDAR = 0的都需要同步
      predicate.equalTo(DataColumns.IS_SYNC_BIRTHDAY_TO_CALENDAR, BIRTHDAY_NOT_SYNC_DIRTY);
      predicate.and();
      predicate.equalTo(RawContactsColumns.IS_DELETED, NORMAIL_CONTACT);
      resultSet = await rdbStore.query(predicate, columns);
      LogUtils.i(TAG, `handleInsertAndUpdateBirthday resultSet.rowCount ->${resultSet?.rowCount}`);
      if (!resultSet || resultSet.rowCount <= 0) {
        return;
      }
      await this.syncEventToCalendar(resultSet, true);
    } catch (error) {
      LogUtils.e(TAG, `Failed to handleInsertAndUpdateBirthday. Code: ${error.code}, message: ${error.message}`);
    } finally {
      if (resultSet && !resultSet.isClosed) {
        resultSet.close();
      }
    }
  }
 
  /**
   * 查询删除失败的生日,触发再次删除
   */
  private async handleDeletedBirthday() {
    let resultSet: relationalStore.ResultSet | null | undefined = null;
    try {
      LogUtils.i(TAG, `handleDeletedBirthday start.`);
      const rdbStore = await contactRdbHelper.initDB(this.context!);
      if (!rdbStore) {
        LogUtils.e(TAG, `handleDeletedBirthday initDB failed.`);
        return;
      }
      const predicate: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('view_contact_data');
      predicate.equalTo(DataColumns.TYPE_ID, EVENT_TYPE_ID);
      predicate.and();
      predicate.in(DataColumns.CUSTOM_DATA, BIRTHDAY_TYPE); //只有生日插入日历数据库
      predicate.and();
 
      //只有IS_SYNC_BIRTHDAY_TO_CALENDAR = 0的都需要同步
      predicate.equalTo(DataColumns.IS_SYNC_BIRTHDAY_TO_CALENDAR, BIRTHDAY_NOT_SYNC_FAILED);
      resultSet = await rdbStore.query(predicate, columns);
      LogUtils.i(TAG, `handleDeletedBirthday resultSet.rowCount ->${resultSet?.rowCount}`);
      if (!resultSet || resultSet.rowCount <= 0) {
        return;
      }
      let calendarEventId: string = '';
      let eventIds: number[] = [];
      if (resultSet.goToFirstRow()) {
        do {
          calendarEventId = resultSet.getString(resultSet.getColumnIndex(DataColumns.CALENDAR_EVENT_ID));
          LogUtils.i(TAG, `handleDeletedBirthday calendarEventId ->${calendarEventId}`);
          eventIds.push(Number(calendarEventId));
        } while (resultSet.goToNextRow());
      }
      if (eventIds.length > 0) {
        await this.deleteBirthdayEvent(eventIds);
      }
    } catch (error) {
      LogUtils.e(TAG, `Failed to handleDeletedBirthday. Code: ${error.code}, message: ${error.message}`);
    } finally {
      if (resultSet && !resultSet.isClosed) {
        resultSet.close();
      }
    }
  }
 
  /**
   * 进程启动时,处理没有同步到日历的生日,包括需要更新、插入、删除的
   */
  public async syncAllBirthdayToCalendar() {
    LogUtils.i(TAG, `syncAllBirthdayToCalendar start.`);
    let isCreateCalendar: boolean = await this.createCalendar();
    if (isCreateCalendar) {
      await this.handleDeletedBirthday();
      await this.handleInsertAndUpdateBirthday();
    }
  }

  /**
   * 刷新生日提醒 只执行一次,后面要删掉
   */
  public async refreshBirthReminder() {
    let resultSet: relationalStore.ResultSet | null | undefined = null;
    try {
      LogUtils.i(TAG, `refreshBirthReminder start.`);
      const rdbStore = await contactRdbHelper.initDB(this.context!);
      if (!rdbStore) {
        LogUtils.e(TAG, `refreshBirthReminder initDB failed.`);
        return;
      }

      // 刷新生日提醒,所有正常联系人生日都需要刷新。
      const predicate: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('view_contact_data');
      predicate.equalTo(DataColumns.TYPE_ID, EVENT_TYPE_ID);
      predicate.and();
      predicate.in(DataColumns.CUSTOM_DATA, BIRTHDAY_TYPE); //只有生日插入日历数据库
      predicate.and();
      predicate.equalTo(RawContactsColumns.IS_DELETED, NORMAIL_CONTACT);
      resultSet = await rdbStore.query(predicate, columns);
      LogUtils.i(TAG, `refreshBirthReminder resultSet.rowCount ->${resultSet?.rowCount}`);
      if (!resultSet || resultSet.rowCount <= 0) {
        return;
      }
      await this.syncEventToCalendar(resultSet, true);
    } catch (error) {
      LogUtils.e(TAG, `Failed to refreshBirthReminder. Code: ${error.code}, message: ${error.message}`);
    } finally {
      if (resultSet && !resultSet.isClosed) {
        resultSet.close();
      }
    }
  }

  /**
   * 更新 settings表中 refresh_contacts 值为13
   */
  private async updateSettingsRefreshContacts() {
    try {
      const rdbStore = await contactRdbHelper.initDB(this.context!);
      if (!rdbStore) {
        throw new Error(`initDb fail`);
      }
      const predicateSettings: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('settings');
      predicateSettings.equalTo(SettingsColumns.ID, 1);
      const updateBucket: ValuesBucket = {};
      updateBucket[SettingsColumns.REFRESH_CONTACTS] = 13;
      let rdbRet = await contactRdbHelper.updateData(updateBucket, predicateSettings);
      LogUtils.w(TAG, `updateSettingsRefreshContacts  update rdbRet: ${rdbRet}`);
    } catch (err) {
      LogUtils.e(TAG, `Failed to updateSettingsRefreshContacts Code: ${err.code}, message: ${err.message}`);
    }
  }
 
  /**
   * 根据rawContactId从view_contact_data视图中查询相关信息构建event对象
   * @param rawContactId
   * @param isNeedUpdate 通过联系人新建没有update操作,云同步等其他场景有更新的场景
   */
  public async handleSingleBirthday(rawContactId: string, isNeedUpdate: boolean) {
    let detailInfoResultSet: relationalStore.ResultSet | null | undefined = null;
    try {
      LogUtils.i(TAG, `handleSingleBirthday rawContactId ->${rawContactId}`);
      const rdbStore = await contactRdbHelper.initDB(this.context!);
      if (!rdbStore) {
        throw new Error(`initDb fail`);
      }
      const predicate: relationalStore.RdbPredicates = new relationalStore.RdbPredicates('view_contact_data');
      predicate.equalTo(DataColumns.RAW_CONTACT_ID, rawContactId);
      predicate.and();
      predicate.equalTo(DataColumns.TYPE_ID, EVENT_TYPE_ID);
      predicate.and();
      predicate.in(DataColumns.CUSTOM_DATA, BIRTHDAY_TYPE); //只有生日插入日历数据库
      detailInfoResultSet = await rdbStore.query(predicate, columns);
      LogUtils.i(TAG, `handleSingleBirthday detailInfoResultSet.rowCount ->${detailInfoResultSet?.rowCount}`);
      await this.syncEventToCalendar(detailInfoResultSet, isNeedUpdate);
    } catch (error) {
      LogUtils.e(TAG, `Failed to handleSingleBirthday. Code: ${error.code}, message: ${error.message}`);
    } finally {
      if (detailInfoResultSet && !detailInfoResultSet.isClosed) {
        detailInfoResultSet.close();
      }
    }
  }
 
  /**
   * 根据rawContactId集合从view_contact_data视图中查询相关信息构建event对象
   * @param rawContactIds
   * @param isNeedUpdate 通过联系人新建没有update操作,云同步等其他场景有更新的场景
   */
  public async handleBatchBirthday(rawContactIds: number[], isNeedUpdate: boolean) {
    let detailInfoResultSet: relationalStore.ResultSet | null | undefined = null;
    try {
      LogUtils.i(TAG, `handleBatchBirthday rawContactIds ->${rawContactIds}`);
      const rdbStore = await contactRdbHelper.initDB(this.context!);
      if (!rdbStore) {
        throw new Error(`initDb fail`);
      }
      const predicate: relationalStore.RdbPredicates = new relationalStore.RdbPredicates("view_contact_data");
      predicate.in(DataColumns.RAW_CONTACT_ID, rawContactIds);
      predicate.and();
      predicate.equalTo(DataColumns.TYPE_ID, EVENT_TYPE_ID);
      predicate.and();
      predicate.in(DataColumns.CUSTOM_DATA, BIRTHDAY_TYPE); //只有生日插入日历数据库
      detailInfoResultSet = await rdbStore.query(predicate, columns);
      LogUtils.i(TAG, `handleBatchBirthday detailInfoResultSet.rowCount ->${detailInfoResultSet?.rowCount}`);
      await this.syncEventToCalendar(detailInfoResultSet, isNeedUpdate);
    } catch (error) {
      LogUtils.e(TAG, `Failed to handleBatchBirthday. Code: ${error.code}, message: ${error.message}`);
    } finally {
      if (detailInfoResultSet && !detailInfoResultSet.isClosed) {
        detailInfoResultSet.close();
      }
    }
  }

  /**
   * Process non-standard format dates.
   * @param date
   * @returns the result.
   */
  private async handleDate(date: string): Promise<string> {
    if (!date || !date.includes('-')) {
      return date;
    }
    const currentYear = new Date().getFullYear();
    const dateArray = date.split('-');
    switch (dateArray.length) {
      case 3:
        if (dateArray[0].length < 4) {
          const index = date.indexOf('-');
          const suffix = date.substring(index);
          return `${currentYear}${suffix}`;
        }
        return date;
      case 2:
        return `${currentYear}-${date}`;
      default:
        LogUtils.e(TAG, `syncEventToCalendar dateArray length is Invalid.`);
        return date;
    }
  }

  /**
   * 从result中查询信息,构建event同步到日历
   * @param resultSet 
   * @returns 
   */
  private async syncEventToCalendar(resultSet: relationalStore.ResultSet, isNeedUpdate: boolean): Promise<boolean> {
    if (!resultSet || resultSet.rowCount <= 0) {
      return true;
    }
    let result: boolean = true;
    let resultAddOrUpdate: boolean = true;
    let detailInfo: string = '';
    let displayName: string = '';
    let rawContactId: number = 0;
    let contactId: number = 0;
    let customData: string = '';
    let calendarEventId: string = '';
    const recurrenceRule: calendarManager.RecurrenceRule = {
      recurrenceFrequency: calendarManager?.RecurrenceFrequency.YEARLY
    }
    if (resultSet.goToFirstRow()) {
      do {
        detailInfo = resultSet.getString(resultSet.getColumnIndex(DataColumns.DETAIL_INFO));
        displayName = resultSet.getString(resultSet.getColumnIndex(RawContactsColumns.DISPLAY_NAME));
        contactId = resultSet.getLong(resultSet.getColumnIndex(RawContactsColumns.CONTACT_ID));
        rawContactId = resultSet.getLong(resultSet.getColumnIndex(DataColumns.RAW_CONTACT_ID));
        customData = resultSet.getString(resultSet.getColumnIndex(DataColumns.CUSTOM_DATA));
        calendarEventId = resultSet.getString(resultSet.getColumnIndex(DataColumns.CALENDAR_EVENT_ID));
        detailInfo = await this.handleDate(detailInfo);
        detailInfo = this.processDate(detailInfo);
        LogUtils.i(TAG, `syncEventToCalendar detailInfo ->${detailInfo}, calendarEventId ->${calendarEventId}`);
        const date = new Date(detailInfo + ' ' + '00:00:00');
        const isDateInvalid = Number.isNaN(date.valueOf());
        if (isDateInvalid) {
          LogUtils.w(TAG, `syncEventToCalendar date is Invalid.`);
          // 更新is_sync_calendar_to_calendar 到 data表
          await this.updateContactDataByRawConId('syncEventToCalendar', rawContactId, BIRTHDAY_NOT_SYNC_INVALID, 0,
            customData);
          return true;
        }
        const startTimeStamp = date.getTime() - date.getTimezoneOffset() * 60000;
        const endTimeStamp = startTimeStamp + 24 * 60 * 60 * 1000;
        let isLunar: boolean = false;
        let identifierValue: string = contactId.toString();
        LogUtils.w(TAG, `syncEventToCalendar customData ->${customData}`);
        if (customData === BIRTHDAY_TYPE_LUNAR || customData === BIRTHDAY_TYPE_LUNAR_POINT) {
          isLunar = true;
          identifierValue = identifierValue + '_' + 'lunar' + date.valueOf();
        } else {
          identifierValue = identifierValue + '_' + 'solar' + date.valueOf();
        }
        LogUtils.w(TAG, `syncEventToCalendar identifierValue ->${identifierValue}`);
        const event: calendarManager.Event = {
          id: Number(calendarEventId),
          title: displayName,
          startTime: startTimeStamp,
          endTime: endTimeStamp,
          isAllDay: true,
          identifier: identifierValue,
          reminderTime: [0, 10080],
          type: calendarManager.EventType.NORMAL,
          recurrenceRule: recurrenceRule,
          timeZone: 'UTC',
          isLunar: isLunar,
        };
 
        //需要更新数据库的场景如云同步,isNeedUpdate为true,新建联系人为先删除,再插入,不执行更新操作isNeedUpdate为false
        if (isNeedUpdate && calendarEventId) {
          resultAddOrUpdate = await this.updateBirthdayEvent(event, Number(rawContactId), customData);
        } else {
          resultAddOrUpdate = await this.addBirthdayEvent(event, Number(rawContactId), customData);
        }
        if (!resultAddOrUpdate) {
          result = resultAddOrUpdate;
        }
      } while (resultSet.goToNextRow());
    }
    LogUtils.w(TAG, `syncEventToCalendar result ->${result}`);
    return result;
  }

   /**
   * 1900年 shanghai时区从GMT+0805调整到了GMT+0800,时间有5分钟偏差
   * 和日历定的规格是没有年份或者小于1904年,全部按照1904年处理
   * @param dateStr
   * @returns
   */
  private processDate(dateStr: string): string {
    // 匹配无年份格式
    const noYearPattern = /^\d{1,2}-\d{1,2}$/;
    // 匹配有年份格式
    const withYearPattern = /^\d{4}-\d{1,2}-\d{1,2}$/;
    LogUtils.w(TAG, `birthday date is ${dateStr}.`);
    if (noYearPattern.test(dateStr)) {
        // 如果没有年份,添加1904年
        const parts = dateStr.split('-');
        const month = parts[0].padStart(2, '0');
        const day = parts[1].padStart(2, '0');
        return `1904-${month}-${day}`;
    } else if (withYearPattern.test(dateStr)) {
        const parts = dateStr.split('-');
        const year = parseInt(parts[0]);
        const month = parts[1].padStart(2, '0');
        const day = parts[2].padStart(2, '0');

        if (year < 1904) {
            LogUtils.w(TAG, `birthday date is less than 1904.`);
            return `1904-${month}-${day}`;
        } else {
            return `${year}-${month}-${day}`;
        }
    } else {
        // 如果格式不符合预期,返回原始字符串
        return dateStr;
    }
  }

  /**
   * 添加生日到日历数据库
   */
  private async addBirthdayEvent(event: calendarManager.Event, rawContactId: number,
      customData: string):
    Promise<boolean> {
    LogUtils.i(TAG, `addBirthdayEvent start`);
    let checkCalendarObjectResult = await this.checkCalendarObject();
    if (!checkCalendarObjectResult) {
      return false;
    }
    try {
      let result: number = -1;
      result = await this.calendar?.addEvent(event) as number;
      LogUtils.w(TAG, `addBirthdayEvent result ->${result}`);

      if (result > -1) {
        //TODO 更新calendar_event_id 到 data表
        await this.updateContactDataByRawConId('addBirthdayEvent', rawContactId, BIRTHDAY_NOT_SYNC_SUCCEED, result,
          customData);
        return true;
      }
    } catch (err) {
      LogUtils.e(TAG, `addBirthdayEvent Failed to addEvent. Code: ${err.code}, message: ${err.message}`);
      return false;
    }
    return false;
  }
 
  /**
   * 更新生日到日历数据库
   */
  private async updateBirthdayEvent(event: calendarManager.Event, rawContactId: number, customData: string):
    Promise<boolean> {
    let checkCalendarObjectResult = await this.checkCalendarObject();
    if (!checkCalendarObjectResult) {
      return false;
    }
    try {
      await this.calendar?.updateEvent(event);
      LogUtils.i(TAG, `Succeeded in updating event`);
      await this.updateContactDataByRawConId('updateBirthdayEvent', rawContactId, BIRTHDAY_NOT_SYNC_SUCCEED, -1,
        customData);
      return true;
    } catch (err) {
      await this.updateContactDataByRawConId('updateBirthdayEvent', rawContactId, BIRTHDAY_NOT_SYNC_DIRTY, -1,
        customData);
      LogUtils.e(TAG, `Failed to update event. Code: ${err.code}, message: ${err.message}`);
      return false;
    }
  }
 
  /**
   * 通过rawConId更新contact_data表中is_sync_calendar_to_calendar标志
   * @param methodName the method name
   * @param rawContactId the raw_contact_id
   * @param isSyncBirthdayToCalendar the is_sync_birthday_to_calendar
   */
  private async updateContactDataByRawConId(methodName: string, rawContactId: number,
    isSyncBirthdayToCalendar: number, calendarEventId: number, customData: string) {
    try {
      const rdbStore = await contactRdbHelper.initDB(this.context!);
      if (!rdbStore) {
        throw new Error(`initDb fail`);
      }
      const updateBucket: ValuesBucket = {};
      if (calendarEventId > 0) {
        updateBucket[DataColumns.CALENDAR_EVENT_ID] = calendarEventId;
      }
      updateBucket[DataColumns.IS_SYNC_BIRTHDAY_TO_CALENDAR] = isSyncBirthdayToCalendar;
      const predicates: relationalStore.RdbPredicates =
        new relationalStore.RdbPredicates(DbConstants.CLONE_NEXT2NEXT_DATA_TABLE_NAME);
      predicates.equalTo(DataColumns.RAW_CONTACT_ID, rawContactId);
      predicates.and();
      predicates.equalTo(DataColumns.CUSTOM_DATA, customData);
      predicates.and();
      predicates.equalTo(DataColumns.TYPE_ID, EVENT_TYPE_ID);
      let rdbRet = await contactRdbHelper.updateData(updateBucket, predicates);
      LogUtils.w(TAG, `${methodName} update table contact_data by rawConId, rdbRet: ${rdbRet}`);
    } catch (err) {
      LogUtils.e(TAG, `Failed to update table contact_data by rawConId in ${methodName}. Code: ${err.code}, message:
        ${err.message}`);
    }
  }
 
  /**
   *  更新contact_data表中is_sync_calendar_to_calendar标志
   * @param methodName the method name
   * @param eventIds the calendar_event_id
   * @param isSyncBirthdayToCalendar the is_sync_birthday_to_calendar
   */
  private async updateContactDataByEventId(methodName: string, eventIds: number[], isSyncBirthdayToCalendar: number) {
    try {
      const rdbStore = await contactRdbHelper.initDB(this.context!);
      if (!rdbStore) {
        throw new Error(`initDb fail`);
      }
      const updateBucket: ValuesBucket = {};
      updateBucket[DataColumns.IS_SYNC_BIRTHDAY_TO_CALENDAR] = isSyncBirthdayToCalendar;
      if (isSyncBirthdayToCalendar === BIRTHDAY_NOT_SYNC_DIRTY) {
        updateBucket[DataColumns.CALENDAR_EVENT_ID] = '';
      }
      const predicates: relationalStore.RdbPredicates =
        new relationalStore.RdbPredicates(DbConstants.CLONE_NEXT2NEXT_DATA_TABLE_NAME);
      predicates.in(DataColumns.CALENDAR_EVENT_ID, eventIds);
      let rdbRet = await contactRdbHelper.updateData(updateBucket, predicates);
      LogUtils.w(TAG, `${methodName} update table contact_data by rawconId, rdbRet: ${rdbRet}`);
    } catch (err) {
      LogUtils.e(TAG, `Failed to update table contact_data by rawconId in ${methodName}. Code: ${err.code}, message:
        ${err.message}`);
    }
  }
 
  /**
   * 从日历数据库删除生日
   */
  public async deleteBirthdayEvent(eventIds: number[]) {
    LogUtils.i(TAG, `deleteBirthdayEvent start.`);
    let checkCalendarObjectResult = await this.checkCalendarObject();
    if (!checkCalendarObjectResult || eventIds.length <= 0) {
      return;
    }
    try {
      await this.calendar?.deleteEvents(eventIds);
      LogUtils.w(TAG, `Succeeded in deleting events`);
      await this.updateContactDataByEventId('deleteBirthdayEvent', eventIds, BIRTHDAY_NOT_SYNC_DIRTY);
    } catch (err) {
      await this.updateContactDataByEventId('deleteBirthdayEvent', eventIds, BIRTHDAY_NOT_SYNC_FAILED);
      LogUtils.e(TAG, `Failed to delete events. Code: ${err.code}, message: ${err.message}`);
    }
  }
 
  private calendarSetConfig(calendar: calendarManager.Calendar) {
    const config: calendarManager.CalendarConfig = {
      enableReminder: true,
      color: '#FFE64566'
    };
    calendar.setConfig(config).then(() => {
      LogUtils.i(TAG, `Succeeded in setting config, data->{enableReminder: ${config?.enableReminder}, color: ${config?.color}`);
    }).catch((err: BusinessError) => {
      LogUtils.e(TAG, `Failed to set config. Code: ${err.code}, message: ${err.message}`);
    });
  }

  /**
   * 标记生日为要删除状态,即is_sync_birthday_to_calendar字段值为2
   * @param contactDataIds contact_data中id列表
   */
  public async markedBirthdayToDelFlag(contactDataIds: number[]) {
    LogUtils.w(TAG, `markedBirthdayToDelFlag contactDataIds ->${contactDataIds}`);
    if (!contactDataIds || contactDataIds.length <= 0) {
      return;
    }
    try {
      const rdbStore = await contactRdbHelper.initDB(this.context!);
      if (!rdbStore) {
        throw new Error(`initDb fail`);
      }
      const predicate: relationalStore.RdbPredicates =
        new relationalStore.RdbPredicates(DbConstants.CLONE_NEXT2NEXT_DATA_TABLE_NAME);
      predicate.in(DataColumns.ID, contactDataIds);
      const updateBucket: ValuesBucket = {};
      updateBucket[DataColumns.IS_SYNC_BIRTHDAY_TO_CALENDAR] = BIRTHDAY_NOT_SYNC_FAILED;
      let rdbRet = await contactRdbHelper.updateData(updateBucket, predicate);
      LogUtils.w(TAG, `markedBirthdayToDelFlag update table contact_data by contactDataIds, rdbRet: ${rdbRet}`);
    } catch (error) {
      LogUtils.e(TAG, `Failed to markedBirthdayToDelFlag. Code: ${error.code}, message: ${error.message}`);
    }
  }

  /**
   * 重置联系人数据库日程
   */
  public async resetAllCalendar(): Promise<boolean> {
    try {
      let checkCalendarObjectResult = await this.checkCalendarObject();
      if (!checkCalendarObjectResult) {
        return false;
      }

      // 删除账户下生日
      await this.calendarManager?.deleteCalendar(this.calendar);
      this.calendar = undefined;
      this.calendarManager = null;
      LogUtils.w(TAG, `deleteCalendar success`);

      // 将 contact_data 表的同步字段置为未同步
      const rdbStore = await contactRdbHelper.initDB(this.context!);
      if (!rdbStore) {
        LogUtils.w(TAG, 'resetAllCalendar rdb init fail!');
        return false;
      }
      // 更新信息
      const updateBucket: ValuesBucket = {};
      updateBucket[DataColumns.IS_SYNC_BIRTHDAY_TO_CALENDAR] = BIRTHDAY_NOT_SYNC_DIRTY;
      updateBucket[DataColumns.CALENDAR_EVENT_ID] = null;

      // 更新的条件
      const predicate: relationalStore.RdbPredicates =
        new relationalStore.RdbPredicates('contact_data');
      predicate.equalTo(DataColumns.TYPE_ID, EVENT_TYPE_ID);
      predicate.and();
      predicate.in(DataColumns.CUSTOM_DATA, BIRTHDAY_TYPE); //只有生日插入日历数据库,需要更新

      let rdbRet = await contactRdbHelper.updateData(updateBucket, predicate);
      LogUtils.w(TAG, `update contact_data BIRTHDAY_NOT_SYNC_DIRTY: ${rdbRet}`);
      if (rdbRet === -1) {
        LogUtils.e(TAG, `update contact_data BIRTHDAY_NOT_SYNC_DIRTY ret error: ${rdbRet}`);
        return false;
      }
    } catch (e) {
      LogUtils.e(TAG, 'resetAllCalendar delete old error: ' + e.code + '--' + e.message);
      return false;
    }

    try {
      // 重新同步账户下生日
      await this.syncAllBirthdayToCalendar();
      LogUtils.w(TAG, `syncAllBirthdayToCalendar: success`);
    } catch (e) {
      LogUtils.e(TAG, 'resetAllCalendar sync new error: ' + e.code + '--' + e.message);
      return false;
    }

    return true;
  }
   
  private async getEventString (event: calendarManager.Event, operation: string,
    customData: string): Promise<string> {
 
    const maskedTitle = StringUtil.maskSensitiveInfo(event?.title);
    const result = `${operation} {` +
    `displayName: ${maskedTitle},` +
    `identifier: ${event?.identifier},` +
    `isLunar: ${event?.isLunar},` +
    `customData: ${customData}}`;
    return result;
  }
}