package eo.ejb.cbs.mainproc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.fujitsu.futurity.model.base.CAANConnectionMgr;
import com.fujitsu.futurity.model.base.CAANException;
import com.fujitsu.futurity.model.base.CAANJDBCUtil;
import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.base.CAANRuntimeException;
import com.fujitsu.futurity.model.ejb.common.JSYejbConnection;
import com.fujitsu.futurity.model.ejb.common.StatusCodes;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;
import com.fujitsu.futurity.model.ejb.common.fw.TemplateMainHandler;

import eo.common.constant.JACStrConst;
import eo.common.util.JCRUtilCommon;
import eo.ejb.cbm.entity.CH0041ETMsg;
import eo.ejb.cbm.entity.CH0041LE;
import eo.ejb.cbs.cbsmsg.ECH0041D010CBSMsg;
import eo.ejb.cbs.cbsmsg.ECH0041D010CBSMsg1List;
import eo.ejb.cbs.cbsmsg.ECH0041D010CBSMsg2List;
import eo.ejb.cbs.cbsmsg.ECH0051D011CBSMsg;
import eo.ejb.common.db.JCHejbCH0041SecProc;

/**
 * 請求債権関連独自処理部品クラスです。
 */
public class JECH0041D010TPMA implements TemplateMainHandler {
	
	/**
	 * コンストラクタです。
	 */
	public JECH0041D010TPMA()
	{
		super();
	}
	
	/**
	 * <p>
	 * 請求債権関連情報を登録します。
	 * </p>
	 * 
	 * @param inCBSMsg   処理対象のメッセージキャリア
	 * @param inCcontext ディスパッチコンテキスト
	 */
	public void invoke(CAANMsg inCBSMsg, AgentDispatchContext inCcontext)
	{
		// CBSMsgにセットされているリストを取得する
		CAANMsg[] msgList = inCBSMsg.getCAANMsgList(ECH0041D010CBSMsg.ECH0041D010CBSMSG1LIST);
		
		// リストが設定されているかチェック
		if (msgList == null || msgList.length == 0)
		{
			// 不正な状態のため、Exceptionをスローする
			throw new CAANRuntimeException();
		}

		// 請求債権関連を登録、更新
		execute(inCBSMsg, inCcontext);
	}

