class BatchCreateHandler {

  constructor(headerSpace) {
    const elements = createBtnGroupArea('batch-action-area', '出欠簿一括作成', this.handleCreateData, {
      btnElId: 'batch-btn',
      yearElId: 'batch-year',
      monthElId: 'batch-month',
      dateElId: 'batch-date',
      defaultThisMonth: true,
    })
    if (!elements) {
      return;
    }
    headerSpace.appendChild(elements['batch-action-area']);
  }

  handleCreateData = async (e, { year, month, date }) => {
    loading(true, '出欠簿一括作成中...');
    showError(false);
    const api = new KintoneRestAPIClient();

    // 園児台帳アプリからデータを読み取る
    const masterRecords = await this.getMasterRecords(api);
    if (!masterRecords) {
      // エラー
      loading(false);
      return;
    }

    const today = new Date(year, month - 1, date);
    const todayString = getFormatDateString(today);
    const records = this.generateRecords(today, todayString, masterRecords);
    // console.log(records);

    const result = await this.createData(api, records, todayString);
    // showSuccess(true, "出欠簿一括作成完了");
    if (result) {
      this.showSuccessDialog(result);
    }

    loading(false);
  }

  showSuccessDialog(result) {
    const contentEl = document.createElement('div');
    contentEl.style.fontSize = '16px';
    if (result.updateResult && result.insertResult) {
      contentEl.innerHTML = `${result.insertResult.records.length}件のデータを更新し、${result.insertResult.records.length}件のデータを新規作成しました。`
    } else if (result.updateResult) {
      contentEl.innerHTML = `${result.updateResult.records.length}件のデータを更新しました。`;
    } else if (result.insertResult) {
      contentEl.innerHTML = `${result.insertResult.records.length}件のデータを生成しました。`;
    } else {
      contentEl.innerHTML = `データの更新はありません。既に最新の状態です。`
    }

    showDialog({
      title: '出欠簿一括作成完了',
      content: contentEl,
      ok: '更新して確認',
      cancel: false,
      onClose: () => { location.reload() }
    });
  }

  generateRecords = (today, todayString, masterRecords) => {
    return masterRecords.reduce((acc, masterRecord) => {
      if (this.needCreateData(masterRecord, today)) {
        acc.push(this.createRecord(masterRecord, todayString));
      }
      return acc;
    }, []);
  }

  needCreateData = (record, today) => {
    // 当日の日付が、退園年月日（「年_退園年月日」「月_退園年月日」「日_退園年月日」を参照）より前の値
    // ※同日の場合は取得条件に合致とする（取得する）、退園年月日に値が入っていない場合は無条件に取得
    const era = record["和暦_退園年月日"].value;
    const lastYear = record["年_退園年月日"].value;
    const lastMonth = record["月_退園年月日"].value;
    const lastDate = record["日_退園年月日"].value;
    if (!era || !lastYear || !lastMonth || !lastDate) {
      return true;
    }
    const todayObj = new Date(today);
    todayObj.setHours(0, 0, 0, 0);
    const lastDateObj = new Date(convertToWesternYear(Number(lastYear), era), Number(lastMonth) - 1, Number(lastDate));
    lastDateObj.setHours(0, 0, 0, 0);
    return todayObj.getTime() <= lastDateObj.getTime();
  }

  createRecord = (record, todayString) => {
    return {
      '登園日': { 'value': todayString },
      '園児ユニークキー': { 'value': record['ユニークキー'].value },
      '担任': { 'value': record['担当者名'].value.map((x)=>x.name).join('、') },
      '保護者ログインID': { 'value': record['保護者ログインID'].value },
    }
  }

  getMasterRecords = async (api) => {
    try {
      return await api.record.getAllRecordsWithId({
        app: env["園児台帳"].appId,
        fields: ['ユニークキー', '担当者名', "保護者ログインID", "和暦_退園年月日", "年_退園年月日", "月_退園年月日", "日_退園年月日"],
      });
    } catch (e) {
      showError(true, '園児台帳アプリのデータ読み取りエラー\n - ' + e);
    }
  }

  createData = async (api, records, todayString) => {
    try {
      const alreadyGeneratedKeys = await this.getAlreadyGeneratedKeys(api, records, todayString);
      // console.log(alreadyGeneratedKeys);
      if (!alreadyGeneratedKeys) {
        // エラー
        return;
      }

      const param = {
        app: env["園児別出欠簿入力"].appId,
      }

      const insert = [];
      const update = [];
      records.forEach(record => {
        const id = alreadyGeneratedKeys[record["園児ユニークキー"].value]
        if (id) {
          update.push({
            id,
            record
          });
        } else {
          insert.push(record);
        }
      });

      let insertResult;
      if (insert.length) {
        param.records = insert;
        insertResult = await api.record.addAllRecords(param);
      }

      let updateResult;
      if (update.length) {
        param.records = update;
        // 本アプリの当日データでテーブルを上書きし、対応する園児データがない行を【削除】します
        updateResult = await api.record.updateAllRecords(param);
      }
      return {
        insertResult,
        updateResult
      }
    } catch (e) {
      showError(true, '本アプリのデータ作成失敗\n - ' + e);
    }
  };

  getAlreadyGeneratedKeys = async (api, records, todayString) => {
    try {
      const needCreateUniqueKeys = records.map((each) => `"${each["園児ユニークキー"].value}"`).join(',')
      const alreadyGeneratedResult = await api.record.getAllRecordsWithId({
        app: env["園児別出欠簿入力"].appId,
        fields: ["園児ユニークキー"],
        condition: `登園日 = "${todayString}" and 園児ユニークキー in (${needCreateUniqueKeys})`
      })
      return alreadyGeneratedResult.reduce((map, each) => {
        map[each["園児ユニークキー"].value] = each["$id"].value;
        return map;
      }, {});
    } catch (e) {
      showError(true, '本アプリのデータ読み取りエラー\n - ' + e);
    }
  }

  static getInstance(env, headerSpace) {
    if (!BatchCreateHandler.instance) {
      BatchCreateHandler.instance = new BatchCreateHandler(env, headerSpace);
    }
    return BatchCreateHandler.instance;
  }
}
