package jp.co.slcs.kaiden2.product_workflow.foundation.plugin.logicdesigner.transitmanager;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jp.co.intra_mart.foundation.logic.annotation.LogicFlowElement;
import jp.co.intra_mart.foundation.logic.element.ElementContext;
import jp.co.intra_mart.foundation.logic.element.FlowElementCloser;
import jp.co.intra_mart.foundation.logic.element.Task;
import jp.co.intra_mart.foundation.logic.exception.FlowExecutionException;
import jp.co.intra_mart.foundation.workflow.application.model.ApplyResultModel;
import jp.co.intra_mart.foundation.workflow.application.model.param.ApplyParam;
import jp.co.intra_mart.foundation.workflow.application.process.ApplyManager;
import jp.co.intra_mart.foundation.workflow.exception.WorkflowException;
import jp.co.slcs.kaiden2.base.foundation.conf.ConstTransitManager;
import jp.co.slcs.kaiden2.base.foundation.helper.DateHelper;
import jp.co.slcs.kaiden2.base.foundation.helper.IdentifierHelper;
import jp.co.slcs.kaiden2.base.foundation.util.StringUtil;
import jp.co.slcs.kaiden2.extension_imw.feature.plugin.kaiden.workflow.ImwActionProcessPlugin;
import jp.co.slcs.kaiden2.product_workflow.foundation.model.entity.K30tRouteDetail;
import jp.co.slcs.kaiden2.product_workflow.foundation.model.service.K30tRouteDetailService;
import jp.co.slcs.kaiden2.product_workflow.foundation.plugin.logicdesigner.category.KaidenProductWorkflowCategory;
import net.arnx.jsonic.JSON;
import org.seasar.framework.beans.util.Beans;
import org.seasar.framework.container.SingletonS2Container;
/**
 * TransitManager自動申請要素クラス.
 * 
 * @author Sumitomo Life Information Systems Co.,Ltd.
 */
