package jp.agentec.sinaburocast.action.user;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.mail.MessagingException;

import org.apache.log4j.Logger;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.TokenProcessor;
import org.seasar.framework.util.StringUtil;
import org.seasar.struts.annotation.ActionForm;
import org.seasar.struts.annotation.Execute;

import jp.agentec.sinaburocast.action.AbstractAction;
import jp.agentec.sinaburocast.common.SinaburoConstant;
import jp.agentec.sinaburocast.common.SinaburoConstant.UserType;
import jp.agentec.sinaburocast.common.SinaburoConstant.giftExchangeHiddenDate;
import jp.agentec.sinaburocast.common.util.MailUtil;
import jp.agentec.sinaburocast.common.util.PropertyUtil;
import jp.agentec.sinaburocast.common.util.SinaburoUtil;
import jp.agentec.sinaburocast.common.util.SinaburoViewUtil;
import jp.agentec.sinaburocast.entity.Gift;
import jp.agentec.sinaburocast.entity.GiftExchangeInfo;
import jp.agentec.sinaburocast.entity.Member;
import jp.agentec.sinaburocast.entity.Message;
import jp.agentec.sinaburocast.entity.Prefecture;
import jp.agentec.sinaburocast.form.user.PointUseForm;
import jp.agentec.sinaburocast.service.GiftExchangeInfoService;
import jp.agentec.sinaburocast.service.GiftService;
import jp.agentec.sinaburocast.service.MemberCardReceiptService;
import jp.agentec.sinaburocast.service.MemberService;
import jp.agentec.sinaburocast.service.MessageService;
import jp.agentec.sinaburocast.service.PointGetService;
import jp.agentec.sinaburocast.service.PrefectureService;

/**
 * ポイント利用
 *
 * @author choi-c
 *
 */
public class PointUseAction extends AbstractAction {
	private final Logger logger = Logger.getLogger(getClass());

	@ActionForm
	public PointUseForm pointUseForm;

	public MemberService memberService;
	public GiftExchangeInfoService  giftExchangeInfoService;
	public MessageService messageService;
	public GiftService giftService;
	public PointGetService pointGetService;
	public PrefectureService prefectureService;
	public MemberCardReceiptService memberCardReceiptService;

	/**
	 * 初期表示
	 * @throws ParseException 
	 */
	@Execute(validator = false)
	public String index() throws ParseException{

		Member member = getMember();
		if(member == null){
			return "/user/login/";
		}
		// 最新のユーザー情報を取得
		member = memberService.findById(member.memberId);
		super.setAuthenticatedToken(member, UserType.USER);
		
		if (StringUtil.isBlank(member.zipCode) || member.prefectureId == null || StringUtil.isBlank(member.cityName) || StringUtil.isBlank(member.areaName) || StringUtil.isBlank(member.telno)
				|| StringUtil.isBlank(member.firstName) || StringUtil.isBlank(member.lastName) || StringUtil.isBlank(member.firstNameKana) || StringUtil.isBlank(member.lastNameKana)
				|| StringUtil.isBlank(member.birthday)) {

			ActionMessages messages = (ActionMessages)request.getAttribute(Globals.ERROR_KEY);

			if (messages == null) {
				messages = new ActionMessages();
			}
			messages.add("pointUse", new ActionMessage(SinaburoViewUtil.getMessage("errors.E050")));
			request.setAttribute(Globals.ERROR_KEY, messages);
			session.setAttribute("pointCheckFlg", true);

			return "/user/userEdit/";
		}

		// ポイント交換利用方法取得
		pointUseForm.giftExchangeInfoList = giftExchangeInfoService.findGiftExchangeInfoList();

		// 現在日付を取得し、ICHICOポイントの交換リンクを表示するか判定する
		Date currentDate = new Date();
		Date hideDate = new SimpleDateFormat("yyyy/MM/dd").parse(giftExchangeHiddenDate.ICHICO_HIDE_DATE);
		if(currentDate.before(hideDate)) {
			pointUseForm.ichicoHide = false;
		} else {
			pointUseForm.ichicoHide = true;
		}
		
        return "/user/pointUse/pointUseIndex.html";
	}

