/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JKKSmtvlCancel
*   ソースファイル名：JKKSmtvlCancel.java
*   作成者          ：富士通
*   日付            ：2013年01月10日
*＜機能概要＞
*   スマートバリューキャンセル部品です。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*   v5.00.00    2013/01/10   FJ）江藤    新規作成(【ANK-1272-00-00】【スマートバリュー】フォロー対応)
*
**********************************************************************/
package com.fujitsu.futurity.bp.custom.common;

import java.util.HashMap;
import java.util.Map;

import com.fujitsu.futurity.bp.custom.constant.JKKSmtvlCancelConstCC;
import com.fujitsu.futurity.bp.x21.bpm.ServiceComponentRequestInvoker;
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.exception.CCException;
import com.fujitsu.futurity.bp.x21.cc.exception.SCCallException;
import com.fujitsu.futurity.common.JCMConstants;
import com.fujitsu.futurity.common.x01.sc.SCControlMapKeys;
import com.fujitsu.futurity.model.base.CAANMsg;

import eo.common.constant.JKKStrConst;
import eo.common.util.JKKCommonUtil;
import eo.ejb.cbs.cbsmsg.EKK2101B002CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK2101B002CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK2441B003CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK2441B003CBSMsg1List;
import eo.ejb.cbs.cbsmsg.EKK2441C030CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK2451B001CBSMsg;
import eo.ejb.cbs.cbsmsg.EKK2451B001CBSMsg1List;

/**
 * スマートバリューキャンセル部品です。<p>
 * <br>
 * @author FJ
 */
public class JKKSmtvlCancel extends AbstractCommonComponent
{
	/** 年月日項目の初期値 */
	public static final String YMD_SHKV = "20991231";

	/** エラーメッセージ */
	public static final String ERR_MSG = "INVALID_RETURN_MESSAGE";

	/** エラーメッセージ：パラメータ設定不正 */
	private static final String ERR_MSG_PARAM = "リクエストパラメータに誤りがあります。";

	/** サービスインタフェース呼び出しで使用するマッパー群 */
	private JKKSmtvlCancelMapperCC mapper = null;

	/** SC呼び出し部品 */
	ServiceComponentRequestInvoker scCall = null;

	/**
	 * スマートバリューキャンセルの初期処理です。
	 * <br>
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @throws Throwable 
	 */
	private void init(IRequestParameterReadWrite param, String fixedText)
	throws Throwable
	{
		// マッパーの初期化
		if (null == this.mapper)
		{
			this.mapper = new JKKSmtvlCancelMapperCC();
		}
		if (param.getData(fixedText) == null)
		{  //本来は呼び出し側でparamに詰め込むべき
			param.setData(fixedText, new HashMap<String, Object>());
		}

		// SC呼び出し部品のインスタンス生成（引数にはログに出力するクラス名を渡す。空文字を設定した場合はログに出力されない。
		if (null == this.scCall)
		{
			this.scCall = new ServiceComponentRequestInvoker();
		}

		// リターンコードに正常を設定
		param.setControlMapData(SCControlMapKeys.RETURN_CODE, JCMConstants.RET_NORMAL);
	}

