package jp.mosp.payroll.common;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;

import jp.mosp.common.MosPAction;
import jp.mosp.common.common.MospConst;
import jp.mosp.common.common.MospException;
import jp.mosp.common.common.MospUtility;
import jp.mosp.legal.LegalReportUtility;
import jp.mosp.payroll.base.Bonus;
import jp.mosp.payroll.base.PayrollConst;
import jp.mosp.payroll.bonus.BonusConst;
import jp.mosp.payroll.bonus.dao.PdBonAllowanceDao;
import jp.mosp.payroll.bonus.dao.PdBonDeductionDao;
import jp.mosp.payroll.bonus.dao.PdBonSumDao;
import jp.mosp.payroll.bonus.dao.PhBounsDao;
import jp.mosp.payroll.bonus.dao.PmDetailBaDao;
import jp.mosp.payroll.bonus.dao.PmDetailBdDao;
import jp.mosp.payroll.bonus.dao.PmDetailBsDao;
import jp.mosp.payroll.bonus.dto.PhBounsDto;
import jp.mosp.payroll.common.vo.FirmBankingOutputVo;
import jp.mosp.payroll.dao.BankTransferDao;
import jp.mosp.payroll.dao.CmBankDao;
import jp.mosp.payroll.dao.CmBranchDao;
import jp.mosp.payroll.dao.CmCoBankDao;
import jp.mosp.payroll.dao.CmCompanyDao;
import jp.mosp.payroll.dto.BankTransferFBDataDto;
import jp.mosp.payroll.dto.CmBankDto;
import jp.mosp.payroll.dto.CmBranchDto;
import jp.mosp.payroll.dto.CmCoBankDto;
import jp.mosp.payroll.dto.CmCompanyDto;

public class BonusFBDataOutputAction extends MosPAction {
	
	// コマンド
	private static final String	CMD_BONUS_FB_DATA_OUTPUT	= "P9011";
	

	/**
	 * コンストラクタ
	 */
	public BonusFBDataOutputAction() {
		super();
		setNeedProcSeq(false);
	}
	

	int	total		= 0;
	int	amount		= 0;
	// 追加レコード長
	int	lenRecord	= 0;
	

	/**
	 * アクション
	 */
	public void action() throws Exception {
		// DBコネクション取得
		getConnection();
		// PAYROLL権限確認
		confirmPayrollAuth();
		// VOの取得
		FirmBankingOutputVo vo = (FirmBankingOutputVo)session.getAttribute(MospConst.ATT_FORMER_VO);
		vo.clearMessage();
		vo.clearErrField();
		vo.initVo(cfg, msg, cmd, aspUser, user);
		if (cmd.equals(CMD_BONUS_FB_DATA_OUTPUT)) {
			// パラメータ取得
			vo.setParams(request);
			// 会社情報登録
			updateCompanyInfo(vo);
			// 追加レコード長取得
			getAddRecordLength(Integer.parseInt(vo.getTxtRecordLength()));
			// 対象年月取得
			Date payday = vo.getDate(vo.getPltSpecifyYear(), vo.getPltSpecifyMonth(), vo.getPltSpecifyDay());
			Date targetMonth = vo.getDate(vo.getPltSpecifyYear(), vo.getPltSpecifyMonth(), vo.getPltSpecifyDay());
			// FBデータ情報取得
			BankTransferDao bankTransferDao = new BankTransferDao();
			bankTransferDao.initDao(cfg, cmd, aspUser, user, conn);
			// ステータスが確定の賞与データのみ取得
			List<BankTransferFBDataDto> list = bankTransferDao.findForCondition(vo.getPltCoBankCode(), targetMonth,
					payday, false);
			// 帳票作成準備
			StringBuffer sb = new StringBuffer();
			String fileName = vo.getPltSpecifyYear() + PayrollConst.FILE_NAME_SEPARATOR + vo.getPltSpecifyMonth()
					+ PayrollConst.FILE_NAME_SEPARATOR + vo.getPltSpecifyDay() + PayrollConst.FILE_NAME_SEPARATOR
					+ PayrollConst.FILE_FB_BONUS_DATA;
			request.setAttribute(MospConst.ATT_FILE_NAME, fileName);
			request.setAttribute(MospConst.ATT_FILE_OBJECT, sb);
			// 賞与データ確認
			if (list.size() == 0) {
				String errMessage = MospUtility.getMessage(msg, PayrollConst.MSG_NO_BONUS, "");
				sb.append(errMessage);
				return;
			}
			//振込金額の取得
			getFrimAmo(list);
			// FBデータ作成
			getFBDataRecord(sb, list, vo);
		}
	}
	
