<?php

namespace Plugin\ApteqPeriodical;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Plugin\ApteqPeriodical\Entity\Periodical;
use Plugin\ApteqPeriodical\Entity\PeriodicalDetail;
use Plugin\ApteqPeriodical\Entity\PeriodicalShipping;
use Plugin\ApteqPeriodical\Repository\PeriodicalRepository;
use Plugin\ApteqPeriodical\Repository\PeriodicalDetailRepository;
use Plugin\ApteqPeriodical\Repository\PeriodicalShippingRepository;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Eccube\Event\TemplateEvent;
use Eccube\Service\OrderHelper;
use Eccube\Entity\Order;
use Eccube\Entity\Shipping;

use Plugin\RemisePayment4\Entity\OrderResult;
use Plugin\RemisePayment4\Entity\OrderResultCard;
use Plugin\RemisePayment4\Entity\RemiseACMember;
use Plugin\RemisePayment4\Entity\RemiseACResult;
use Plugin\RemisePayment4\Repository\OrderResultCardRepository;
use Plugin\RemisePayment4\Repository\RemiseACMemberRepository;

/**
 * 管理画面：受注一覧　定期購入継続状況で検索
 *
 * Class ApteqPeriodicalEvent　
 * @package Plugin\ApteqPeriodical
 */
class ApteqPeriodicalEvent implements EventSubscriberInterface
{
    
    /**
     * @var EntityManagerInterface
     */
    private $entityManager;
    
    /**
     * @var PeriodicalRepository
     */
    protected $periodicalRepository;
    
    /**
     * @var PeriodicalDetailRepository
     */
    protected $periodicalDetailRepository;
    
    /**
     * @var PeriodicalShippingRepository
     */
    protected $periodicalShippingRepository;
    
    /**
     * @var OrderResultCardRepository
     */
    protected $orderResultCardRepository;
    
    /**
     * @var RemiseACMemberRepository
     */
    protected $remiseACMemberRepository;
    
    /**
     * @var OrderHelper
     */
    private $orderHelper;

    /**
     * PeriodicalController constructor.
     *
     * @param PeriodicalRepository $periodicalRepository
     * @param PeriodicalDetailRepository $periodicalDetailRepository
     * @param PeriodicalShippingRepository $periodicalShippingRepository
     * @param OrderResultCardRepository $orderResultCardRepository
     * @param RemiseACMemberRepository $remiseACMemberRepository
     * @param OrderHelper $orderHelper
     * 
     */
    public function __construct(
        EntityManagerInterface $entityManager,
        PeriodicalRepository $periodicalRepository,
        PeriodicalDetailRepository $periodicalDetailRepository,
        PeriodicalShippingRepository $periodicalShippingRepository,
        OrderResultCardRepository $orderResultCardRepository,
        RemiseACMemberRepository $remiseACMemberRepository,
        OrderHelper $orderHelper
    ) {
        $this->entityManager = $entityManager;
        $this->periodicalRepository = $periodicalRepository;
        $this->periodicalDetailRepository = $periodicalDetailRepository;
        $this->periodicalShippingRepository = $periodicalShippingRepository;
        $this->orderResultCardRepository = $orderResultCardRepository;
        $this->remiseACMemberRepository = $remiseACMemberRepository;
        $this->orderHelper = $orderHelper;
    }
    
    
    public static function getSubscribedEvents()
    {
        return [
            '@admin/Order/index.twig' => 'onRenderAdminOrderIndexTwig',
            '@admin/Order/edit.twig' => 'onRenderAdminOrderEditTwig',
            EccubeEvents::ADMIN_ORDER_EDIT_INDEX_COMPLETE => 'onAdminOrderEditIndexComplete',
            EccubeEvents::FRONT_SHOPPING_COMPLETE_INITIALIZE => 'onFrontShoppingCompleteInitialize'
        ];
    }
    /**
    * 管理画面：受注一覧　検索欄に定期購入継続状況を追加する.        
    *
    * @param TemplateEvent $event
     */
    public function onRenderAdminOrderIndexTwig(TemplateEvent $event)
    {        
        $event->addSnippet('@ApteqPeriodical/admin/Order/periodical_index.twig');
    }
    