	/**
	 * スマートバリューキャンセル処理を行います。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param trgtData 対象データ
	 * @param fixedText ユーザ任意文字列
	 * @throws Throwable 
	 */
	@SuppressWarnings("unchecked")
	public void cancelSmtvl(SessionHandle handle, IRequestParameterReadWrite param, HashMap trgtData, String fixedText)
	throws Throwable
	{
		init(param, fixedText);

		// 入力パラメータチェック処理
		String errMsg = chkInput(handle, param, trgtData);
		if (!JKKCommonUtil.isNull(errMsg))
		{
			// チェックエラー
			throw new CCException(errMsg, new Exception());
		}
		
		// 対象データから業務情報を取得
		String svcKeiNo = (String)trgtData.get(JKKSmtvlCancelConstCC.SVC_KEI_NO);
		String idoDiv = (String)trgtData.get(JKKSmtvlCancelConstCC.IDO_DIV);

		// ■サービス契約番号に紐づく他事業者割引契約を取得。他事業者割引契約が存在しない場合、処理対象外
		CAANMsg msgEKK2441B003 = searchTajgsWribKei(handle, param, fixedText, svcKeiNo);
		if (msgEKK2441B003 == null)
		{
			return;
		}
		
		// ■他事業者割引契約が仮登録中以外は、処理対象外
		if (!isKariAdd(msgEKK2441B003))
		{
			return;
		}
		
		// ■起因が、住所変更以外の場合
		if(!JKKStrConst.CD00576_ADCHG_ADD.equals(idoDiv))
		{
			
			// ■他事業者割引契約に紐づくサービス契約に、「キャンセル済／解約済／照査ＮＧまたは従量制プラン」以外が存在する場合、処理対象外
			String tajgsWribKeiNo = msgEKK2441B003.getString(EKK2441B003CBSMsg1List.TAJGS_WRIB_KEI_NO);
			CAANMsg[] msgListEKK2451B001 = searchTajgswkeiTgkei(handle, param, fixedText, tajgsWribKeiNo);
			if(msgListEKK2451B001 != null && msgListEKK2451B001.length > 0)
			{
				for (CAANMsg msgEKK2451B001 : msgListEKK2451B001)
				{
					String svcKeiStat = msgEKK2451B001.getString(EKK2451B001CBSMsg1List.SVC_KEI_STAT);
					
					String shosaDslFinCd = msgEKK2451B001.getString(EKK2451B001CBSMsg1List.SHOSA_DSL_FIN_CD);
					
					String eohntPplanTikiSkcd = msgEKK2451B001.getString(EKK2451B001CBSMsg1List.EOHNT_PPLAN_TIKI_SKCD);
					
					if(!(JKKStrConst.CD00037_CANCEL_ZM.equals(svcKeiStat)
							|| JKKStrConst.CD00037_DSL_ZM.equals(svcKeiStat)
							|| JKKStrConst.CD00037_SHOSA_ZUMI.equals(svcKeiStat) && JKKStrConst.CD00469_2.equals(shosaDslFinCd)
							|| JKKStrConst.CD01421_JURYO.equals(eohntPplanTikiSkcd)
						))
					{
						return;
					}
				}
			}
		}
		// ■起因が、住所変更の場合
		else
		{
			//  ■解約→新規の場合は処理対象外
			//  ※住所変更の場合は、スマートバリューに紐づく両契約の状態を判定しない。
			//    一方でも満たさなくスマートバリューの適合条件をみなさない場合は、キャンセルする。
			CAANMsg[] msgListEKK2101B002 = searchAdchgDtl(handle, param, fixedText, svcKeiNo);
			if(msgListEKK2101B002 != null && msgListEKK2101B002.length > 0)
			{
				for (CAANMsg msgEKK2101B002 : msgListEKK2101B002)
				{
					// 変更前識別番号（移転元サービス契約番号）
					String chbfSkbtNo = msgEKK2101B002.getString(EKK2101B002CBSMsg1List.CHBF_SKBT_NO);
					
					// 変更後識別番号（移転先サービス契約番号）
					String chafSkbtNo = msgEKK2101B002.getString(EKK2101B002CBSMsg1List.CHAF_SKBT_NO);
					
					// 解約→新規の場合、変更前識別番号、変更後識別番号がともにされており、サービス契約番号が異なる。
					if(chbfSkbtNo != null && chafSkbtNo != null && !chbfSkbtNo.equals(chafSkbtNo))
					{
						return;
					}
				}
			}
		}
		
		// ■スマートバリュー仮登録申込キャンセル処理
		cnclSmtvlKariAddMkm(handle, param, fixedText, msgEKK2441B003);
		
	}

	/**
	 * 入力パラメータのチェックを行います。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param trgtData 対象データ
	 * @return エラーメッセージ
	 */
	@SuppressWarnings("unchecked")
	private String chkInput(SessionHandle handle, IRequestParameterReadWrite param, HashMap trgtData)
	{
		// サービス契約番号が設定されていない
		String svcKeiNo = (String)trgtData.get(JKKSmtvlCancelConstCC.SVC_KEI_NO);
		if (JKKCommonUtil.isNull(svcKeiNo))
		{
			return ERR_MSG_PARAM + "サービス契約番号が設定されていません。";
		}
		
		// 異動区分が設定されていない
		String idoDiv = (String)trgtData.get(JKKSmtvlCancelConstCC.IDO_DIV);
		if (JKKCommonUtil.isNull(idoDiv))
		{
			return ERR_MSG_PARAM + "異動区分が設定されていません。";
		}
		
		// チェックOK
		return "";
	}