	/**
	 * 期間内か判定し、ポイントセット画面へ遷移
	 * @return
	 * @throws IOException 
	 */
	@Execute(validator = false)
	public String pointUse() throws IOException{
		
		String giftExchangeInfoIdStr = request.getParameter("giftExchangeInfoId");
		Integer giftExchangeInfoId = -1;
		if(giftExchangeInfoIdStr.isEmpty()) {
			request.setAttribute("errMsg", SinaburoViewUtil.getMessage("errors.E000"));
			return "/error/errorMsg.html";
		}
		giftExchangeInfoId = Integer.parseInt(giftExchangeInfoIdStr);
		// IDからポイント交換タイプを格納
		pointUseForm.giftType = (giftExchangeInfoId == SinaburoConstant.giftType.ECOBO) ? SinaburoConstant.giftType.ECOBO : SinaburoConstant.giftType.ICHICO;
		
		// プルダウンセット
		GiftExchangeInfo giftExchangeInfo = giftExchangeInfoService.findGiftExchangeInfoById(giftExchangeInfoId);

		// ポイント交換期間外はエラー
		if(!(Integer.parseInt(giftExchangeInfo.startDate) <= Integer.parseInt(SinaburoUtil.getToDayString()) &&
			   Integer.parseInt(giftExchangeInfo.endDate) >= Integer.parseInt(SinaburoUtil.getToDayString()) )){
			
			request.setAttribute("errMsg", giftExchangeInfo.expiredMessage);
			return "/error/errorMsg.html";
		}

		// ICHICOポイント交換の場合、一度会員情報入力画面に遷移させる
		if(giftExchangeInfoId == SinaburoConstant.giftType.ICHICO && !pointUseForm.uEditEndFlg) {
			redirect("/user/userEdit/?pointUseFlg=true");
			return null;
		}
		// ポイント交換用プルダウン取得
		pointUseForm.giftList = giftService.findByGiftType(pointUseForm.giftType);

        return "/user/pointUse/pointUse.html";
	}

	/**
	 * 交換ポイント確認
	 * @return
	 */
	@Execute(validator = false)
	public String confirm()  {
		
		Member member = getMember();
		if(member == null){
			return "/user/login/";
		}

		// ポイント情報取得
		Gift gift = giftService.findById(Integer.parseInt(pointUseForm.giftId));
		//選択した枚数が保有ポイント数より少ない場合
		if( member.pointNum < gift.requiredPoint){
			addError(SinaburoViewUtil.getMessage("errors.E013"));
			return "/user/pointUse/pointUse.html";
		}
		
		if(SinaburoConstant.giftType.ICHICO.equals(pointUseForm.giftType)) {
			// ICHICOポイント会員番号入力画面
			return "/user/pointUse/memberConfirm.html";
		} else {
			TokenProcessor.getInstance().saveToken(request);
			// ポイント交換申請確認画面
			return "/user/pointUse/pointUseConfirm.html";
		}
	}

	/**
	 * 会員番号確認(ICHICOポイント交換時のみ)
	 * @return
	 */
	@Execute(validator = false)
	public String memberConfirm()  {
		
		// 未入力
		if(pointUseForm.memberNum.isEmpty()) {
			addError(SinaburoViewUtil.getMessage("errors.E067"));
		}else {
			// 半角数字ではない
			if(!pointUseForm.memberNum.matches("^[0-9]+$")) {
				addError(SinaburoViewUtil.getMessage("errors.E068"));
			}
			// 8桁ではない
			if(pointUseForm.memberNum.length() != 8) {
				addError(SinaburoViewUtil.getMessage("errors.E069"));
			}
		}
		// エラーがあるならリターン
		if(hasErrors()) {
			return "/user/pointUse/memberConfirm.html";
		}
		
		TokenProcessor.getInstance().saveToken(request);
		// ポイント交換申請確認画面
		return "/user/pointUse/pointUseConfirm.html";
	}
	
	
	/**
	 * 会員登録方法ページ
	 * @return
	 * @throws ParseException 
	 */
	@Execute(validator = false)
	public String memberRegistPage() throws ParseException {
		
		// 当月を取得
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM");
		String [] currentYearMonth = sdf.format(SinaburoUtil.getTimestamp()).split("/");
		// 申請済みか判定
		if(memberCardReceiptService.findByMemberIdAndMonth(getMember().memberId, currentYearMonth[0], currentYearMonth[1])){
			request.setAttribute("errMsgForMemberCardReceipt", SinaburoViewUtil.getMessage("errors.E070"));
			return "/user/pointUse/memberConfirm.html";
		}
		
		// 現在日付を取得し、会員カード郵送申請ボタンを表示するか判定する
		Date currentDate = new Date();
		Date hideDate = new SimpleDateFormat("yyyy/MM/dd").parse(giftExchangeHiddenDate.MEMBER_CARD_RECEIPT_HIDE_DATE);
		if(currentDate.before(hideDate)) {
			pointUseForm.memberCardReceiptHide = false;
		} else {
			pointUseForm.memberCardReceiptHide = true;
		}
		
		return "/user/pointUse/memberRegistPage.html";
	}
	
