/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JCKSV900101CC
*   ソースファイル名：JCKSV900101CC.java
*   作成者          ：富士通
*   日付            ：2011年07月01日
*＜機能概要＞
*   AxMに対して会員情報更新依頼を行います。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*   v1.00.00    2011/07/01   FJ）眞方    新規作成
*   v5.00.00    2013/03/14   FJ）関      【IT1-2013-0000483】シスログ出力条件を修正
*
**********************************************************************/

package com.fujitsu.futurity.bp.custom.common;

import static com.fujitsu.futurity.bp.custom.common.JCKPmpCommonUtil.*;
import static com.fujitsu.futurity.bp.custom.common.JCKPmpScParamHenshu.getResultMsgList;
import static com.fujitsu.futurity.bp.custom.common.JCKPmpScParamHenshu.isSuccess;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fujitsu.futurity.bp.custom.constant.CKSV9001_CKSV9001OP_CKSV900101CC;
import com.fujitsu.futurity.bp.x21.bpm.db.SessionHandle;
import com.fujitsu.futurity.bp.x21.bpm.parameter.IRequestParameterReadWrite;
import com.fujitsu.futurity.bp.x21.cc.AbstractCommonComponent;
import com.fujitsu.futurity.bp.x21.cc.ICommonComponent;
import com.fujitsu.futurity.common.JCCSuperComExecUtil;
import com.fujitsu.futurity.common.JCCSyslogFormat;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.common.JCMAPLConstMgr;

import eo.ejb.cbs.cbsmsg.ECK0151B020CBSMsg;
import eo.ejb.cbs.cbsmsg.ECK0151B020CBSMsg1List;
import eo.ejb.cbs.cbsmsg.ECK0151C010CBSMsg;
import eo.ejb.cbs.cbsmsg.ECK0151E010CBSMsg;
import eo.ejb.cbs.cbsmsg.ECKA9010001CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081B523CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK0081B523CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EZM0321A010CBSMsg;
import eo.ejb.cbs.cbsmsg.EZM0321A010CBSMsg1List;

/**
 * AxMに対して会員情報更新依頼を行う。
 * <BR>
 * @ author 富士通
 */