	/**
	 * <p>
	 * 料金項目抽出変換に対象のレコードが存在するか判定するメソッドです。
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param con1 コネクション
	 * @param pstmt1 プリペアステートメント
	 * @param rsltQuery リザルトセット
	 * @param inDtMsg 業務機能識別コード
	 * @param traMtSeikyNo 繰越元請求番号
	 * @return boolean true：存在する、false：存在しない
	 */
	public static void execute(CAANMsg inCBSMsg, AgentDispatchContext inContext) {

		// CBSMsgにセットされているリストを取得する
		CAANMsg[] ech0041D010CBSMsg1List = inCBSMsg.getCAANMsgList(ECH0041D010CBSMsg.ECH0041D010CBSMSG1LIST);

		// 登録明細を初期化
		ArrayList<CAANMsg> entList = new ArrayList<CAANMsg>();

		// コネクション
		Connection con1 = null;

		// プリペアステートメント
		PreparedStatement pstmt1 = null;

		// リザルトセット
		ResultSet rsltQuery = null;

		try
		{
			//コネクション取得
			con1 = JSYejbConnection.getConnection(CH0041ETMsg.getTableName());

			// SQL文の作成
			StringBuffer sql_Buff = JCHejbCH0041SecProc.getSeikySaikenKnrn1Sql();

			//prepareStatementにSQL文をセット
			pstmt1 = con1.prepareStatement(sql_Buff.toString());

			for (int i = 0; i < ech0041D010CBSMsg1List.length; i++)
			{
				String mtSaikenNo = ech0041D010CBSMsg1List[i].getString(ECH0041D010CBSMsg1List.TRA_MT_SAIKEN_NO);
				String mtSeikyNo = ech0041D010CBSMsg1List[i].getString(ECH0041D010CBSMsg1List.TRA_MT_SEIKY_NO);
				String skSeikyNo = ech0041D010CBSMsg1List[i].getString(ECH0041D010CBSMsg1List.TRA_SK_SEIKY_NO);

				// 引継元債権番号が設定されているかチェック
				if (!JCRUtilCommon.isNull(mtSaikenNo))
				{
					// 債権番号をキーに繰越元の請求債権関連を取得
					CAANMsg mtSeikySaikenKnrn = getSeikySaikenKnrnBySaikenNo(inCBSMsg, inContext, con1, pstmt1, rsltQuery, mtSaikenNo);

					if (mtSeikySaikenKnrn != null)
					{
						// 繰越元の請求債権関連を元に、
						// 新規登録の請求債権関連、繰越元の請求債権関連を編集
						// 請求書再発行の窓口の場合、このルートを通る
						setSeikySknKnrn1(inCBSMsg, entList, mtSeikySaikenKnrn, skSeikyNo);
					}
					else
					{
						// 繰越元の請求債権関連が存在しない場合、
						// 採番された請求番号、債権番号で新規登録の請求債権関連を編集
						// 随時請求書登録の場合、このルートを通る
						setSeikySknKnrn0(inCBSMsg, entList, mtSeikyNo, mtSaikenNo);
					}
				}
				else
				{
					// 請求番号をキーに繰越元の請求債権関連を取得
					CAANMsg[] mtSeikySaikenKnrn = getSeikySaikenKnrnBySeikyNo(inCBSMsg, inContext, mtSeikyNo);

					// 繰越元の請求債権関連を元に、
					// 新規登録の請求債権関連、繰越元の請求債権関連を編集
					// 請求書再発行の口座振替、クレジットの場合、このルートを通る
					setSeikySknKnrn2(inCBSMsg, entList, mtSeikySaikenKnrn, skSeikyNo);
				}

			}

			// 全ての請求債権関連登録情報のセットが終わったら、CBSMsgにセットする
			inCBSMsg.set(ECH0041D010CBSMsg.ECH0041D010CBSMSG2LIST, (CAANMsg[])entList.toArray(new CAANMsg[0]));
		}
		catch (SQLException e)
		{
			inCBSMsg.set(CH0041ETMsg.STATUS, StatusCodes.FIND_DB_ERR);
			throw new CAANRuntimeException(e);
		}
		finally 
		{
			// 資源の解放
			try
			{
				if(rsltQuery != null)
				{
					rsltQuery.close();
				}
				if(pstmt1 != null)
				{
					pstmt1.close();
				}
				if(con1 != null)
				{
					CAANConnectionMgr.getInstance().close(con1);
				}
			}
			catch(SQLException e)
			{
				inCBSMsg.set(ECH0041D010CBSMsg.STATUS, StatusCodes.FIND_DB_ERR);
				throw new CAANRuntimeException(e);
			}
		}

	}