    /**
     * 管理画面：受注登録画面に定期購入情報登録フォームを表示する.
     *
     * @param TemplateEvent $event
     */
    public function onRenderAdminOrderEditTwig(TemplateEvent $event)
    {    
        $parameters = $event->getParameters();
        
        $Order = $parameters['Order'];
        $OrderItems = $Order['OrderItems'];
        $Shippings = $Order['Shippings'];
        $Customer = $Order['Customer'];
        
        $saletype = $Order->getSaleTypes();
        
        if($saletype) {
            $saletype_id = $saletype[0]['id'];
        } else {
            $saletype_id = null;
        }

        if ($saletype_id == 5) { // 定期購買
            
            $order_id = $Order['id'];
            $result = $this->periodicalDetailRepository->searchByOrderId($order_id);
            
            if (count($result) != 0) {
                $PeriodicalDetail = $result[0];

                if ($PeriodicalDetail) {
                    $periodical_id = $PeriodicalDetail->getPeriodicalId();
                    $result2 = $this->periodicalRepository->searchByPeriodicalId($periodical_id);
                    $Periodical = $result2[0];
                    
                    $count = $this->periodicalDetailRepository->countPeriodicalDetail($periodical_id, $PeriodicalDetail->getId());
                    $total_count = $this->periodicalDetailRepository->countTotalPeriodicalDetail($periodical_id);

                    if ($Periodical) {
                        $parameters['Periodical'] = $Periodical;
                        $parameters['PeriodicalDetail'] = $PeriodicalDetail;
                        $parameters['count'] = $count;
                        $parameters['total_count'] = $total_count;
                        
                        $event->setParameters($parameters);            

                        $event->addSnippet('@ApteqPeriodical/admin/Order/periodical.twig');
                    }
                }
            }
        }

    }    
    
    /**
     * 管理画面：次回定期情報登録時に定期購入情報をDB登録
     *          受注情報更新時・受注情報新規登録時もここを通る！
     *
     * @param EventArgs $event
     */
    public function onAdminOrderEditIndexComplete(EventArgs $event)
    {
        //$Order = new Order();
        $OriginOrder = $event->getArgument('OriginOrder');
        $Order = $event->getArgument('TargetOrder');
        $basic_order_id = $event->getArgument('basic_order_id'); 
        
        //dump($OriginOrder);exit;
        
        $this->registerPeriodical($Order, $basic_order_id);
    }
    
    
    
    /**
     * フロント画面：購入完了時に定期購入情報をDB登録
     *
     * @param EventArgs $event
     */
    public function onFrontShoppingCompleteInitialize(EventArgs $event)
    {    
        //$Order = new Order();
        $Order = $event->getArgument('Order');

        $this->registerPeriodical($Order, null);        
    }
    