public class JCKSV900101CC extends AbstractCommonComponent implements ICommonComponent
{
	/**
	 * 共通コンポーネント実行。<br />
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return リクエストパラメータ
	 * @throws Throwable
	 */
	@SuppressWarnings("unchecked")
	public IRequestParameterReadWrite executeMain(SessionHandle handle, IRequestParameterReadWrite param, String fixedText) throws Throwable
	{
		// エラーフラグ(実行判定用)
		String errFlgCc = "0";

		// 入力パラメータの取得
		Map inMap = (Map)param.getData(fixedText);
		String trnCd   = (String)inMap.get(CKSV9001_CKSV9001OP_CKSV900101CC.TRN_CD);
		String tableId = (String)inMap.get(CKSV9001_CKSV9001OP_CKSV900101CC.TRGT_TABLE_ID);
		String sysid   = (String)inMap.get(CKSV9001_CKSV9001OP_CKSV900101CC.UPD_TRGT_SYSID);

		/**
		 * 最大指示書更新件数の取得
		 */
		Integer maxCnt = null;
		Map<?, ?> result = callEZM0321A010(handle, param, "CK_MAX_UPD_CNT");
		String maxCntStr = null;
		if (JCKPmpScParamHenshu.isSuccess(result))
		{
			String keyPre = EZM0321A010CBSMsg.EZM0321A010CBSMSG1LIST + "[0].";
			maxCntStr = JCKPmpScParamHenshu.getResultString(result, keyPre + EZM0321A010CBSMsg1List.WORK_PARAM_SETTE_VALUE);
			if ((maxCntStr != null)&&(!"".equals(maxCntStr)))
			{
				try
				{
					maxCnt = Integer.parseInt(maxCntStr);
				}
				catch (Exception e)
				{
					errFlgCc = "1";
					printErrorLog("業務パラメータから取得した最大指示書更新件数が数値ではありません。(取得値：" + maxCntStr + ")");
				}
			}
			else
			{
				errFlgCc = "1";
				printErrorLog("業務パラメータから最大指示書更新件数が取得できません。(パラメータID:CK_MAX_UPD_CNT)");
			}
		}

		/**
		 * 最大エラー回数の取得
		 */
		String maxErrCnt = null;
		int maxErrCntInt = 0;
		if ("0".equals(errFlgCc))
		{
			result = callEZM0321A010(handle, param, "CK_SJISHO_MAXERR_CNT");
			if (JCKPmpScParamHenshu.isSuccess(result))
			{
				String keyPre = EZM0321A010CBSMsg.EZM0321A010CBSMSG1LIST + "[0].";
				maxErrCnt = JCKPmpScParamHenshu.getResultString(result, keyPre + EZM0321A010CBSMsg1List.WORK_PARAM_SETTE_VALUE);
				if ((maxErrCnt != null)&&(!"".equals(maxErrCnt)))
				{
					try
					{
						// 数値チェック用
						maxErrCntInt = Integer.parseInt(maxErrCnt);
					}
					catch (Exception e)
					{
						errFlgCc = "1";
						printErrorLog("業務パラメータから取得した指示書最大エラー回数が数値ではありません。(取得値：" + maxErrCnt + ")");
					}
				}
				else
				{
					errFlgCc = "1";
					printErrorLog("業務パラメータから指示書最大エラー回数が取得できません。(パラメータID:CK_MAX_ERR_CNT)");
				}
			}
		}

		/**
		 * 指示書データの読込
		 */
		if ("0".equals(errFlgCc))
		{
			result = callECK0151B020(handle, param, trnCd, tableId, sysid, null, maxErrCnt);
			if (!JCKPmpScParamHenshu.isSuccess(result))
			{
				errFlgCc = "1";
				printErrorLog("指示書データの読込に失敗しました。");

			}
		}

		List<String> errSysidList = new ArrayList<String>();

		/**
		 * 会員情報更新依頼
		 */
		if ("0".equals(errFlgCc))
		{
			String preSysId = "";
			int updCnt = 0;
			
			CAANMsg[] templateArray = JCKPmpScParamHenshu.getResultMsgList(result, ECK0151B020CBSMsg.ECK0151B020CBSMSG1LIST);
			for (int i = 0; i < templateArray.length; i++)
			{
				
				// 指示書情報取得
				CAANMsg shijishoRec = templateArray[i];
				String nowSysId        = shijishoRec.getString(ECK0151B020CBSMsg1List.TRAN_TRGT_SYSID);
				String sjishoNo        = shijishoRec.getString(ECK0151B020CBSMsg1List.SJISHO_NO);
				String sjishoNaiyioSeq = shijishoRec.getString(ECK0151B020CBSMsg1List.SJISHO_NAIYO_SEQ);
				String trgtTableId = shijishoRec.getString(ECK0151B020CBSMsg1List.TRGT_TABLE_ID);
				String updDtmBf = shijishoRec.getString(ECK0151B020CBSMsg1List.UPD_DTM);
				String recTrnCd = shijishoRec.getString(ECK0151B020CBSMsg1List.TRN_CD);
				String parameter2 = shijishoRec.getString(ECK0151B020CBSMsg1List.PARAMETER_2);

				// Maxエラー回数を超えたSYSIDの場合はスキップ
				if (errSysidList.contains(nowSysId)){
					continue;
				}

				// 最大指示書更新件数(SYSID毎の最大更新件数)を超えた場合はスキップ
				if (preSysId.equals(nowSysId))
				{
					updCnt += 1;
					if (maxCnt < updCnt)
					{
						continue;
					}
				}
				else
				{
					preSysId = nowSysId;
					updCnt = 1;
				}

				// 認証ID連携の時はサービス契約コード通番を取得
				if("N01".equals(recTrnCd)
					&& ("TNM00050".equals(trgtTableId) || "TNM00050_D".equals(trgtTableId))
					&& "05".equals(parameter2))
				{
					String svcKeiNo = shijishoRec.getString(ECK0151B020CBSMsg1List.PARAMETER_1);
					String ninshoId = shijishoRec.getString(ECK0151B020CBSMsg1List.PARAMETER_4);

					// サービス契約番号に紐付くISP認証ID、ADSL認証IDを全て取得する。
					result = callEKK0081B523BySvcKeiNo(handle, param, "3", svcKeiNo);
					if (isSuccess(result))
					{
						CAANMsg[] dataList = getResultMsgList(result, EKK0081B523CBSMsg.EKK0081B523CBSMSG1LIST);

						if (dataList != null && dataList.length > 0)
						{
							int seq = 0;
							String bfSvcKeiUcwkNo = "";

							// 指示書に登録された認証IDと同じものがあれば、通番をセットする。
							for (int j = 0; j < dataList.length; j++)
							{
								CAANMsg rec = dataList[j];

								// サービス契約内訳番号が変われば、通番をカウントアップ
								if (!bfSvcKeiUcwkNo.equals(rec.getString(EKK0081B523CBSMsg1List.SVC_KEI_UCWK_NO)))
								{
									seq++;
								}

								String recNinshoId = rec.getString(EKK0081B523CBSMsg1List.NINSHO_ID);
								if (!JCKBPCommon.isNullOrBlank(recNinshoId) && recNinshoId.equals(ninshoId))
								{
									// 通番をセット
									shijishoRec.set(ECK0151B020CBSMsg1List.PARAMETER_3, String.valueOf(seq));
									break;
								}

								bfSvcKeiUcwkNo = rec.getString(EKK0081B523CBSMsg1List.SVC_KEI_UCWK_NO);
							}
						}
					}
				}

				/**
				 * AxM会員情報更新依頼
				 */
				trgtTableId = (trgtTableId != null) ? trgtTableId.trim() : trgtTableId;
				shijishoRec.set(ECK0151B020CBSMsg1List.TRGT_TABLE_ID, trgtTableId);
				result = callECKA9010001Msg(handle, param, shijishoRec);
				String resErrFlg = JCKPmpScParamHenshu.getResultString(result, ECKA9010001CBSMsg.RES_ERR_FLG);
				if ((JCKPmpScParamHenshu.isSuccess(result))&&("0".equals(resErrFlg)))
				{
					/**
					 * 指示書削除(連携成功時)
					 */
					result = callECK0151E010(handle, param, sjishoNo, sjishoNaiyioSeq, updDtmBf);
				}
				else
				{
					/**
					 * 指示書エラー回数更新(連携失敗時)
					 */
					result = callECK0151C010(handle, param, sjishoNo, sjishoNaiyioSeq);
					errFlgCc = "1";
					if (JCKPmpScParamHenshu.isSuccess(result))
					{
						// エラーが発生したSYSIDとしてリストに追加
						errSysidList.add(nowSysId);
						// 変更後エラー回数を取得
						String chafErrCnt = JCKPmpScParamHenshu.getResultString(result, ECK0151C010CBSMsg.CHAF_ERR_CNT);
						chafErrCnt = JCKBPCommon.isNullOrBlank(chafErrCnt) ? "0" : chafErrCnt;
						// エラー回数がMaxエラー回数を超えていた場合
						if(maxErrCntInt <= Integer.parseInt(chafErrCnt))
						{
							// シスログ出力
							printSyslog4AxmErr(nowSysId);
						}
					}
				}
			}
		}
		else
		{
			errFlgCc = "1";
		}

		/**
		 * 下りマッピング
		 */
		// 下りコントロールマップのセット(指示書のエラー回数更新結果をコミットする必要がある為、常に正常終了を返却する)
		JCKPmpScParamHenshu.setResultCtrlData(param, result, fixedText);

		// 下りユーザデータマップのセット(当CCではエラー有無はユーザ情報のエラーフラグで通知する)
		Map<String, Object> resultMap = new HashMap();
		resultMap.put("err_flg", errFlgCc);
		JCKPmpScParamHenshu.setResultUserData(param, fixedText, resultMap);

		/**
		 * 処理結果の判定
		 */
		// 当CCでは例外Throwは行わない(指示書のエラー回数更新をコミットさせる為)
		//if (!"0".equals(errFlgCc)) {
		//	String errMsg = "会員情報更新依頼CCで例外が発生しました";
		//	throw new CCException(errMsg, new Exception(errMsg));
		//}

		return param;
	}