	/**
	 * FBデータ作成
	 * @param sb
	 * @param list
	 * @throws Exception
	 */
	protected void getFBDataRecord(StringBuffer sb, List<BankTransferFBDataDto> list, FirmBankingOutputVo vo)
			throws Exception {
		// 会社銀行情報取得準備
		CmCoBankDao cmCoBankDao = new CmCoBankDao();
		cmCoBankDao.initDao(cfg, cmd, aspUser, user, conn);
		// 会社銀行コードを持つ社員のリストを取得
		// 会社銀行情報取得
		CmCoBankDto cmCoBankDto = cmCoBankDao.findForKey(vo.getPltCoBankCode());
		// 対象社員でまわす
		for (int j = 0; j < list.size(); j++) {
			BankTransferFBDataDto bankTransferFBDataDto = list.get(j);
			if (j == 0) {
				// ヘッダーレコード設定
				setHeaderRecordData(sb, bankTransferFBDataDto, cmCoBankDto, vo);
			}
			// データレコード設定
			setDataRecordData(sb, bankTransferFBDataDto, vo);
			// ステータス更新
			updateBonusStatus(bankTransferFBDataDto);
		}
		// すべて確認し終わったらトレーラーレコード設定
		LegalReportUtility.getTrailerRecord(sb, String.valueOf(total), String.valueOf(amount), checkLineFeed(vo
			.getPltRecordType()), lenRecord);
		// 改行付与確認
		checkLineFeed(vo.getPltEndRecord());
		
		// エンドレコード作成
		// エンドレコード出力確認
		if (checkLineFeed(vo.getPltEndRecord())) {
			LegalReportUtility.getEndRecord(sb, checkLineFeed(vo.getPltRecordType()), lenRecord);
		}
		// 初期化
		total = 0;
		amount = 0;
	}
	
	/**
	 * ヘッダーデータ設定
	 * @param sb
	 * @param aryBankCode
	 * @param aryBranchCode
	 * @param cmCompanyDto
	 * @param udPaymentDto
	 * @param cmCoBankDto
	 * @throws Exception 
	 */
	protected void setHeaderRecordData(StringBuffer sb, BankTransferFBDataDto bankTransferFBDataDto,
			CmCoBankDto cmCoBankDto, FirmBankingOutputVo vo) throws Exception {
		
		String[] aryBankName = getBankName(cmCoBankDto.getBankCode());
		String[] aryBranchName = getBranchNameArray(cmCoBankDto.getBankCode(), cmCoBankDto.getBranchCode());
		
		// 銀行名設定
		String coBankName = aryBankName[2];
		String coBranchName = aryBranchName[3];
		LegalReportUtility.getHeaderRecode(sb, PayrollConst.FB_BONUS_TYPE_CODE, vo.getPltCodeType(), vo
			.getTxtCompanyCode(), getLowerUpKana(vo.getTxtCompanyName()), String.valueOf(MospUtility
			.getMonth(bankTransferFBDataDto.getPayday())), String.valueOf(MospUtility.getDay(bankTransferFBDataDto
			.getPayday())), cmCoBankDto.getBankCode(), getLowerUpKana(coBankName), cmCoBankDto.getBranchCode(),
				getLowerUpKana(coBranchName), cmCoBankDto.getAccountType(), cmCoBankDto.getAccountNo(),
				checkLineFeed(vo.getPltRecordType()), lenRecord);
	}
	
	/**
	 * データレコードデータ設定
	 * @param sb
	 * @param bankTransferFBDataDto
	 * @throws Exception
	 */
	private void setDataRecordData(StringBuffer sb, BankTransferFBDataDto bankTransferFBDataDto, FirmBankingOutputVo vo)
			throws Exception {
		if (0 != bankTransferFBDataDto.getBankPayAmount()) {
			String[] aryBankName = getBankName(bankTransferFBDataDto.getPaidBankCode());
			String[] aryBranchName = getBranchNameArray(bankTransferFBDataDto.getPaidBankCode(), bankTransferFBDataDto
				.getPaidBranchCode());
			
			// 銀行名設定
			String bankName = aryBankName[2];
			String branchName = aryBranchName[3];
			String bankPayAmount = String.valueOf(bankTransferFBDataDto.getBankPayAmount());
			
			LegalReportUtility.getFBDataRecord(sb, bankTransferFBDataDto.getPaidBankCode(), getLowerUpKana(bankName),
					bankTransferFBDataDto.getPaidBranchCode(), getLowerUpKana(branchName), bankTransferFBDataDto
						.getAccountType(), bankTransferFBDataDto.getAccountNo(), getLowerUpKana(bankTransferFBDataDto
						.getHolderKana()), bankPayAmount, bankTransferFBDataDto.getKCode(), bankTransferFBDataDto
						.getStationCode(), checkLineFeed(vo.getPltRecordType()), lenRecord);
			// 件数設定
			total++;
			// 合計金額設定
			amount += bankTransferFBDataDto.getBankPayAmount();
		}
	}
	