    /**
     * 定期購入情報をDB登録
     *
     * @param Eccube\Entity\Order $Order
     *          int $basic_order_id
     */
    public function registerPeriodical(\Eccube\Entity\Order $Order, int $basic_order_id = null)
    {
        $Periodical = new Periodical();
        $PeriodicalDetail = new PeriodicalDetail();
        
        $saletype = $Order->getSaleTypes();
        if($saletype) {
            $saletype_id = $saletype[0]['id'];
        } else {
            $saletype_id = null;
        }
        
        if ($saletype_id == 5) { // 定期購買
            
            $OrderItems = $Order->getOrderItems();
            foreach ($OrderItems as $OrderItem) {
                if ($OrderItem->isProduct()) {
                    // $ProductClass = $OrderItems[0]->getProductClass();
                    // 2022.04 購入商品変更時のエラー対応
                    $ProductClass = $OrderItem->getProductClass();
                }
            }
            $Shippings = $Order->getShippings();
            $Customer = $Order->getCustomer();
            
            if ($basic_order_id == null) { // 新規登録の場合
                // 2021.05 お届け希望日ではなく、発送予定日を定期受注複製時の基準にするように変更
                // お届け希望日指定なしの場合は注文日を定期の今回発送予定日とする
                $this_shipping_date = $Shippings[0]->getShippingDeliveryDate();
                if ($this_shipping_date) {
                    $this_shipping_schedule_date = $this_shipping_date->modify('-1 days');
                } else {
                    $this_shipping_schedule_date = $Order->getCreateDate();
                }
            
                // 定期情報作成
                if ($Customer) {
                    $Periodical -> setCustomerId($Customer->getId());
                } else { // 非会員の場合
                    $Periodical -> setCustomerId(null);
                }
                $Periodical -> setPeriodicalStatus(1); // 継続中
                $Periodical -> setFirstOrderDate($Order->getCreateDate());
                $Periodical -> setShippingInterval(1); // お届け間隔・1→１カ月
                $Periodical -> setPaymentTotal($Order->getPaymentTotal());
                $Periodical -> setProductId($ProductClass->getProduct()->getId());
                $Periodical -> setProductClassId($ProductClass->getId());
                //$Periodical -> setProductName($OrderItems[0]['product_name']);
                $Periodical -> setClassCategoryName01($OrderItems[0]->getClassCategoryName1());
                $Periodical -> setClassCategoryName02($OrderItems[0]->getClassCategoryName2());
                $Periodical -> setNote($Order->getNote());
                $Periodical -> setCountry($Order->getCountry());
                $Periodical -> setPref($Order->getPref());
                $Periodical -> setName01($Order->getName01());
                $Periodical -> setName02($Order->getName02());
                $Periodical -> setKana01($Order->getKana01());
                $Periodical -> setKana02($Order->getKana02());
                $Periodical -> setEmail($Order->getEmail());
                $Periodical -> setPhoneNumber($Order->getPhoneNumber());
                $Periodical -> setPostalCode($Order->getPostalCode());
                $Periodical -> setAddr01($Order->getAddr01());
                $Periodical -> setAddr02($Order->getAddr02());
                //$Periodical -> setShippingTime($Shippings[0]->getShippingDeliveryName());
                $Periodical -> setShippingTime($Shippings[0]->getShippingDeliveryTime());
                $Periodical -> setCreateDate($Order->getCreateDate());
                $Periodical -> setUpdateDate($Order->getCreateDate());

                $this->entityManager->persist($Periodical);
                $this->entityManager->flush();
                
                $PeriodicalDetail -> setPeriodicalId($Periodical->getId());
                $PeriodicalDetail -> setOrderId($Order->getId());                
                // 2021.05 変更　お届け希望日じゃなくて、発送予定日を基準にする
                // 新規の定期購入受注時は注文日を今回発送予定日とする
                $PeriodicalDetail -> setThisShippingDate($this_shipping_schedule_date);
                $PeriodicalDetail -> setNextShippingDate($this->periodicalDetailRepository -> makeNextShippingDate($this_shipping_schedule_date));            
                $PeriodicalDetail -> setCreateDate($Order->getCreateDate());
                $PeriodicalDetail -> setUpdateDate($Order->getCreateDate());
                
                //dump($PeriodicalDetail);exit;
                
                $this->entityManager->persist($PeriodicalDetail);
                
            } else {    // 受注情報更新・次回受注情報作成の場合（定期情報がすでにある）
                
                $result = $this->periodicalDetailRepository->searchByOrderId($basic_order_id);            
                if (count($result) != 0) {
                    $result2 = $this->periodicalRepository->searchByPeriodicalId($result[0]->getPeriodicalId());
                    $Periodical = $result2[0];                    
                    
                    if ($basic_order_id != $Order->getId()) {   // 次回受注情報作成の場合
                        $PeriodicalDetail -> setPeriodicalId($Periodical->getId());
                        $PeriodicalDetail -> setOrderId($Order->getId());
                        $PeriodicalDetail -> setLastShippingDate($result[0]->getThisShippingDate());
                        $PeriodicalDetail -> setThisShippingDate($this->periodicalDetailRepository -> makeNextShippingDate($PeriodicalDetail -> getLastShippingDate()));
                        $PeriodicalDetail -> setNextShippingDate($this->periodicalDetailRepository -> makeNextShippingDate($PeriodicalDetail -> getThisShippingDate()));            
                        $PeriodicalDetail -> setCreateDate($Order->getCreateDate());
                        $PeriodicalDetail -> setUpdateDate($Order->getCreateDate());

                        $this->entityManager->persist($PeriodicalDetail);
                        
                        // お届け希望日設定・発送予定日クリア
                        // 2021.05 お届け希望日ではなく発送予定日を設定するように変更
                        $Shippings[0]->setShippingDeliveryDate(null);
                        $Shippings[0]->setShippingScheduleDate($PeriodicalDetail -> getThisShippingDate());
                        
                        $this->entityManager->persist($Shippings[0]);
                        
                        //dump($Shippings[0]);exit;
                        
                        // カード支払いの場合ルミーズ関連テーブルに登録(「カード情報を更新する」表示のため)　2021.1
                        $payment_id = $Order->getPayment()->getId();
                        if ($payment_id == '32' or $payment_id == '6') {
                            $this->registerRemisePeriodical($Order, $basic_order_id);
                        }
                        
                    } else {    // 受注情報更新の場合
                        //$PeriodicalDetail　= $result[0]; //コピーできない？
                        
                        $Periodical -> setPaymentTotal($Order->getPaymentTotal());
                        $Periodical -> setProductId($ProductClass->getProduct()->getId());
                        $Periodical -> setProductClassId($ProductClass->getId());
                        //$Periodical -> setProductName($OrderItems[0]['product_name']);
                        
                        // 更新時は商品が$OrderItems[0]でない場合があるため全部チェックする
                        // 定期商品は一度に一種類しか買えない
                        foreach ($OrderItems as $OrderItem_tmp) {
                            if ($OrderItem_tmp->isProduct()) {                                
                                $Periodical -> setClassCategoryName01($OrderItem_tmp->getClassCategoryName1());
                                $Periodical -> setClassCategoryName02($OrderItem_tmp->getClassCategoryName2());
                            }
                        }
                        
                        $Periodical -> setNote($Order->getNote());
                        $Periodical -> setCountry($Order->getCountry());
                        $Periodical -> setPref($Order->getPref());
                        $Periodical -> setName01($Order->getName01());
                        $Periodical -> setName02($Order->getName02());
                        $Periodical -> setKana01($Order->getKana01());
                        $Periodical -> setKana02($Order->getKana02());
                        $Periodical -> setEmail($Order->getEmail());
                        $Periodical -> setPhoneNumber($Order->getPhoneNumber());
                        $Periodical -> setPostalCode($Order->getPostalCode());
                        $Periodical -> setAddr01($Order->getAddr01());
                        $Periodical -> setAddr02($Order->getAddr02());
                        //$Periodical -> setShippingTime($Shippings[0]->getShippingDeliveryName());
                        $Periodical -> setShippingTime($Shippings[0]->getShippingDeliveryTime());
                        $Periodical -> setUpdateDate($Order->getUpdateDate());
                        
                        //dump($Periodical);exit; 
                        $this->entityManager->persist($Periodical);
                        
                        // 2021.05 お届け希望日ではなく発送予定日を設定するように変更
                        if($Shippings[0]->getShippingScheduleDate() && ($Shippings[0]->getShippingScheduleDate() != $result[0] -> getThisShippingDate())) {
                            $result[0] -> setThisShippingDate($Shippings[0]->getShippingScheduleDate());
                            $result[0] -> setNextShippingDate($this->periodicalDetailRepository -> makeNextShippingDate($Shippings[0]->getShippingScheduleDate()));
                        }
                        
                        $result[0]->setUpdateDate($Order->getUpdateDate());

                        $this->entityManager->persist($result[0]);
                        //dump($result);exit;                    
                    }              
                }
            }
            
            $this->entityManager->flush();
        }
    }
    