	/**
	 * <p>
	 * 請求債権関連を取得する。<br>
	 * （債権番号をキーに最新請求の請求債権関連を取得（単一））<br>
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param con1 コネクション
	 * @param pstmt1 プリペアステートメント
	 * @param rsltQuery リザルトセット
	 * @param traMtSaikenNo 繰越元債権番号
	 * @return 取得した請求債権関連テーブルの情報(取得できなかった場合はnullを返す)
	 */
	private static CAANMsg getSeikySaikenKnrnBySaikenNo(CAANMsg inCBSMsg, AgentDispatchContext inContext,
			Connection con1, PreparedStatement pstmt1, ResultSet rsltQuery, String traMtSaikenNo) {

		// パラメータ設定リスト
		List<Object> replaceListCnt = new ArrayList<Object>();

		try{
			// パラメータ設定リストに値を設定
			replaceListCnt.add(traMtSaikenNo);

			// PreparedStatementの指定されたパラメータカラムに 指定された値を設定
			for (int idx = 0; idx < replaceListCnt.size(); idx++ )
			{
				CAANJDBCUtil.setParam(pstmt1, idx+1, replaceListCnt.get(idx));
			}

			// ResultSetの取得
			rsltQuery = pstmt1.executeQuery();

			// 返却用請求債権関連
			CAANMsg retMsg = new CAANMsg(CH0041ETMsg.class.getName());

			if (rsltQuery.next()){
				retMsg.set(CH0041ETMsg.SEIKY_NO, rsltQuery.getString("SEIKY_NO"));
				retMsg.set(CH0041ETMsg.SAIKEN_NO, rsltQuery.getString("SAIKEN_NO"));
				retMsg.set(CH0041ETMsg.SEIKY_KKSHI_FLG, rsltQuery.getString("SEIKY_KKSHI_FLG"));
				retMsg.set(CH0041ETMsg.KKSHI_CNT, rsltQuery.getString("KKSHI_CNT"));
			}
			else
			{
				return null;
			}

			return retMsg;
		}
		catch (SQLException e)
		{
			inCBSMsg.set(CH0041ETMsg.STATUS, StatusCodes.FIND_DB_ERR);
			throw new CAANRuntimeException(e);
		}
	}

	/**
	 * <p>
	 * 請求債権関連を取得する。<br>
	 * （請求番号をキーに関連する請求債権関連を取得（複数件））<br>
	 * </p>
	 * @param inCBSMsg 処理対象のメッセージキャリア
	 * @param inContext Agentから渡されたAgentDispatchContext
	 * @param traMtSeikyNo 繰越元請求番号
	 * @return 取得した請求債権関連テーブルの情報(取得できなかった場合は長さが0の配列を返す)
	 */
	private static CAANMsg[] getSeikySaikenKnrnBySeikyNo(CAANMsg inCBSMsg, AgentDispatchContext inContext, String traMtSeikyNo) {

		CAANMsg msgCH0041 = new CAANMsg(CH0041ETMsg.class.getName());
		CAANMsg[] msgCH0041List = null;
		CH0041LE le = new CH0041LE();

		// 引継元請求債権関連を取得する条件を設定
		msgCH0041.set(CH0041ETMsg.SEIKY_NO, traMtSeikyNo);
		msgCH0041.set(CH0041ETMsg.MK_FLG, JACStrConst.MK_FLG_YK);

		try
		{
			msgCH0041List = le.findByCondition(msgCH0041);
		}
		catch (CAANException ce)
		{
			throw new CAANRuntimeException(ce);
		}

		return msgCH0041List;
	}

	/**
	 * <p>
	 * 請求債権関連に登録する情報を設定する
	 * </p>
	 * @param inCBSMsg   処理対象のメッセージキャリア
	 * @param entList      請求債権関連登録情報格納用リスト
	 * @param mtSeikyNo 引継元請求番号
	 * @param mtSaikenNo 引継元債権番号
	 */
	private static void setSeikySknKnrn0(CAANMsg inCBSMsg,ArrayList<CAANMsg> entList, String mtSeikyNo, String mtSaikenNo)
	{
		// 請求債権関連登録明細を生成する。
		CAANMsg addMsg = new CAANMsg("eo.ejb.cbs.cbsmsg.ECH0041D010CBSMsg2List");
		addMsg.set(ECH0041D010CBSMsg2List.SEIKY_NO, mtSeikyNo);
		addMsg.set(ECH0041D010CBSMsg2List.SAIKEN_NO, mtSaikenNo);
		addMsg.set(ECH0041D010CBSMsg2List.SEIKY_KKSHI_FLG, JACStrConst.SEIKY_KKSHI_FLG_NSI_SHKV);
		addMsg.set(ECH0041D010CBSMsg2List.KKSHI_CNT, "0");

		entList.add(addMsg);
	}