	/**
	 * 賞与ステータス更新
	 * @param bankTransferFBDataDto
	 * @throws SQLException
	 * @throws IllegalAccessException
	 * @throws NoSuchFieldException
	 * @throws MospException
	 */
	private void updateBonusStatus(BankTransferFBDataDto bankTransferFBDataDto) throws SQLException,
			IllegalAccessException, NoSuchFieldException, MospException {
		// 給与情報更新
		//	PhBounsDao phBonusDao = new PhBounsDao();
		//	phBonusDao.initDao(cfg, cmd, aspUser, user, conn);
		//	PhBounsDto udBonusDto = phBonusDao.findForKey(bankTransferFBDataDto.getKCode(), bankTransferFBDataDto.getCalcDate(), bankTransferFBDataDto.getPayday());
		//	if (udBonusDto != null) {
		// ステータスをFBデータ出力済みに設定
		//		udBonusDto.setCalcStatus(UnicConst.CALC_STATUS_FB);
		// UD_PAYMENT更新
		//		udBonusDao.update(udBonusDto, true);
		// コミット
		//		commit();
		//	}
		
	}
	
	/**
	 * 会社情報更新
	 * @param vo
	 * @throws SQLException
	 * @throws IllegalAccessException
	 * @throws NoSuchFieldException
	 * @throws MospException
	 */
	private void updateCompanyInfo(FirmBankingOutputVo vo) throws SQLException, IllegalAccessException,
			NoSuchFieldException, MospException {
		// DAO準備
		CmCompanyDao cmCompanyDao = new CmCompanyDao();
		cmCompanyDao.initDao(cfg, cmd, aspUser, user, conn);
		// 存在確認
		CmCompanyDto cmCompanyDto = cmCompanyDao.findAll();
		
		if (cmCompanyDto != null) {
			cmCompanyDto.setCompanyFbAddress(vo.getTxtCoAddress());
			cmCompanyDto.setCompanyFbKana(vo.getTxtCompanyName());
			// 更新
			cmCompanyDao.update(cmCompanyDto);
		} else {
			cmCompanyDto = new CmCompanyDto();
			cmCompanyDto.setCompanyFbAddress(vo.getTxtCoAddress());
			cmCompanyDto.setCompanyFbKana(vo.getTxtCompanyName());
			// 登録
			cmCompanyDao.insert(cmCompanyDto);
			
		}
		// コミット
		commit();
	}
	
	/**
	 * 銀行名取得(利用可能所属のみ)(CM_BANK)
	 * @return 銀行名リスト
	 * @throws Exception
	 */
	protected String[] getBankName(String bankCode) throws Exception {
		// 準備
		String[] aryBankName = new String[3];
		// DAOの準備
		CmBankDao dao = new CmBankDao();
		dao.initDao(cfg, cmd, aspUser, user, conn);
		// 情報の取得
		CmBankDto cmBankDto = dao.findForKey(bankCode);
		// 配列の作成
		if (cmBankDto != null) {
			aryBankName[0] = cmBankDto.getBankCode();
			aryBankName[1] = cmBankDto.getBankName();
			aryBankName[2] = cmBankDto.getBankKana();
		} else {
			aryBankName[0] = bankCode;
			aryBankName[1] = bankCode;
			aryBankName[2] = bankCode;
			
		}
		
		return aryBankName;
	}
	
	/**
	 * 支店コード取得(利用可能所属のみ)(CM_BANK)
	 * @return 銀行コードリスト
	 * @throws Exception
	 */
	protected String[] getBranchNameArray(String bankCode, String branchCode) throws Exception {
		// 準備
		String[] aryBranchName = new String[4];
		// DAOの準備
		CmBranchDao dao = new CmBranchDao();
		dao.initDao(cfg, cmd, aspUser, user, conn);
		// 情報の取得
		CmBranchDto cmBranchDto = dao.findForKey(bankCode, branchCode);
		// 配列の作成
		if (cmBranchDto != null) {
			aryBranchName[0] = cmBranchDto.getBankCode();
			aryBranchName[1] = cmBranchDto.getBranchCode();
			aryBranchName[2] = cmBranchDto.getBranchName();
			aryBranchName[3] = cmBranchDto.getBranchKana();
		} else {
			aryBranchName[0] = bankCode;
			aryBranchName[1] = branchCode;
			aryBranchName[2] = branchCode;
			aryBranchName[3] = branchCode;
			
		}
		return aryBranchName;
	}
	
