// cookieManager内部メッセージ定数
const MSG_SESSION_ERROR = 'セッションエラーが発生しました。';
const MSG_NOT_APP_ERROR = 'アプリ以外からアクセスされています。';

/**
 * cookieManager
 * クッキー操作の共通クラス
 */
const cookieManager = (function() {

  // セッションIDクッキー名称リスト
  const COOKIE_SESSION_NAMES = Object.freeze({
      apiSid: 'api_sid',          // セッションAPI
      mypageSid: 'mypage_sid',    // マイページ画面ID(アクセストークン：マイページログイン時に生成、保存)
      mypageSidNext: 'mypagef_sid',  // マイページ画面ID 次の画面判定用(リフレッシュトークン：マイページログイン時に生成、保存)
  });
  // クッキー名称リスト
  const COOKIE_NAMES = Object.freeze({
      xuid: 'admage_adplus_xuid', // 広告ID
      agentCode: 'agent_code',    // 販売店コード
      auid: 'auid',               // AUIDのログイン状態（AUIDでログインしたか）
      code: 'code',               // AUログイン認証要求で取得した「code」の値
      kbi: 'kbi',                 // KBIのログイン状態（KBIでログインしたか）
      plan: 'plan',               // UQMobileのプラン情報
      poikatsu: 'poikatsu',       // ポイ活情報
      requestPay: 'request_pay',  // 課金導線
      serviceId: 'service_id',    // サービスID
      snsToken: 'sns_token',      // SNSのトークン
      snsType: 'sns_type',        // SNSの種別
      state: 'state',             // SNSのログイン情報
      token: 'token',               // 仮登録メール内URLに付与されるtoken
      userInfoKey: 'user_info_key', // ICCID・TEL・サービスID・商品IDを保持しているKVSのkey
      inApp: "inApp"              , // アプリ導線フラグ（true）
  });

  /**
   * 属性付きクッキーを設定する
   * @param {string} name - クッキー名
   * @param {string|Object} value - クッキーに保存する値。単一の文字列またはオブジェクト
   * @param {Object} options - クッキーの属性情報。オブジェクト
   */
  function setCookieWithOption(name, value, options) {
    var cookieValue;
    var setOptions = '';
    var defaultOptions = ';secure=true;sameSite=None;'
    if (typeof value === 'object') {
    // オブジェクトの場合はJSON形式で保存
      cookieValue = encodeURIComponent(JSON.stringify(value));
    } else {
    // 文字列の場合はそのまま保存
      cookieValue = encodeURIComponent(value);
    }
    if (typeof options === 'object') {
      const optionPath = options.path  ? ';path=' + options.path : '';
      const optionDomain = options.domain  ? ';domain=' + options.domain : '';
      const optionExpires = options.expires  ? ';expires=' + options.expires.toUTCString() : '';
      setOptions = optionPath + optionDomain + optionExpires;
    }
    // セッションクッキーとして保存
    document.cookie = name + '=' + cookieValue + setOptions + defaultOptions;
  }

  /**
   * クッキーを取得する
   * @param {string} name - 取得したいクッキー名
   * @return {string|Object|null} - クッキーの値。JSON形式の場合はオブジェクト、単一の値は文字列、クッキーが存在しない場合はnull
   */
  function getCookie(name) {
    var nameWithEquals = name + '=';
    var cookies = document.cookie.split(';'); // クッキーをセミコロンで分割

    for (var i = 0; i < cookies.length; i++) {
      var cookie = cookies[i].trim(); // 前後の空白をトリム

      // 指定したクッキー名が見つかった場合
      if (cookie.indexOf(nameWithEquals) === 0) {
        var cookieValue = cookie.substring(nameWithEquals.length); // クッキーの値部分を取得

        // JSON形式かどうかを確認し、パースできればオブジェクトとして返す
        try {
          return JSON.parse(decodeURIComponent(cookieValue));
        } catch (e) {
          // JSONパースが失敗した場合は、単一の文字列値として返す
          return decodeURIComponent(cookieValue);
        }
      }
    }
    return null; // クッキーが見つからなかった場合
  }

  /**
   * クッキー内の特定のプロパティを取得する
   * @param {string} cookieName - クッキー名
   * @param {string} key - 取得したいプロパティのキー名
   * @return {string|null} - 指定されたプロパティの値、存在しない場合はnull
   */
  function getCookieValueByKey(cookieName, key) {
    var cookieObject = getCookie(cookieName);
    if (cookieObject && Object.prototype.hasOwnProperty.call(cookieObject, key)) {
      return cookieObject[key];
    }
    return null;
  }

  /**
   * クッキーを削除する
   *
   */
  function deleteCookie(name) {
    document.cookie =  name + '=;max-age=0';
  }

  return {
    /**
     * APIセッションID取得
     * @return {string|null} - APIセッションID
     */
    getApiSid: function() {
      return getCookie(COOKIE_SESSION_NAMES.apiSid);
    },

    /**
     * マイページセッションID取得
     * @return {string|null} - マイページセッションID
     */
    getMypageSid: function() {
      return getCookie(COOKIE_SESSION_NAMES.mypageSid);
    },

    /**
     * マイページセッションID(リフレッシュ)取得
     * @return {string|null} - マイページセッションID(リフレッシュ)
     */
    getMypageSidNext: function() {
      return getCookie(COOKIE_SESSION_NAMES.mypageSidNext);
    },

    /**
     * 広告ID取得
     * @return {string|null} - 広告ID
     */
    getXuId: function() {
      return getCookie(COOKIE_NAMES.xuid);
    },

    /**
     * 販売店コード取得
     * @return {string|null} - 販売店コード
     */
    getAgentCode: function() {
      return getCookie(COOKIE_NAMES.agentCode);
    },

    /**
     * AUIDのログイン状態取得
     * @return {string|null} - AUIDのログイン状態(true または null)
     */
    getAuid: function() {
      return getCookie(COOKIE_NAMES.auid);
    },

    /**
     * AUログイン認証要求で取得したCODEを取得
     * @return {string|null} - AUログイン認証要求で取得したCODE
     */
    getCode: function() {
      return getCookie(COOKIE_NAMES.code);
    },

    /**
     * KBIのログイン状態取得
     * @return {string|null} - KBIのログイン状態(true または null)
     */
    getKbi: function() {
      return getCookie(COOKIE_NAMES.kbi);
    },

    /**
     * UQMobileのプラン情報取得
     * @return {string|null} - UQMobileのプラン情報
     */
    getPlan: function() {
      return getCookie(COOKIE_NAMES.plan);
    },

    /**
     * ポイ活情報取得
     * @return {string|null} - ポイ活情報(
     *                           appLoginMission：auWiFiアクセスアプリ起動ミッション完了日
     *                           poikatsuLoginMission：ポイ活ログインミッション完了日
     *                           expireDays：有効期限日数)
     */
    getPoikatsu: function() {
      return getCookie(COOKIE_NAMES.poikatsu);
    },

    /**
     * 課金導線取得
     * @return {string|null} - 課金導線
     */
    getRequestPay: function() {
      return getCookie(COOKIE_NAMES.requestPay);
    },

    /**
     * サービスID取得
     * @return {string|null} - サービスID
     */
    getServiceId: function() {
      return getCookie(COOKIE_NAMES.serviceId);
    },

    /**
     * SNSのトークン取得
     * @return {string|null} - SNSのトークン
     */
    getSnsToken: function() {
      return getCookie(COOKIE_NAMES.snsToken);
    },

    /**
     * SNSの種別取得
     * @return {string|null} - SNSの種別
     */
    getSnsType: function() {
      return getCookie(COOKIE_NAMES.snsType);
    },

    /**
     * SNSのログイン情報取得
     * @return {string|null} - SNSのログイン情報
     */
    getState: function() {
      return getCookie(COOKIE_NAMES.state);
    },

    /**
     * 仮登録メール内URLに付与されるtoken取得
     * @return {string|null} - 仮登録メール内URLに付与されるtoken
     */
    getToken: function() {
      return getCookie(COOKIE_NAMES.token);
    },

    /**
     * ICCID・TEL・サービスID・商品IDを保持しているKVSのkey取得
     * @return {string|null} - ICCID・TEL・サービスID・商品IDを保持しているKVSのkey
     */
    getUserInfoKey: function() {
      return getCookie(COOKIE_NAMES.userInfoKey);
    },

    /**
     * クッキーにAPIセッションIDを設定
     * @param {string} apiSid - APIセッションID
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setApiSid: function(apiSid, options) {
      return setCookieWithOption(COOKIE_SESSION_NAMES.apiSid, apiSid, options);
    },

    /**
     * クッキーにマイページセッションID(アクセストークン)を設定
     * @param {string} mypageSid - マイページセッションID
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setMypageSid: function(mypageSid, options) {
      return setCookieWithOption(COOKIE_SESSION_NAMES.mypageSid, mypageSid, options);
    },

    /**
     * クッキーにマイページセッションID(リフレッシュトークン)を設定
     * @param {string} mypageSidNext - マイページセッションID
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setMypageSidNext: function(mypageSidNext, options) {
      return setCookieWithOption(COOKIE_SESSION_NAMES.mypageSidNext, mypageSidNext, options);
    },

    /**
     * クッキーに広告IDを設定
     * @param {string} xuid - 広告ID
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setXuId: function(xuid, options) {
      return setCookieWithOption(COOKIE_NAMES.xuid, xuid, options);
    },

    /**
     * クッキーにAUIDのログイン状態を設定
     * @param {string} auid - AUIDのログイン状態
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setAuid: function(auid, options) {
      return setCookieWithOption(COOKIE_NAMES.auid, auid, options);
    },

    /**
     * クッキーにKBIのログイン状態を設定
     * @param {string} kbi - KBIのログイン状態
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setKbi: function(kbi, options) {
      return setCookieWithOption(COOKIE_NAMES.kbi, kbi, options);
    },

    /**
     * クッキーに課金導線を設定
     * @param {string} requestPay - 課金導線
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setRequestPay: function(requestPay, options) {
      return setCookieWithOption(COOKIE_NAMES.requestPay, requestPay, options);
    },

    /**
     * クッキーに販売店コードを設定
     * @param {string} agentCode - 販売店コード
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setAgentCode: function(agentCode, options) {
      return setCookieWithOption(COOKIE_NAMES.agentCode, agentCode, options);
    },

    /**
     * クッキーにICCID・TEL・サービスID・商品IDを保持しているKVSのkeyを設定
     * @param {string} userInfoKey - ICCID・TEL・サービスID・商品IDを保持しているKVSのkey
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setUserInfoKey: function(userInfoKey, options) {
      return setCookieWithOption(COOKIE_NAMES.userInfoKey, userInfoKey, options);
    },

    /**
     * クッキーにSNSの種別を設定
     * @param {string} snsType - SNSの種別
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setSnsType: function(snsType, options) {
      return setCookieWithOption(COOKIE_NAMES.snsType, snsType, options);
    },

    /**
     * クッキーにSNSのトークンを設定
     * @param {string} snsToken - SNSのトークン
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setSnsToken: function(snsToken, options) {
      return setCookieWithOption(COOKIE_NAMES.snsToken, snsToken, options);
    },

    /**
     * クッキーにサービスIDを設定
     * @param {string} serviceId - サービスID
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setServiceId: function(serviceId, options) {
      return setCookieWithOption(COOKIE_NAMES.serviceId, serviceId, options);
    },

    /**
     * クッキーに仮登録メール内URLに付与されるtokenを設定
     * @param {string} token - 仮登録メール内URLに付与されるtoken
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setToken: function(token, options) {
      return setCookieWithOption(COOKIE_NAMES.token, token, options);
    },

    /**
     * クッキーにUQMobileのプラン情報を設定
     * @param {string} plan - UQMobileのプラン情報
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setPlan: function(plan, options) {
      return setCookieWithOption(COOKIE_NAMES.plan, plan, options);
    },

    /**
     * クッキーにSNSのログイン情報を設定
     * @param {string} state - SNSのログイン情報
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setState: function(state, options) {
      return setCookieWithOption(COOKIE_NAMES.state, state, options);
    },

    /**
     * クッキーにAUログイン認証要求で取得した「code」の値を設定
     * @param {string} code - AUログイン認証要求で取得した「code」の値
     * @param {Object} options - クッキーの属性情報。オブジェクト{path,domain,expires}
     */
    setCode: function(code, options) {
      return setCookieWithOption(COOKIE_NAMES.code, code, options);
    },

    /**
     * ポイ活クッキーのauWiFiアクセスアプリ起動ミッション完了日取得
     * @return {string|null} - アプリログインミッション
     */
    getAppLoginMission: function() {
      return getCookieValueByKey(COOKIE_NAMES.poikatsu, 'appLoginMission');
    },

    /**
     * ポイ活クッキーのポイ活ログインミッション完了日取得
     * @return {string|null} - ポイ活ログインミッション完了日
     */
    getPoikatsuLoginMission: function() {
      return getCookieValueByKey(COOKIE_NAMES.poikatsu, 'poikatsuLoginMission');
    },

    /**
     * ポイ活クッキーの有効期限日数取得
     * @return {string|null} - 有効期限日数
     */
    getExpireDays: function() {
      return getCookieValueByKey(COOKIE_NAMES.poikatsu, 'expireDays');
    },

    /**
     * アプリ導線フラグ取得
     * @return {string|null} - アプリ導線フラグ
     */
    getInApp: function() {
      return getCookie(COOKIE_NAMES.inApp);
    },

    /**
     * クッキーに複数の値を設定・更新する
     * @param {Object} newValues - 新しく追加したい値（オブジェクト形式）
     */
    setPoikatsuCookie: function(newValues) {
      // 既存のクッキーを取得（クッキーがない場合は空オブジェクト）
      var existingCookie = getCookie(COOKIE_NAMES.poikatsu);
      var cookieObject = existingCookie ? existingCookie : {};
      // 新しい値を既存のクッキーオブジェクトに追加または更新
      for (var key in newValues) {
        if (Object.prototype.hasOwnProperty.call(newValues, key)) {
          cookieObject[key] = newValues[key];
        }
      }
      // 更新されたクッキーオブジェクトをJSON形式で保存
      setCookieWithOption(COOKIE_NAMES.poikatsu, cookieObject, {path: '/poikatsu'});
    },

    /**
     * マイページ画面ID(アクセストークン)クッキーを削除する
     */
    deleteMypageSidCookie: function() {
      deleteCookie(COOKIE_SESSION_NAMES.mypageSid);
    },

    /**
     * マイページ画面ID(リフレッシュトークン)クッキーを削除する
     */
    deleteMypageSidNextCookie: function() {
      deleteCookie(COOKIE_SESSION_NAMES.mypageSidNext);
    },

    /**
     * アプリ導線フラグクッキーを削除する
     */
    deleteInAppCookie: function() {
      deleteCookie(COOKIE_NAMES.inApp);
    },

    /**
     * セッションAPIクッキーを削除する
     */
    deleteApiSidCookie: function() {
      deleteCookie(COOKIE_SESSION_NAMES.apiSid);
    },

    /**
      * 販売店コードクッキーを削除する
      */
    deleteAgentCodeCookie: function() {
      deleteCookie(COOKIE_NAMES.agentCode);
    },

    /**
     * 課金導線クッキーを削除する
     */
    deleteRequestPayCookie: function() {
      deleteCookie(COOKIE_NAMES.requestPay);
    },

    /**
     * AUIDのログイン状態クッキーを削除する
     */
    deleteAuidCookie: function() {
      deleteCookie(COOKIE_NAMES.auid);
    },

    /**
     * KBIのログイン状態クッキーを削除する
     */
    deleteKbiCookie: function() {
      deleteCookie(COOKIE_NAMES.kbi);
    },

    /**
     * SNSトークンクッキーを削除する
     */
    deleteSnsTokenCookie: function() {
      deleteCookie(COOKIE_NAMES.snsToken);
    },

    /**
     * SNS種別クッキーを削除する
     */
    deleteSnsTypeCookie: function() {
      deleteCookie(COOKIE_NAMES.snsType);
    },

    /**
     * ICCID・TEL・サービスID・商品IDを保持しているKVSのkeyクッキーを削除する
     */
    deleteUserInfoKeyCookie: function() {
      deleteCookie(COOKIE_NAMES.userInfoKey);
    },

    /**
     * ポイ活クッキーを削除する
     */
    deletePoikatsuCookie: function() {
      deleteCookie(COOKIE_NAMES.poikatsu);
    },

    /**
     * すべてのクッキーを削除する
     */
    deleteAllCookies: function() {
      const cookies = document.cookie;
      const array = cookies.split(';');
      array.forEach(function(value) {
        const content = value.split('=');
        deleteCookie(content[0]);
      });
    },

    /**
     * アプリ導線フラグを判定する
     * @return {boolean} - アプリ導線の場合はtrue、そうでない場合はfalse
     */
    isInApp: function() {
      return true === this.getInApp();
    },

    /**
     * AUIDログイン状態フラグを判定する
     * @return {boolean} - AUIDログインの場合はtrue、そうでない場合はfalse
     */
    isAuid: function() {
      return true === this.getAuid();
    },

    /**
     * KBIログイン状態フラグを判定する
     * @return {boolean} - KBIログインの場合はtrue、そうでない場合はfalse
     */
    isKbi: function() {
      return true === this.getKbi();
    },

    /**
     * マイページ画面ID(アクセストークン)を取得する。
     * 存在しない場合はエラー画面へリダイレクト
     * @return {string} - マイページ画面ID(アクセストークン)
     */
    checkMypageSid: function() {
      let sid = this.getMypageSid();
      if (sid === null) {
        this.deleteAllCookies();
        document.location.href = "error?c=8000";
        return null;
      }
      return sid;
    },

  };
})();