	/**
	 * 他事業者割引契約一覧照会処理
	 * <br>
	 * 他事業者割引契約一覧照会(サービス契約番号)サービスインターフェースを呼び出します。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @param svcKeiNo サービス契約番号
	 * @return 他事業者割引契約一覧照会(サービス契約番号)結果
	 * @throws Throwable
	 */
	private CAANMsg searchTajgsWribKei(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, String svcKeiNo)
	throws Throwable
	{
		// 照会結果
		CAANMsg msgEKK2441B003 = null;

		// 上りマッピング処理
		HashMap<String, Object> inMapEKK2441B003 = this.mapper.editInMsgEKK2441B003(param, svcKeiNo);
		// サービスインターフェース呼び出し
		CAANMsg rsltMsgEKK2441B003 = callSvcInter(handle, param, fixedText, inMapEKK2441B003, new EKK2441B003CBSMsg().getContents());

		// 結果を返却
		CAANMsg[] rsltMsgListEKK2441B003 = rsltMsgEKK2441B003.getCAANMsgList(EKK2441B003CBSMsg.EKK2441B003CBSMSG1LIST);
		if (rsltMsgListEKK2441B003 != null && rsltMsgListEKK2441B003.length > 0)
		{
			msgEKK2441B003 = rsltMsgListEKK2441B003[0];
		}

		return msgEKK2441B003;
	}

	/**
	 * 他事業者割引契約対象契約一覧照会処理
	 * <br>
	 * 他事業者割引契約対象契約一覧照会サービスインターフェースを呼び出します。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @param tajgsWribKeiNo 他事業者割引契約番号
	 * @return 他事業者割引契約対象契約一覧照会結果
	 * @throws Throwable
	 */
	private CAANMsg[] searchTajgswkeiTgkei(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, String tajgsWribKeiNo)
	throws Throwable
	{
		// 上りマッピング処理
		HashMap<String, Object> inMapEKK2451B001 = this.mapper.editInMsgEKK2451B001(param, tajgsWribKeiNo);
		// サービスインターフェース呼び出し
		CAANMsg rsltMsgEKK2451B001 = callSvcInter(handle, param, fixedText, inMapEKK2451B001, new EKK2451B001CBSMsg().getContents());

		CAANMsg[] msgListEKK2451B001 = rsltMsgEKK2451B001.getCAANMsgList(EKK2451B001CBSMsg.EKK2451B001CBSMSG1LIST);

		return msgListEKK2451B001;
	}

	/**
	 * 他事業者割引契約一覧照会(サービス契約番号)結果から、スマートバリューが仮登録状態かどうかを返します。
	 * <br>
	 * @param msgEKK2441B003 他事業者割引契約一覧照会(サービス契約番号)結果
	 * @return 仮登録の場合はtrue、仮登録でない場合はfalse
	 */
	private boolean isKariAdd(CAANMsg msgEKK2441B003)
	{
		// 他事業者割引契約締結年月日
		String tajgsWribKeiCncYmd = msgEKK2441B003.getString(EKK2441B003CBSMsg1List.TAJGS_WRIB_KEI_CNC_YMD);

		// 他事業者割引契約締結年月日がnull、または初期値の場合は、仮登録
		return JKKCommonUtil.isNull(tajgsWribKeiCncYmd) || YMD_SHKV.equals(tajgsWribKeiCncYmd);
	}

	
	/**
	 * 住所変更明細一覧照会処理
	 * <br>
	 * 住所変更明細一覧照会（変更前識別番号）サービスインターフェースを呼び出します。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @param svcKeiNo サービス契約番号
	 * @return 住所変更明細一覧照会結果
	 * @throws Throwable
	 */
	private CAANMsg[] searchAdchgDtl(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, String svcKeiNo)
	throws Throwable
	{
		// 上りマッピング処理
		HashMap<String, Object> inMapEKK2101B002 = this.mapper.editInMsgEKK2101B002(param, svcKeiNo);
		// サービスインターフェース呼び出し
		CAANMsg rsltMsgEKK2101B002 = callSvcInter(handle, param, fixedText, inMapEKK2101B002, new EKK2101B002CBSMsg().getContents());

		// 結果を返却
		CAANMsg[] msgListEKK2101B002  = rsltMsgEKK2101B002.getCAANMsgList(EKK2101B002CBSMsg.EKK2101B002CBSMSG1LIST);
		
		return msgListEKK2101B002;
	}
	

