class Link2Handler {

  constructor(headerSpace) {
    const elements = createBtnGroupArea('link-2-action-area', '2歳以上日誌データ連携', this.handleLink, {
      btnElId: 'link-2-btn',
      yearElId: 'link-2-year',
      monthElId: 'link-2-month',
      dateElId: 'link-2-date',
      defaultThisMonth: true,
    })
    if (!elements) {
      return;
    }
    headerSpace.appendChild(elements['link-2-action-area']);
  }


  handleLink = async (e, { year, month, date }) => {
    loading(true, '日誌データ連携中...');
    showError(false);
    const api = new KintoneRestAPIClient();

    const dateString = getFormatDateString(year, month, date)
    // 本アプリからデータを読み取る
    const currentAppRecords = await this.getRecords(api, dateString);
    if (!currentAppRecords) {
      // エラー
      loading(false);
      return;
    }

    const groupedRecords = this.groupingAndSort(currentAppRecords);

    const records = [];
    for (const item of groupedRecords) {
      records.push(this.generateRecord(dateString, item));
    }

    const result = await this.insertOrUpdateData(api, records, dateString);
    if (result) {
      // showSuccess(true, "日誌データ連携作成完了");
      this.showSuccessDialog(result, year, month, date);
    }
    loading(false);
  }

  showSuccessDialog(result, year, month, date) {
    const dateString = year + '年' + month + '月' + date + '日';
    const contentEl = document.createElement('div');
    contentEl.style.fontSize = '16px';
    if (!result.size) {
      contentEl.innerHTML = `${dateString}の園児別テーブルに追加するデータはありませんでした。`;
    } else if (!result.insert) {
      contentEl.innerHTML = `${dateString}の園児別テーブルに${result.size}件のデータを再作成しました。`;
    } else if (!result.update) {
      contentEl.innerHTML = `${dateString}の日誌は生成しましたが、園児別テーブルに${result.size}件のデータを追加しました。`;
    } else {
      contentEl.innerHTML = `${dateString}の${result.update}人の園児の日誌を更新し、${result.insert}人の園児の日誌を新規作成しました。`
    }
    showDialog({
      title: '日誌データ連携作成完了',
      content: contentEl,
      ok: 'アプリへ行く',
      cancel: '閉じる',
      dataHolder: result,
      onOk: () => { window.open(`${location.origin}/k/${env["2歳以上日誌出力用"].appId}/`) },
    });
  }

  getRecords = async (api, dateString) => {
    try {
      return await api.record.getAllRecordsWithId({
        app: env["園児別出欠簿入力"].appId,
        fields: ['クラス', '学年', "園児名", "園での様子_伝達事項", "評価反省"],
        condition: `学年 not in ("", "０歳児", "１歳児") and 登園日 = "${dateString}"`
      });
    } catch (e) {
      showError(true, '本アプリのデータ読み取りエラー\n - ' + e);
      loading(false);
    }
  }

  groupingAndSort = (data) => {
    const groupedByGrade = {};
    // 1. group by 学年
    data.forEach((record) => {
      const grade = record['学年'].value;
      if (!groupedByGrade[grade]) {
        groupedByGrade[grade] = [];
      }
      groupedByGrade[grade].push(record);
    });

    // 2. sort by クラス
    const classOrder = {};
    classItems.forEach((item, index) => {
      classOrder[item.value] = index;
    });
    for (const grade in groupedByGrade) {
      groupedByGrade[grade].sort((a, b) => {
        return classOrder[a["クラス"].value] - classOrder[b["クラス"].value];
      });
    }

    // 3. return a list
    return termItems.reduce((acc, term) => {
      const grade = term.value;
      // Skip ０歳児 and １歳児
      if (grade === "０歳児" || grade === "１歳児") {
        return acc;
      }
      acc.push({
        grade: grade,
        items: groupedByGrade[grade] || []
      });
      return acc;
    }, []);
  }

  generateRecord = (todayString, groupedRecords) => {
    return {
      '登園日': { 'value': todayString },
      '学年': { 'value': groupedRecords.grade },
      '園児別テーブル': {
        'value': groupedRecords.items.map((record) => {
          return {
            'value': {
              'クラス名': { 'value': record['クラス'].value },
              '名前': { 'value': record['園児名'].value },
              '子どもの様子': { 'value': record['園での様子_伝達事項'].value },
              '反省評価_園児別テーブル': { 'value': record['評価反省'].value },
            }
          }
        })
      }
    };
  }

  insertOrUpdateData = async (api, records, dateString) => {
    const results = [];
    const generatedRecords = await api.record.getAllRecordsWithId({
      app: env["2歳以上日誌出力用"].appId,
      fields: ["$id", "学年"],
      condition: `登園日 = "${dateString}"`
    })
    const existIdMap = generatedRecords.reduce((map, item) => {
      const grade = item['学年'].value;
      const id = item['$id'].value;
      map[grade] = id;
      return map;
    }, {});

    for (const record of records) {
      try {
        const generatedRecordId = existIdMap[record["学年"].value];
        const param = {
          app: env["2歳以上日誌出力用"].appId,
          record
        }
        const result = {
          id: generatedRecordId,
          type: generatedRecordId ? 'update' : 'insert',
          size: record["園児別テーブル"].value.length,
        };

        let awaitResult;

        if (result.type === 'update') {
          param.id = generatedRecordId;
          // 本アプリの当日データでテーブルを上書きし、対応する園児データがない行を【削除】します
          awaitResult = await api.record.updateRecord(param);
        } else {
          awaitResult = await api.record.addRecord(param);
        }
        Object.assign(result, awaitResult);
        results.push(result);
      } catch (e) {
        showError(true, '日誌データ連携作成失敗\n - ' + e);
      }
    }

    return results.reduce((result, item) => {
      // Sum all sizes
      result.size += item.size;

      // Sum based on type
      if (item.type === 'insert') {
        result.insert += item.size;
      } else if (item.type === 'update') {
        result.update += item.size;
      }

      return result;
    }, {
      size: 0,     // Total sum of all sizes
      insert: 0,   // Sum of insert sizes
      update: 0    // Sum of update sizes
    });;
  };

  static getInstance(headerSpace) {
    if (!Link2Handler.instance) {
      Link2Handler.instance = new Link2Handler(headerSpace);
    }
    return Link2Handler.instance;
  }
}