	/**
	 * 業務パラメータ管理一意照会SC呼出。<br />
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param paramId 業務パラメータID
	 * @return 実行結果
	 * @throws Throwable
	 */
	private Map<?, ?> callEZM0321A010(SessionHandle handle, IRequestParameterReadWrite param, String paramId) throws Throwable
	{
		//***************************************************
		//* ＳＣへの上りマッピング
		//***************************************************
		Map<Object, Object> param4serviceIf = new HashMap<Object, Object>();
		param4serviceIf.put(EZM0321A010CBSMsg.KEY_WORK_PARAM_ID, paramId);
		HashMap<String, Object> paramMap = JCKBPCommon.createScParamForSearch(param, EZM0321A010CBSMsg.class , param4serviceIf, "1");

		//***************************************************
		//* ＳＣ呼出実行
		//***************************************************
		printDebugLog("業務パラメータ管理一意照会SC呼び出し開始（ 業務パラメータID：" + paramId + " ）");
		Map<?, ?> result = JCKPmpCommonUtil.scCallRun(param, handle, paramMap);
		printDebugLog("業務パラメータ管理一意照会SC呼び出し完了" + result);

		return result;
	}

	/**
	 * 指示書データ読込用SC呼出。<br />
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param trnCd 処理コード
	 * @param trgtTableId 対象テーブルID
	 * @param updTrgtSysid 更新対象SYSID
	 * @param rsltFlg 結果フラグ
	 * @param maxErrCnt 最大指示書件数
	 * @return ＳＣ実行結果
	 * @throws Throwable
	 */
	private Map<?, ?> callECK0151B020(SessionHandle handle, IRequestParameterReadWrite param, String trnCd, String trgtTableId, String updTrgtSysid,
			String rsltFlg, String maxErrCnt) throws Throwable
	{
		//***************************************************
		//* ＳＣへの上りマッピング
		//***************************************************
		Map<Object, Object> param4serviceIf = new HashMap<Object, Object>();
		param4serviceIf.put(ECK0151B020CBSMsg.KEY_TRN_CD, trnCd);
		param4serviceIf.put(ECK0151B020CBSMsg.KEY_TRGT_TABLE_ID, trgtTableId);
		param4serviceIf.put(ECK0151B020CBSMsg.KEY_TRAN_TRGT_SYSID, updTrgtSysid);
		param4serviceIf.put(ECK0151B020CBSMsg.KEY_ERR_CNT, maxErrCnt);
		param4serviceIf.put(ECK0151B020CBSMsg.KEY_RSLT_FLG, rsltFlg);
		HashMap<String, Object> paramMap = JCKBPCommon.createScParamForSearch(param, ECK0151B020CBSMsg.class , param4serviceIf, "1");

		//***************************************************
		//* ＳＣ呼出実行
		//***************************************************
		printDebugLog("指示書読込SC呼び出し開始");
		Map<?, ?> result = JCKPmpCommonUtil.scCallRun(param, handle, paramMap);
		printDebugLog("指示書読込SC呼び出し完了" + result);

		return result;
	}

