/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JBSbatCNCrecardRsltDataNgHosei
*	ソースファイル名	：JBSbatCNCrecardRsltDataNgHosei.java
*	作成者				：富士通　
*	作成日				：2023年02月16日
*＜機能概要＞
*　クレジットカード有効性結果NG補正部品です。
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v1.00.00	2023/02/16	富士通		新規作成
*	v64.00.00	2023/02/16  FJ)孫		【ANK-4349-00-00】コンテンツクレカ有効性結果補正のシステム化対応
*********************************************************************/
package eo.business.service;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;

import com.fujitsu.futurity.model.common.check.LengthCheck;

import eo.business.common.JBSbatBusinessService;
import eo.business.common.JCCBatCommon;
import eo.common.constant.JCNStrConst;
import eo.common.constant.JPCBatchMessageConstant;
import eo.common.util.JKKCommonUtil;
import eo.framework.application.JBSbatBusinessException;
import eo.framework.file.JBSbatInputFileUtil;
import eo.framework.item.JBSbatCommonItem;
import eo.framework.item.JBSbatOutputItem;

/**
* (クラスの機能概要) <p>
*<BR>
* @author 富士通
*/
public class JBSbatCNCrecardRsltDataNgHosei extends JBSbatBusinessService
{
	/**▼▼▼▼▼▼ツールから生成した宣言です 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成した宣言です 終了▲▲▲▲▲▲*/

	/** レコードサイズ */
	private static final int ITEM_SIZE = 2;

	/** エラーコード */
	private static String errCd = "";
	
	/** 置き換え文字 */
	private static String[] msgCkanMoji = null;

	/** 必須 */
	private static final String IS_REQUIRED = "IS_REQUIRED";

	/** 属性: 半角英数字1 */
	private static final String ATTR_HLFWD_ALP_1 = "半角英数字1";

	/** クレジットカード預かりIDの格納用リスト */
	private static final ArrayList<String> crecardAzkriIdList = new ArrayList<String>();
	
	private static String KAKOIMOJI = "\"";
	