	/**
	 * 半角カナ変換(小文字→大文字)
	 * @param strTarget
	 * @return　半角カナ文字列
	 */
	protected String getLowerUpKana(String strTarget) {
		// 半角カナ(小文字)
		String[] aryLowerKana = { "ｧ", "ｨ", "ｩ", "ｪ", "ｫ", "ｬ", "ｭ", "ｮ", "ｯ" };
		// 半角カナ(大文字)
		String[] aryLowerUpKana = { "ｱ", "ｲ", "ｳ", "ｴ", "ｵ", "ﾔ", "ﾕ", "ﾖ", "ﾂ" };
		// 準備
		String retString = "";
		String repString = "";
		// 文字列の桁数で回す
		for (int i = 0; i < strTarget.length(); i++) {
			// 順番に文字列を取得していく
			repString = strTarget.substring(i, i + 1);
			// 文字列を順番に確認
			for (int j = 0; j < aryLowerKana.length; j++) {
				// 半角かな(小文字)が存在したら大文字へ変換
				if (aryLowerKana[j].equals(repString)) {
					repString = aryLowerUpKana[j];
					break;
				}
			}
			// 文字列を結合
			retString += repString;
		}
		return retString;
	}
	
	/**
	 * 改行付与確認
	 * @param strLineFeed
	 * @return
	 */
	private boolean checkLineFeed(String strLineFeed) {
		// レコード区分に改行をつけない
		if (strLineFeed.equals(PayrollConst.FB_RECORD_TYPE_NONE)) {
			return false;
		}
		// レコード区分に改行をつける
		return true;
	}
	
	/**
	 * 追加レコード長取得
	 * @param addLenRecord
	 */
	private void getAddRecordLength(int addLenRecord) {
		// 追加レコード長-120(最小レコード長)
		lenRecord = addLenRecord - PayrollConst.FB_LOWER_LEN_RECORD;
		if (lenRecord < 0) {
			lenRecord = 0;
		}
	}
	
	/**
	 * 振込み金額の取得
	 * @param list
	 */
	private void getFrimAmo(List<BankTransferFBDataDto> lineList) throws Exception {
		String oldkCode = "";
		String newkCode = "";
		
		for (int i = 0; i < lineList.size(); i++) {
			BankTransferFBDataDto list = lineList.get(i);
			
			newkCode = list.getKCode();
			if (!oldkCode.equals(newkCode)) {
				Bonus sumAmo = getPayment(list.getKCode(), list.getCalcDate());
				int amount = sumAmo.getSumAmount(BonusConst.DTL_SUM_BANK1);
				list.setBankPayAmount(amount);
			} else {
				Bonus sumAmo = getPayment(list.getKCode(), list.getCalcDate());
				int amount = sumAmo.getSumAmount(BonusConst.DTL_SUM_BANK2);
				list.setBankPayAmount(amount);
			}
			oldkCode = newkCode;
			
		}
		
	}
	
	/**
	 * 賞与伝票インスタンスを取得、設定する。<br><br>
	 * kCode、calcDateをキーとして賞与情報を取得し、{@link #payment}に格納する。
	 * @param kCode     社員コード
	 * @param payMonth 計算年月
	 * @return 賞与伝票
	 * @throws NoSuchFieldException 
	 * @throws IllegalAccessException 
	 * @throws SQLException 
	 */
	protected Bonus getPayment(String kCode, Date payMonth) throws SQLException, IllegalAccessException,
			NoSuchFieldException {
		PhBounsDto header = new PhBounsDao(cfg, cmd, aspUser, user, conn).findForKey(kCode, payMonth);
		if (header == null) {
			return null;
		}
		return new Bonus(header, new PmDetailBaDao(cfg, cmd, aspUser, user, conn).findForSlip(header.getSlipCode()),
				new PmDetailBdDao(cfg, cmd, aspUser, user, conn).findForSlip(header.getSlipCode()), new PmDetailBsDao(
						cfg, cmd, aspUser, user, conn).findForSlip(header.getSlipCode()), new PdBonAllowanceDao(cfg,
						cmd, aspUser, user, conn).find(kCode, payMonth), new PdBonDeductionDao(cfg, cmd, aspUser, user,
						conn).find(kCode, payMonth), new PdBonSumDao(cfg, cmd, aspUser, user, conn).find(kCode,
						payMonth));
	}
	
}