	/**
	 * AxM連携API呼出SC呼出。<br />
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param shijishoRec 指示書レコード
	 * @return ＳＣ実行結果
	 * @throws Throwable
	 */
	private Map<?, ?> callECKA9010001Msg(SessionHandle handle, IRequestParameterReadWrite param, CAANMsg shijishoRec) throws Throwable
	{
		//***************************************************
		//* ＳＣへの上りマッピング
		//***************************************************
		Map<String, Object> userData = JCKPmpScParamHenshu.copyMsgToMap(shijishoRec, ECK0151B020CBSMsg1List.class, ECKA9010001CBSMsg.class);
		HashMap<String, Object> paramMap = JCKBPCommon.createScParam(param, ECKA9010001CBSMsg.class , userData, "1");

		//***************************************************
		//* ＳＣ呼出実行
		//***************************************************
		printDebugLog("AxM連携API呼出SC呼び出し開始");
		Map<?, ?> result = JCKPmpCommonUtil.scCallRun(param, handle, paramMap);
		printDebugLog("AxM連携API呼出SC呼び出し完了" + result);

		return result;
	}

	/**
	 * 指示書削除SC呼出。<br />
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param sjishoNo 指示書番号
	 * @param sjishoNaiyioSeq 指示書内容枝番
	 * @param updDtmBf 更新年月日時分秒(更新前)
	 * @return ＳＣ実行結果
	 * @throws Throwable
	 */
	private Map<?, ?> callECK0151E010(SessionHandle handle, IRequestParameterReadWrite param, String sjishoNo, String sjishoNaiyioSeq, String updDtmBf)
			throws Throwable
	{
		//***************************************************
		//* ＳＣへの上りマッピング
		//***************************************************
		Map<Object, Object> userData = new HashMap<Object, Object>();
		userData.put(ECK0151E010CBSMsg.SJISHO_NO, sjishoNo);
		userData.put(ECK0151E010CBSMsg.SJISHO_NAIYO_SEQ, sjishoNaiyioSeq);
		userData.put(ECK0151E010CBSMsg.UPD_DTM_BF, updDtmBf);
		HashMap<String, Object> paramMap = JCKBPCommon.createScParam(param, ECK0151E010CBSMsg.class , userData, "1");

		//***************************************************
		//* ＳＣ呼出実行
		//***************************************************
		printDebugLog("指示書削除SC呼び出し開始");
		Map<?, ?> result = JCKPmpCommonUtil.scCallRun(param, handle, paramMap);
		printDebugLog("指示書削除SC呼び出し完了" + result);

		return result;
	}