    /**
     * ルミーズ定期情報をDB登録
     *
     * @param Eccube\Entity\Order $Order
     *          int $basic_order_id
     */
    public function registerRemisePeriodical(\Eccube\Entity\Order $Order, int $basic_order_id = null)
    {
        $OrderResult = new OrderResult();
        $OrderResultCard = new OrderResultCard();
        $RemiseACMember = new RemiseACMember();
        $RemiseACResult = new RemiseACResult();
        
        $OrderResult->setId($Order->getId());
        $OrderResult->setKind(1);
        $OrderResult->setPaymentId(32);
        $OrderResult->setPaymentTotal($Order->getPaymentTotal());
        $OrderResult->setCreateDate($Order->getCreateDate());
        $OrderResult->setUpdateDate($Order->getCreateDate());        
        
        $result_card = $this->orderResultCardRepository->findById($basic_order_id);
        
        $OrderResultCard->setId($Order->getId());
        $OrderResultCard->setState(3);
        //$OrderResultCard->setJob('AUTH');
        if($result_card) {
            $OrderResultCard->setCardParts($result_card[0]->getCardParts());
            $OrderResultCard->setExpire($result_card[0]->getExpire());
            $OrderResultCard->setMemberId($result_card[0]->getMemberId());
        }
        $OrderResultCard->setACTotal($Order->getPaymentTotal());
        $OrderResultCard->setCreateDate($Order->getCreateDate());
        $OrderResultCard->setUpdateDate($Order->getCreateDate());
        
        //　さくらサーバーのCRON利用で次回課金日をチェックする仕様に変更したため、ここでは次回課金日を設定しない
        // 2021.07 変更
//        // 2021.05,2021.06,2021.07　追記
//        // カード情報更新は「次回課金日」（next_date）が未来の日付でないとできない。
//        // そのため、次回定期受注を作成する際に next_date に interval_value（課金間隔）をプラスした次回課金日を登録する。
//        // カード情報更新時に次回課金日が使われる。
//        $result_ac_member = $this->remiseACMemberRepository->findById($result_card[0]->getMemberId());
//        $today = new \DateTime();
//        
//        if($result_ac_member[0]->getNextDate() < $today) {
//        // 次回課金日が過去の日付だったら未来の日付に変更
//            $interval = $result_ac_member[0]->getIntervalValue();
//            $plus = ' +'.$interval.' month';
//            $next_date_day = $result_ac_member[0]->getNextDate()->format('d');
//            $next_date = $result_ac_member[0]->getNextDate()->format('Y-m')."-".$next_date_day.$plus;
//            $next_date_year = date('Y', strtotime($next_date));
//            $next_date_month = date('m', strtotime($next_date));
//
//            $dt = $next_date_year."/".$next_date_month."/".$next_date_day;
//            $next_date = new \DateTime($dt);
//            $result_ac_member[0]->setNextDate($next_date);
//            
//            $this->entityManager->persist($result_ac_member[0]);
//        }
//        // 2021.05,2021.06,2021.07　追記 ここまで
        
        $RemiseACResult->setId($Order->getId());
        $RemiseACResult->setResult(2); // 0:失敗　1:成功　2~8:- 9:初回購入
        $RemiseACResult->setChargeDate($Order->getCreateDate());
        $RemiseACResult->setCreateDate($Order->getCreateDate());
        $RemiseACResult->setUpdateDate($Order->getCreateDate());
        
//            dump($OrderResult);
//            dump($OrderResultCard);
//            dump($RemiseACResult);
//            exit;
        
        $this->entityManager->persist($OrderResult);
        $this->entityManager->persist($OrderResultCard);
        $this->entityManager->persist($RemiseACResult);    
    }
}