	/**
	 * <p>
	 * 請求債権関連に登録する情報を設定する
	 * </p>
	 * @param inCBSMsg   処理対象のメッセージキャリア
	 * @param entList      請求債権関連登録情報格納用リスト
	 * @param mtSeikySaikenKnrn 引継元請求債権関連
	 * @param traSkSeikyNo 引継先請求番号
	 */
	private static void setSeikySknKnrn1(CAANMsg inCBSMsg, ArrayList<CAANMsg> entList, CAANMsg mtSeikySaikenKnrn, String traSkSeikyNo)
	{
		JCHejbCH0041SecProc ch0041 = new JCHejbCH0041SecProc();

		CAANMsg entMsg = new CAANMsg(ECH0041D010CBSMsg2List.class.getName());

		// 請求債権関連登録処理
		// 請求番号
		entMsg.set(ECH0041D010CBSMsg2List.SEIKY_NO, traSkSeikyNo);
		// 債権番号
		entMsg.set(ECH0041D010CBSMsg2List.SAIKEN_NO, mtSeikySaikenKnrn.getString(CH0041ETMsg.SAIKEN_NO));

		// 請求繰越フラグ←"1"(繰越先)
		entMsg.set(ECH0041D010CBSMsg2List.SEIKY_KKSHI_FLG, "1");

		// 登録情報を格納する前に繰返回数を数値として取得する
		int kkCnt = Integer.parseInt(mtSeikySaikenKnrn.getString(CH0041ETMsg.KKSHI_CNT));
		// 請求を再発行するため、繰返回数をカウントアップ
		kkCnt++;
		entMsg.set(ECH0041D010CBSMsg2List.KKSHI_CNT, Integer.toString(kkCnt));

		// リストに登録情報を追加
		entList.add(entMsg);

		// 引継元 請求債権関連更新処理
		if ("1".equals(inCBSMsg.getObject(ECH0051D011CBSMsg.FUNC_CODE).toString()))
		{
			ch0041.updateSeikySaikenKnrn(inCBSMsg, mtSeikySaikenKnrn);
		}
	}

	/**
	 * <p>
	 * 請求債権関連に登録する情報を設定する
	 * </p>
	 * @param inCBSMsg   処理対象のメッセージキャリア
	 * @param entList      請求債権関連登録情報格納用リスト
	 * @param mtSeikySaikenKnrn 引継元請求債権関連
	 * @param traSkSeikyNo 引継先請求番号
	 */
	private static void setSeikySknKnrn2(CAANMsg inCBSMsg, ArrayList<CAANMsg> entList, CAANMsg[] mtSeikySaikenKnrn, String traSkSeikyNo)
	{
		JCHejbCH0041SecProc ch0041 = new JCHejbCH0041SecProc();

		for (int i = 0; mtSeikySaikenKnrn.length > i; i++)
		{
			CAANMsg entMsg = new CAANMsg(ECH0041D010CBSMsg2List.class.getName());

			// 請求債権関連登録処理
			// 請求番号
			entMsg.set(ECH0041D010CBSMsg2List.SEIKY_NO, traSkSeikyNo);
			// 債権番号
			entMsg.set(ECH0041D010CBSMsg2List.SAIKEN_NO, mtSeikySaikenKnrn[i].getString(CH0041ETMsg.SAIKEN_NO));

			// 請求繰越フラグ←"1"(繰越先)
			entMsg.set(ECH0041D010CBSMsg2List.SEIKY_KKSHI_FLG, "1");

			// 登録情報を格納する前に繰返回数を数値として取得する
			int kkCnt = Integer.parseInt(mtSeikySaikenKnrn[i].getString(CH0041ETMsg.KKSHI_CNT));
			// 請求を再発行するため、繰返回数をカウントアップ
			kkCnt++;
			entMsg.set(ECH0041D010CBSMsg2List.KKSHI_CNT, Integer.toString(kkCnt));

			// リストに登録情報を追加
			entList.add(entMsg);

			// 引継元 請求債権関連更新処理
			if ("1".equals(inCBSMsg.getObject(ECH0051D011CBSMsg.FUNC_CODE).toString()))
			{
				ch0041.updateSeikySaikenKnrn(inCBSMsg, mtSeikySaikenKnrn[i]);
			}
		}
	}

}