	/**
	 * 指示書エラー回数更新SC呼出。<br />
	 * @param sjishoNo 指示書番号
	 * @param sjishoNaiyioSeq 指示書内容枝番
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @return 実行結果
	 * @throws Throwable
	 */
	private Map<?, ?> callECK0151C010(SessionHandle handle, IRequestParameterReadWrite param, String sjishoNo, String sjishoNaiyioSeq)
			throws Throwable
	{

		//***************************************************
		//* ＳＣへの上りマッピング
		//***************************************************
		Map<Object, Object> userData = new HashMap<Object, Object>();
		userData.put(ECK0151C010CBSMsg.SJISHO_NO, sjishoNo);
		userData.put(ECK0151C010CBSMsg.SJISHO_NAIYO_SEQ, sjishoNaiyioSeq);
		userData.put(ECK0151C010CBSMsg.ERR_CNT, null);
		userData.put(ECK0151C010CBSMsg.RSLT_FLG, null);
		HashMap<String, Object> paramMap = JCKBPCommon.createScParam(param, ECK0151C010CBSMsg.class , userData, "1");

		//***************************************************
		//* ＳＣ呼出実行
		//***************************************************
		printDebugLog("指示書エラー回数更新SC呼び出し開始");
		Map<?, ?> result = JCKPmpCommonUtil.scCallRun(param, handle, paramMap);
		printDebugLog("指示書エラー回数更新SC呼び出し完了" + result);

		return result;
	}

	/**
	 * AxM連携に規定回数以上失敗したSYSIDをシスログに出力する。
	 * @param sysid SYSID
	 */
	private void printSyslog4AxmErr(String sysid)
	{
		String proId = "CKSV9001";
		String msgId = "LZC0200-E"; // 現行の指示書除外リスト追加時のメッセージID
		String msg   = "認証サーバーへの連携が規定回数以上失敗したため、連携除外となりました。（SYSID : " + sysid + "）";

		String sysdate = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date(System.currentTimeMillis()));
		HashMap<String, Object> propMap = new HashMap<String, Object>();

		propMap.put(JCCSuperComExecUtil.EXEC_BUFF_SIZE, JCMAPLConstMgr.getString(JCCSuperComExecUtil.EXEC_BUFF_SIZE));
		propMap.put(JCCSuperComExecUtil.EXEC_PERMIT_MEMORY, JCMAPLConstMgr.getString(JCCSuperComExecUtil.EXEC_PERMIT_MEMORY));
		propMap.put(JCCSyslogFormat.SYSLOG_FOMAT_PTN_KEY, JCMAPLConstMgr.getString(JCCSyslogFormat.SYSLOG_FOMAT_PTN_KEY));
		propMap.put(JCCSyslogFormat.SYSLOG_MAILING_ID_KEY, JCMAPLConstMgr.getString(JCCSyslogFormat.SYSLOG_MAILING_ID_KEY));
		propMap.put(JCCSyslogFormat.SYSLOG_OUT_DIR_OPTION, JCMAPLConstMgr.getString(JCCSyslogFormat.SYSLOG_OUT_DIR_OPTION));
		JCCSyslogFormat.logger(proId, msgId, sysdate, msg, null, propMap);
	}

	/**
	 * BPチェック用パラメータ作成。<br />
	 * @param handle セッションハンドル
	 * @param param リクエストパラメータ
	 * @param fixedText ユーザ定義文字列
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public HashMap getInvokeCBS(SessionHandle handle, IRequestParameterReadWrite param, String fixedText)
	{
		return JCKPmpScParamHenshu.createBpNotCheckParam();
	}

	/**
	 * ＢＰチェック結果の編集。<br />
	 * @param param リクエストパラメータ
	 * @param caanMsgs サービスインターフェイス用のパラメータ配列
	 * @param returnCode リターンコード
	 * @return リクエストパラメータ
	 * @throws Throwable 
	 */
	public IRequestParameterReadWrite editErrorInfo(IRequestParameterReadWrite param, CAANMsg[] caanMsgs, Integer returnCode) throws Throwable
	{
		return JCKPmpScParamHenshu.editErrorInfo(param, caanMsgs, returnCode);
	}
}