	/**
	 * 初期処理
	 * @param JBSbatCommonItem commonItem　バッチ共通パラメータ電文
	 * @throws Exception
	 */
	public void initial(JBSbatCommonItem commonItem) throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの初期処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した初期化のソースです 開始▼▼▼▼▼▼*/
		super.setCommonInfo(commonItem);
		/**▲▲▲▲▲▲ツールから生成した初期化のソースです 終了▲▲▲▲▲▲*/
	/**▲▲▲▲▲▲業務サービスの初期処理を記述してください。▲▲▲▲▲▲*/
	}

	/**
	 * 主処理
	 * @return JBSbatOutputItem　出力情報
	 * @throws Exception
	 */
	public JBSbatOutputItem execute() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの主処理を記述してください。▼▼▼▼▼▼*/
		String strFreeParam = commonItem.getFreeItem();
		// パラメータを区切り文字で分割する
		String[] lines = strFreeParam.split(JCNStrConst.S_PARAM_DELIM);
		// コンテンツ有効性結果補正ファイル
		conProcessItemCheck(lines[0]);
		// 有効性チェック結果データファイル
		ykProcessItemCheck(lines[1], lines[2]);
		return null;
		/**▲▲▲▲▲▲業務サービスの主処理を記述してください。▲▲▲▲▲▲*/
	}
	
	/**
	 * コンテンツ有効性結果補正ファイル読み込み、チェック処理を行う。<br>
	 * 
	 * @param fileName ファイル名(コンテンツ有効性結果補正ファイル)
	 * @param data 入力ファイルの行データ
	 * @param index ループの現在のインデックス
	 * @throws Exception 
	 * @throws JBSbatBusinessException 業務サービス内で発生した例外全般。
	 */
	private void conProcessItemCheck(String fileName) throws Exception
	{
		// コンテンツ有効性結果補正ファイル読み込み用のリスト
		ArrayList<String> contResultList = new ArrayList<String>();
		
		// コンテンツ有効性結果補正ファイル読み込み
		contResultList = readFile(fileName);
			
		for(int i = 0; i < contResultList.size(); i++)
		{
			String[] contData = contResultList.get(i).split(JCNStrConst.S_SEP_CAM, -1);
			// 項目数チェック
			if(ITEM_SIZE != contData.length)
			{
				errCd = JPCBatchMessageConstant.ECNB0410AI;
				msgCkanMoji = new String[] {fileName, String.valueOf(i + 1), contResultList.get(i) };
				break;
			}
			String sysId = checkQuototion(contData[0]);
			String crecardAzkriId = checkQuototion(contData[1]);
			// 列表現 : 0 - 項目名 , 1 - 必須, 2 - 形式, 3 - 最小, 4 - 最大, 5 - データ
			String[][] recordDefinition = {
					{ "SYSID", IS_REQUIRED, ATTR_HLFWD_ALP_1, "10", "10", sysId },
					{ "クレジットカード番号預りID", IS_REQUIRED, ATTR_HLFWD_ALP_1, "16", "16", crecardAzkriId } };
			// 項目チェック（必須・属性・桁数チェック）を行う。
			for(String[] arrayData : recordDefinition)
			{
				// 必須エラーの場合
				if(checkRequired(fileName, arrayData, i))
				{
					break;
				}
				// 属性エラーの場合
				if(checkAttribute(fileName, arrayData, i))
				{
					break;
				}
				// 桁数エラーの場合
				if(checkDigits(fileName, arrayData, i))
				{
					break;
				}
			}
			if(!errCd.isEmpty())
			{
				break;
			}
			// ２番目要素をクレジットカード預かりIDリストに格納する
			crecardAzkriIdList.add(crecardAzkriId);
		}
		if(!errCd.isEmpty())
		{
			super.logPrint.printBusinessErrorLog(JPCBatchMessageConstant.ECNB0480JW);
			super.commonItem.addErrorCount(1);
			logPrint.printBusinessErrorLog(errCd, msgCkanMoji);
		}
	}
	
	/**
	 * 有効性チェック結果データファイル読み込み、チェック処理を行う。<br>
	 * 
	 * @param fileName ファイル名(有効性チェック結果データファイル)
	 * @param data 入力ファイルの行データ
	 * @param index ループの現在のインデックス
	 * @throws JBSbatBusinessException 業務サービス内で発生した例外全般。
	 */
	private void ykProcessItemCheck(String fileInName, String fileOutName) throws Exception
	{
		// 有効性チェック結果データファイル読み込み用のリスト
		ArrayList<String> ykResultList = new ArrayList<String>();
		// 退避リスト
		ArrayList<String> taihiList = new ArrayList<String>();
		// 出力ファイル作成
		OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream(fileOutName, true));
		// ファイル書き込み用
		BufferedWriter bw = new BufferedWriter(ow);
		// 有効性チェック結果データファイル読み込み
		ykResultList = readFile(fileInName);
		
		for(int k = 0; k < ykResultList.size(); k++)
		{
			String[] ykData = ykResultList.get(k).split(JCNStrConst.S_SEP_CAM, -1);
			if(errCd.isEmpty() && crecardAzkriIdList.contains(ykData[2]))
			{
				taihiList.add(ykData[2]);
				if(JCNStrConst.S_JCN_YK_CFM_RSLT_DIV_OK.equals(ykData[4]) || JCNStrConst.S_JCN_YK_CFM_RSLT_DIV_NO_SUPPORT.equals(ykData[4]))
				{
					ykData[4] = JCNStrConst.S_JCN_YK_CFM_RSLT_DIV_NG;
				}
			}
			writeFile(ykData, bw);
		}
		bw.close();
		
		if (errCd.isEmpty())
		{
			int count = 0;
			for(int i = 0; i < crecardAzkriIdList.size(); i++)
			{
				if(!taihiList.contains(crecardAzkriIdList.get(i)))
				{
					logPrint.printBusinessErrorLog(JPCBatchMessageConstant.ECNB0450AI, new String[] {crecardAzkriIdList.get(i) });
					count++;
				}
			}
			if(count > 0)
			{
				super.logPrint.printBusinessErrorLog(JPCBatchMessageConstant.ECNB0490JW);
				super.commonItem.addErrorCount(1);
			}
		}
	}
	
	/**
	 * ダブルクォーテーションをチェックする。<br>
	 * 
	 * @param data 入力ファイルの行データ
	 * @throws JBSbatBusinessException 業務サービス内で発生した例外全般。
	 */
	private String checkQuototion(String data) throws JBSbatBusinessException
	{
		String colm = data;
		// 先頭 または 最後がダブルクォートの場合
		if (colm.startsWith(KAKOIMOJI))
		{
			colm = colm.substring(1);
		}
		if (colm.endsWith(KAKOIMOJI))
		{
			colm = colm.substring(0, colm.length() - 1);
		}
		return colm;
	}
	
	/**
	 * 必要なエラーを確認してください。<br>
	 * 
	 * @param fileName ファイル名(有効性チェック結果データファイル)
	 * @param data 入力ファイルの行データ
	 * @param index ループの現在のインデックス
	 * @return true:エラーあり false:エラーなし
	 * @throws JBSbatBusinessException 業務サービス内で発生した例外全般。
	 */
	private boolean checkRequired(String fileName, String[] data, int index) throws JBSbatBusinessException
	{
		// 0 - 項目名
		// 1 - 必須
		// 5 - データ
		if (IS_REQUIRED.equals(data[1]))
		{
			if (JKKCommonUtil.isNull(data[5]))
			{
				// 必須エラーの場合
				errCd = JPCBatchMessageConstant.ECNB0420AI;
				msgCkanMoji = new String[] {fileName, String.valueOf(index + 1), data[0] };
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 属性エラーを確認します。<br>
	 * 
	 * @param fileName ファイル名(有効性チェック結果データファイル)
	 * @param data 入力ファイルの行データ
	 * @param index ループの現在のインデックス
	 * @return true:エラーあり false:エラーなし
	 * @throws JBSbatBusinessException 
	 */
	private boolean checkAttribute(String fileName, String[] data, int index) throws JBSbatBusinessException
	{
		// 0 - 項目名
		// 2 - 形式
		// 5 - データ
		if (!JKKCommonUtil.isNull(data[5]))
		{
			// 半角英数字1
			if (ATTR_HLFWD_ALP_1.equals(data[2]))
			{
				if (!JCCBatCommon.isHannkakuESuuji1(data[5]))
				{
					// 属性エラーの場合
					errCd = JPCBatchMessageConstant.ECNB0430AI;
					msgCkanMoji = new String[] {fileName, String.valueOf(index + 1), data[0] };
					return true;
				}
			
			}
		}
		return false;
	}
	
	/**
	 * 桁エラーチェックを実行します。<br>
	 * 
	 * @param fileName ファイル名(有効性チェック結果データファイル)
	 * @param data 入力ファイルの行データ
	 * @param index ループの現在のインデックス
	 * @return true:エラーあり false:エラーなし
	 * @throws JBSbatBusinessException 業務サービス内で発生した例外全般。
	 */
	private boolean checkDigits(String fileName, String[] data, int index) throws JBSbatBusinessException
	{
		// 0 - 項目名
		// 3 - 最小
		// 4 - 最大
		// 5 - データ
		if (!JKKCommonUtil.isNull(data[5]))
		{
			// 桁数チェック
			if(!LengthCheck.isLength2Check(data[5], Integer.parseInt(data[3]), Integer.parseInt(data[4])))
			{
				// 桁数エラーの場合
				errCd = JPCBatchMessageConstant.ECNB0440AI;
				msgCkanMoji = new String[] {fileName, String.valueOf(index + 1), data[0] };
				return true;
			}
		}
		return false;
	}

	/**
	 * ファイル読み込み処理を行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 1.引数で読込ファイルディレクトリ(フルパス)を設定します。<br>
	 *
	 * 2.引数を元にファイル読込を行い、行をListへ格納します。<br>
	 * 
	 * </pre>
	 * <p>
	 * @param strFileDir    出力ディレクトリ(フルパス)。
	 * @return resultList   返却用List
	 * @throws Exception    業務サービス内で発生した例外全般。
	 */
	private static ArrayList<String> readFile(String strFileDir) throws Exception
	{
		ArrayList<String> resultList = new ArrayList<String>();
		File file = new File(strFileDir);
		if(!file.exists()){
			return resultList;
		}
		// 外部出力ファイルパス
		JBSbatInputFileUtil inFile = new JBSbatInputFileUtil(strFileDir);
		inFile.setEncode(JCNStrConst.SJIS); // 文字コード
		inFile.setLine(JCNStrConst.S_LINE_SEPARAOR_CR_LF); // 改行コード
		inFile.createReader();
		try
		{
			while (true) 
			{
				String line = inFile.readLine();
				if (line == null)
				{
					inFile.close();
					break;
				}
				resultList.add(line);
			}
			return resultList;
		} 
		catch (IOException e)
		{
			throw e;
		} 
		finally
		{
			inFile.close();
		}
	}
	
	/**
	 * ファイル書き込み処理を行います。<br>
	 * <p>
	 * <b>処理フロー</b><br>
	 * <pre>
	 * 
	 * </pre>
	 * <p>
	 * @param fileName    出力ディレクトリ(フルパス)。
	 * @param data        出力データ。
	 * @throws Exception  業務サービス内で発生した例外全般。
	 */
	private void  writeFile(String[] data, BufferedWriter bw) throws Exception
	{
		StringBuffer buf = new StringBuffer();
		for (String arrayData : data) 
		{
			buf.append(arrayData);
			buf.append(",");
		}
		bw.write(buf.toString().substring(0, buf.length() - 1));
		bw.write("\r\n");
	}
	
	/**
	 * 業務サービス終了処理
	 * @throws Exception
	 */
	public void terminal() throws Exception
	{
	/**▼▼▼▼▼▼業務サービスの終了処理を記述してください。▼▼▼▼▼▼*/
		/**▼▼▼▼▼▼ツールから生成した終了処理のソースです 開始▼▼▼▼▼▼*/
		/**▲▲▲▲▲▲ツールから生成した終了処理のソースです 終了▲▲▲▲▲▲*/
	/**▲▲▲▲▲▲業務サービスの終了処理を記述してください。▲▲▲▲▲▲*/
	}
	/**▼▼▼▼▼▼ツールから生成したメソッドです 開始▼▼▼▼▼▼*/
	/**▲▲▲▲▲▲ツールから生成したメソッドです 終了▲▲▲▲▲▲*/
}