	/**
	 * 
	 * 他事業者割引契約申込キャンセルサービスインターフェースを呼び出します。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @param msgEKK2441B003 他事業者割引契約一覧照会(サービス契約番号)結果
	 * @throws Throwable
	 */
	private void cnclSmtvlKariAddMkm(SessionHandle handle, IRequestParameterReadWrite param, String fixedText, CAANMsg msgEKK2441B003)
	throws Throwable
	{
		// 上りマッピング処理
		HashMap<String, Object> inMapEKK2441C030 = this.mapper.editInMsgEKK2441C030(param, msgEKK2441B003);
		// サービスインターフェース呼び出し
		callSvcInter(handle, param, fixedText, inMapEKK2441C030, new EKK2441C030CBSMsg().getContents());
	}
	
	
	/*
	 * --------------------------------------------------------------------------------------------
	 *  以下共通で使用するUtil系のメソッド ↓↓↓↓↓
	 * --------------------------------------------------------------------------------------------
	 */

	/**
	 * サービスインターフェース呼び出し処理です。
	 * <br>
	 * @param handle セッションマネージャなどを持ったハンドル
	 * @param param モデルグループ、コントロールマップを含むパラメータオブジェクト
	 * @param fixedText ユーザ任意文字列
	 * @param siInMap サービスインターフェースの入力マップ
	 * @param contents サービスインターフェースのテンプレート項目の配列
	 * @return 業務データ
	 * @throws Throwable 
	 */
	private CAANMsg callSvcInter(
			SessionHandle handle,
			IRequestParameterReadWrite param,
			String fixedText,
			HashMap<String, Object> siInMap,
			Object[][] contents)
			throws Throwable
	{
		
		// サービスインターフェースの呼び出し
		Map<?, ?> rsltMap = this.scCall.run(siInMap, handle);
		// エラーマッピング処理
		this.mapper.editResultRP(rsltMap, param, fixedText, contents);
		// エラーチェック処理
		errChk(rsltMap);
		// 業務データ取得処理
		CAANMsg workData = getWorkCAANMsg(rsltMap);

		return workData;
	}

	/**
	 * エラーチェック処理です。
	 * <br>
	 * @param msgList サービスインタフェース実行結果
	 * @throws SCCallException 
	 */
	private void errChk(
			Map<?, ?> msgList) 
			throws SCCallException
	{
		CAANMsg[] templates = (CAANMsg[])msgList.get(JCMConstants.TEMPLATE_LIST_KEY);
		CAANMsg template = templates[0];

		// リターンコード取得
		Integer returnCode = (Integer)msgList.get(JCMConstants.RET_CD_INT_KEY);
		
		// ステータス取得
		int templateStatus = template.getInt(JCMConstants.STATUS_INT_KEY);
		
		if ((0 != returnCode.intValue()) || (0 != templateStatus))
		{
			String errMsg = ERR_MSG;
			throw new SCCallException(errMsg, String.valueOf(returnCode), templateStatus);
		}
	}

	/**
	 * 業務データの取得処理です。
	 * <br>
	 * @param workMapKey 業務データのマップキー
	 * @param rslt SVIFの実行結果データ
	 * @return 業務データ
	 */
	private CAANMsg getWorkCAANMsg(Map<?, ?> rslt)
	{
		CAANMsg[] templates = (CAANMsg[])rslt.get(JCMConstants.TEMPLATE_LIST_KEY);
		CAANMsg parentTemplate = templates[0];

		return parentTemplate;
	}
}