	/**
	 * 郵送先確認
	 * @return
	 */
	@Execute(validator = false)
	public String confirmOfAddress() {

		Member member = getMember();
		if(member == null){
			return "/user/login/";
		}
		// 最新のユーザー情報を取得
		member = memberService.findById(member.memberId);
		if(member.prefectureId != null) {
			Prefecture prefecture = prefectureService.findNameById(member.prefectureId);
			member.prefecture = prefecture;
		}
		// 住所をセット
		request.setAttribute("member", member);
		TokenProcessor.getInstance().saveToken(request);
		return "/user/pointUse/confirmOfAddress.html";
	}
	
	/**
	 * 郵送受付の完了メールを送信する
	 * @return
	 */
	@Execute(validator = false)
	public String sendEmailForMemberCardReceipt() throws UnsupportedEncodingException, MessagingException {
		
		Member member = getMember();
		if(member == null){
			return "/user/login/";
		}	
		member = memberService.findById(member.memberId);
		
		// カード郵送申請情報をDBに登録する
		memberCardReceiptService.insertMemberCardReceipt(member);
		
		//メール送信
		try {
			Message message = messageService.findById(SinaburoConstant.MessageCode.MEMBER_CARD_RECEIPT);
			if (!StringUtil.isBlank(member.mainPcEmail)) {
				MailUtil.send(member.mainPcEmail, PropertyUtil.getProperty("MEMBER_CARD_RECEIPT_MAIL_TITLE"), message.message);
			}
			if (!StringUtil.isBlank(member.subPcEmail)) {
				MailUtil.send(member.subPcEmail, PropertyUtil.getProperty("MEMBER_CARD_RECEIPT_MAIL_TITLE"), message.message);
			}
		} catch (MessagingException e) {
			logger.warn("Mail send failed." + e.toString());
			addError(SinaburoViewUtil.getMessage("errors.E055"));
			return "/user/pointUse/confirmOfAddress.html";
		}
		
		return "/user/pointUse/memberCardReceiptEnd.html";
	}

	/**
	 * ポイント交換申請ボタン押下
	 * @return 遷移先パス。
	 * @throws MessagingException
	 * @throws UnsupportedEncodingException
	 */
	@Execute(validator = false, validate = "validate", input="/error/doubleAction.html")
	public String regist() throws UnsupportedEncodingException, MessagingException  {

		Member member = getMember();
		if(member == null){
			return "/user/login/";
		}
		member = memberService.findById(member.memberId);
		Gift gift = giftService.findById(Integer.parseInt(pointUseForm.giftId));

		// 選択した枚数が保有ポイント数より少ない場合
		if (member.pointNum < gift.requiredPoint) {
			getMember().pointNum = member.pointNum;
			addError(SinaburoViewUtil.getMessage("errors.E013"));
			return "/user/pointUse/pointUse";
		}
		
		// 会員番号更新
		if(SinaburoConstant.giftType.ICHICO.equals(pointUseForm.giftType)) {
			member.memberNum = pointUseForm.memberNum;
		}
		
		//2.ユーザのポイント数より消費ポイント数を減算しDBに登録する。
		//3.ポイント交換申請情報をDBに登録する。
		pointGetService.cutDownPointLogic(gift,member);
		getMember().pointNum = member.pointNum;

		//メール送信
		try {
			GiftExchangeInfo giftExchangeInfo = new GiftExchangeInfo();
			if(SinaburoConstant.giftType.ECOBO.equals(pointUseForm.giftType)) {
				giftExchangeInfo = giftExchangeInfoService.findGiftExchangeInfoById(SinaburoConstant.giftType.ECOBO);
			} else {
				giftExchangeInfo = giftExchangeInfoService.findGiftExchangeInfoById(SinaburoConstant.giftType.ICHICO);
			}
			if (!StringUtil.isBlank(member.mainPcEmail)) {
				MailUtil.send(member.mainPcEmail, PropertyUtil.getProperty("POINT_USE_MAIL_TITLE"), giftExchangeInfo.mailBody);
			}
			if (!StringUtil.isBlank(member.subPcEmail)) {
				MailUtil.send(member.subPcEmail, PropertyUtil.getProperty("POINT_USE_MAIL_TITLE"), giftExchangeInfo.mailBody);
			}
		} catch (MessagingException e) {
			logger.warn("Mail send failed." + e.toString());
			addError(SinaburoViewUtil.getMessage("errors.E055"));
			return "/user/pointUse/pointUse.html";
		}
		
		//ポイント交換完了画面
		return "/user/pointUse/pointUseEnd.html";
	}

	/**
	 * 二度押し検証
	 *
	 * @return
	 */
	public ActionMessages validate() {
		ActionMessages errors = new ActionMessages();

		// トークン確認
   		if (!TokenProcessor.getInstance().isTokenValid(request, true)) {
   			errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("errors.invalid", "Token"));
    	}

   		return errors;
	}
	
}