@LogicFlowElement(id = "TransitManagerRegister", category = KaidenProductWorkflowCategory.class, index = 100)
public class TransitManagerRegisterTask extends
        Task<TransitManagerRegisterTaskMetadata, TransitManagerRegisterParameter, TransitManagerRegisterResult>
        implements FlowElementCloser {
    
    /** K30tRouteDetailService. */
    protected K30tRouteDetailService k30tRouteDetailService;
    /** DateHelper. */
    protected DateHelper dateHelper;
    /** IdentifierHelper. */
    protected IdentifierHelper identifierHelper;
    
    /** システム案件ID. */
    private static final String SYSTEM_MATTER_ID = "systemMatterId";
    /** ユーザデータID. */
    private static final String USER_DATA_ID = "userDataId";
    /** フォーマットパターン:yyyy-MM-dd. */
    private static final String FORMAT_PATTERN_HAIFUN_YMD = "yyyy-MM-dd";
    
    /**
     * コンストラクタ.
     * 
     * @param context {@link ElementContext}
     */
    public TransitManagerRegisterTask(ElementContext context) {
        super(context);
        context.addFlowElementCloser(this);
        
        k30tRouteDetailService = SingletonS2Container.getComponent(K30tRouteDetailService.class);
        dateHelper = SingletonS2Container.getComponent(DateHelper.class);
        identifierHelper = SingletonS2Container.getComponent(IdentifierHelper.class);
    }
    
    /**
     * ロジックフロー実行.
     * 
     * @param parameter {@link TransitManagerRegisterParameter}
     */
    @Override
    public TransitManagerRegisterResult execute(TransitManagerRegisterParameter parameter)
            throws FlowExecutionException {
        TransitManagerRegisterResult result = new TransitManagerRegisterResult();
        Beans.copy(parameter, result).execute();
        
        result.setStatus("0");
        result.setMessage("自動申請成功");
        
        // 旅程明細テーブルへ登録
        int insertCnt = insertTable(parameter.getArgs(), parameter.getDatas());
        
        if (insertCnt > 0) {
            try {
                // 申請処理
                ApplyResultModel resultModel = apply(parameter.getArgs());
                
                result.setSystemMatterId(resultModel.getSystemMatterId());
                result.setUserDataId(resultModel.getUserDataId());
                
            } catch (WorkflowException e) {
                result.setStatus("1");
                result.setMessage("自動申請失敗");
            } finally {
                deleteTable(parameter.getArgs());
            }
        }
        
        return result;
    }
    
    /**
     * 後処理.
     */
    @Override
    public void close() {
    }
    
    /**
     * 旅程明細のテーブルにデータを登録する。
     * 
     * @param args 申請に必要なデータ
     * @param datas TMデータ
     */
    private int insertTable(Map<String, Object> args, List<Map<String, Object>> datas) {
        List<K30tRouteDetail> entityList = new ArrayList<K30tRouteDetail>();
        Long tupleId = 0L;
        Long rowNumber = 1L;
        for (Map<String, Object> map : datas) {
            
            K30tRouteDetail entity = new K30tRouteDetail();
            entity.systemMatterId = (String) args.get(SYSTEM_MATTER_ID);
            entity.userDataId = (String) args.get(USER_DATA_ID);
            entity.gadgetClass = "routeDetail";
            entity.gadgetVariation = "v03";
            entity.gadgetInstance = 0L;
            entity.tupleId = tupleId;
            entity.gadgetId = entity.gadgetClass + "_" + entity.gadgetVariation + "_" + entity.gadgetInstance;
            entity.rowNumber = rowNumber;
            
            entity.expTypeCd = "20100002";
            entity.accountCd = "31001011";
            entity.taxTypeCd = "V8";
            entity.taxRate = new BigDecimal("0.08");
            entity.quantity = BigDecimal.ONE;
            entity.transCurrencyCd = "JPY";
            entity.companyRate = BigDecimal.ONE;
            entity.companyCurrencyCd = "JPY";
            entity.payTypeCd = "0002";
            entity.departmentSetCd = "comp_sample_01";
            entity.departmentCd = "dept_sample_11";
            entity.projectCd = "000001";
            entity.roundTripFlag = "0";
            entity.routeLinkFlag = "0";
            
            // TransitManagerのデータの設定
            String categoryCd = (String) map.get(ConstTransitManager.CATEGORY_CODE);
            entity.routeDate = dateHelper.toTimestamp(converFormatDate((String) map.get(ConstTransitManager.PAY_DATE),
                    FORMAT_PATTERN_HAIFUN_YMD, DateHelper.FORMAT_PATTERN_SLASH_YMD));
            
            if (ConstTransitManager.TRAIN.equals(categoryCd)) {
                // 鉄道
                entity.startingSpot = (String) map.get(ConstTransitManager.STATION_NAME1);
                entity.arrivalSpot = (String) map.get(ConstTransitManager.STATION_NAME2);
            } else if (ConstTransitManager.BUS.equals(categoryCd)) {
                // バス
                entity.startingSpot = (String) map.get(ConstTransitManager.COMPANY_NAME1);
                entity.arrivalSpot = (String) map.get(ConstTransitManager.COMPANY_NAME1);
            } else if (ConstTransitManager.SALE.equals(categoryCd)) {
                // 物販
                entity.startingSpot = ConstTransitManager.DISP_SALE;
                entity.arrivalSpot = ConstTransitManager.DISP_SALE;
            }
            
            entity.supplement = (String) map.get(ConstTransitManager.MEMO);
            entity.transAmount = (BigDecimal) map.get(ConstTransitManager.PAYMENT);
            entity.companyAmount = (BigDecimal) map.get(ConstTransitManager.PAYMENT);
            entity.companyAmountSum = (BigDecimal) map.get(ConstTransitManager.PAYMENT);
            
            // TMキー
            String tmKey = (String) map.get(ConstTransitManager.USER_NO) + "_"
                    + map.get(ConstTransitManager.USER_CARD_NO) + "_" + map.get(ConstTransitManager.IC_RECORD_ID)
                    + "_0_" + map.get(ConstTransitManager.TM_APPLY_NO);
            entity.relationId = tmKey;
            entity.relationType = "searchTransitManager";
            
            Map<String, Object> camelMap = new HashMap<String, Object>();
            for (String key : map.keySet()) {
                String camelKey = StringUtil.snakeToCamel(key);
                camelMap.put(camelKey, map.get(key));
            }
            entity.relationData = JSON.encode(camelMap);
            
            entityList.add(entity);
            
            tupleId++;
            rowNumber++;
        }
        
        return k30tRouteDetailService.insertBatch(entityList).length;
    }
    
    /**
     * 登録したデータを削除する。
     * 
     * @param args
     * @return 削除件数
     */
    private int deleteTable(Map<String, Object> args) {
        
        Map<String, Object> criteria = new HashMap<String, Object>();
        criteria.put(SYSTEM_MATTER_ID, args.get(SYSTEM_MATTER_ID));
        criteria.put(USER_DATA_ID, args.get(USER_DATA_ID));
        
        List<K30tRouteDetail> entityList = k30tRouteDetailService.genericSelectList(criteria);
        
        return k30tRouteDetailService.deleteBatch(entityList).length;
    }
    
    /**
     * 申請処理.
     * 
     * @param args
     * @return result 申請結果
     * @throws WorkflowException
     */
    private ApplyResultModel apply(Map<String, Object> args) throws WorkflowException {
        ApplyManager applyManager = new ApplyManager();
        
        ApplyParam applyParam = createApplyParam(args);
        
        Map<String, Object> userParam = createUserParam(args);
        Map<String, Object> copyData = new HashMap<String, Object>();
        copyData.put(SYSTEM_MATTER_ID, args.get(SYSTEM_MATTER_ID));
        copyData.put(USER_DATA_ID, args.get(USER_DATA_ID));
        userParam.put("copyTarget", copyData);
        
        // 申請処理
        return applyManager.apply(applyParam, userParam);
        
    }
    
    /**
     * ApplyParamを生成する。.
     * 
     * @param k30mTmAutoApply
     * @param k30mTmAutoUser
     * @return ApplyParam
     */
    private ApplyParam createApplyParam(Map<String, Object> args) {
        ApplyParam applyParam = new ApplyParam();
        
        applyParam.setFlowId("0_test"); // フローID
        applyParam.setMatterName("自動登録"); // 案件名
        applyParam.setApplyBaseDate(dateHelper.getNowStringYYYYMMDD()); // 申請基準日
        applyParam.setApplyAuthUserCode((String) args.get("userCd")); // 申請権限者
        applyParam.setApplyExecuteUserCode((String) args.get("userCd")); // 申請実行者
        applyParam.setApplyAuthCompanyCode((String) args.get("companyCd")); // 権限者会社コード
        applyParam.setApplyAuthOrgzCode("comp_sample_01"); // 権限者組織コード
        applyParam.setApplyAuthOrgzSetCode((String) args.get("companyCd")); // 権限者組織セットコード
        applyParam.setUserDataId(identifierHelper.get()); // ユーザデータID
        
        return applyParam;
    }
    
    /**
     * UserParamを生成する。.
     * 
     * @return UserParam ユーザパラメータ
     */
    private Map<String, Object> createUserParam(Map<String, Object> args) {
        
        Map<String, Object> userParam = new HashMap<String, Object>();
        userParam.put(ImwActionProcessPlugin.SEND_DATA_FLAG, "true");
        userParam.put(ImwActionProcessPlugin.SEARCH_CRITERIA_COMPANY_KEY, args.get("companyCd"));
        userParam.put(ImwActionProcessPlugin.SEARCH_CRITERIA_DATE_KEY, dateHelper.getNowStringYYYYMMDD());
        
        return userParam;
    }
    
    /**
     * 日付形式変換.
     * formatterBefore 形式から formatterAfter 形式へ変換する。
     * dateが空白またはnullの場合、nullを返却する。
     * 
     * @param date 変換したい値
     * @param formatterBefore 変換前フォーマット
     * @param formatterAfter 変換後フォーマット
     * @return
     */
    private String converFormatDate(String date, String formatterBefore, String formatterAfter) {
        if (StringUtil.isEmpty(date)) {
            return null;
        }
        Date payDate = dateHelper.toDate(date, formatterBefore);
        return dateHelper.toFormat(payDate, formatterAfter);
    }
}