<?php 
/** 
 * @version EC=CUBE4 
 * @copyright 株式会社 翔 kakeru.co.jp 
 * @author 
 * 2021年12月20日作成 
 * 
 * app\Customize\Service\CustomerService.php 
 * 
 * LandMark 用 
 * 
 * 
 *                               C= C= C= ┌(;・_・)┘トコトコ 
 ******************************************************/ 
 
namespace Customize\Service; 
 
use Doctrine\ORM\EntityManager; 
use Doctrine\ORM\QueryBuilder; 
use Eccube\Entity\Customer; 
use Eccube\Entity\CustomerAddress; 
use Eccube\Entity\Master\CustomerStatus; 
use Eccube\Entity\Master\Pref; 
use Eccube\Entity\Shipping; 
use Eccube\Repository\CustomerRepository; 
use Lm\Entity\CustomerShippingAddress; 
use Symfony\Component\DependencyInjection\ContainerInterface; 
use Symfony\Component\HttpFoundation\Session\SessionInterface; 
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; 
use Lm\Service\Db\SqlService; 
use Customize\Service\CommonService; 
use Symfony\Component\HttpFoundation\RequestStack; 
 
class CustomerService 
{ 
 
 
    const LM_Customer_Email = 'LM_Customer_Email_'; 
    const MYPAGE_UPDATE_SESSON = 'MYPAGE_UPDATE_SESSON'; 
    const MYPAGE_UPDATE_SESSON_MESSAGE = 'MYPAGE_UPDATE_SESSON_MESSAGE'; 
    const FIRSTLOGINFLG = 'FIRSTLOGINFLG'; 
    const AMAZONPAY_CUSTOMER_LOGIN_FLG = 'AMAZONPAY_CUSTOMER_LOGIN_FLG'; 
    const LM_CUSTOMER_MAdA = ['address3', 'fax', 'melmaga']; 
    const AmazonProfileKey = 'amazon_pay_v2.profile'; 
 
    protected $CustomerRepository; 
    protected $Container; 
    protected $Request; 
    protected $CommonService; 
    protected $Session; 
    protected $encoderFactory; 
 
 
    public function __construct(CustomerRepository $CustomerRepository 
        , ContainerInterface                       $Container 
        , RequestStack                             $RequestStack 
        , SessionInterface                         $session 
        , CommonService                            $CommonService 
        , EncoderFactoryInterface                  $encoderFactory 
    ) 
    { 
        $this->CustomerRepository = $CustomerRepository; 
        $this->Container = $Container; 
        $this->Request = $RequestStack->getCurrentRequest(); 
        $this->CommonService = $CommonService; 
        $this->Session = $session; 
        $this->encoderFactory = $encoderFactory; 
 
    } 
 
    /** 
     * 2021/12/16 kakeru 
     * ランドマーク customerの呼び出し 
     * 
     * @param $Email username 
     */ 
    public function GetLandMarkCustomer($Email, $Pass = null) 
    { 
        $Sql = new SqlService(); 
 
        $Pass = $Pass ?? $this->Request->get('login_pass'); 
 
        $Customer = $Sql->Table('customer_table') 
            ->Set('customer_mail', $Email) 
            ->Set('customer_ddate', null) 
            ->Where('customer_password = SHA1( :Pass )') 
            ->Param(':Pass', $Pass) 
            ->Find(); 
 
        return $this->SetLmCustomerTel($Customer); 
    } 
 
 
    /** 
     * 2021/12/16 kakeru 
     * ランドマーク customerの呼び出し 
     * 
     * @param $Email username 
     */ 
    public function GetLandMarkCustomerEmail($Email) 
    { 
        $Sql = new SqlService(); 
 
 
        $Customer = $Sql->Table('customer_table') 
            ->Set('customer_mail', $Email) 
            ->Set('customer_ddate', null) 
            ->Find(); 
 
        return $this->SetLmCustomerTel($Customer);; 
    } 
 
    /** 
     * 2021/12/23 kakeru 
     * 新規会員登録で ランドマーク側の Email チェック 
     * 
     * @param $Email string 
     */ 
    public function CheckLanEmail($Email) 
    { 
 
        $em = $this->Container->get('doctrine.orm.entity_manager'); 
        $Qb = $em->createQueryBuilder(); 
 
        $Customer = $Qb 
            ->select(['C']) 
            ->from("Eccube\\Entity\\Customer", 'C') 
            ->where('C.email= :Email') 
            ->setParameter('Email', $Email) 
            ->getQuery() 
            ->getResult(); 
        if ($Customer[0] ?? null) { 
            return null; 
        } 
 
        return $this->GetLandMarkCustomerEmail($Email); 
 
    } 
 
    /** 
     * 2021/12/23 kakeru 
     * ランドマーク customerの呼び出し 
     * 
     * @param $Email username 
     */ 
    public function GetLandMarkCustomerId($Id, $Flg = false) 
    { 
        $Sql = new SqlService(); 
 
 
        $Customer = $Sql->Table('customer_table') 
            ->Set('customer_id', $Id) 
            //                       ->Set('customer_ddate',null) 
            ->Find(); 
        if ($Flg) { 
            return $Customer; 
        } 
 
        return $this->SetLmCustomerTel($Customer); 
 
    } 
 
 
    /** 
     * 2021/12/16 kakeru 
     * dtb_customer の登録 
     * 
     * @param $Emai string , 
     * @param $LmCustomer array() 
     */ 
    public function SetCustomer($Customer, $LmCustomer, $Flg = true) 
    { 
 
        $AddFlg = false; 
        if (null === $Customer) { 
            // FIXME: Revert Me!! 
            try { 
                throw new \Exception('[LM]CustomerService::SetCustomer()'); 
            } catch (\Exception $e) { 
                log_warning($e->getMessage(), [ 
                    '$Customer' => $Customer, 
                    '$LmCustomer' => $LmCustomer, 
                    '$Flg' => $Flg, 
                    '$_SERVER' => $_SERVER, 
                    '$_POST' => $_POST, 
                    '$_GET' => $_GET, 
                    'trace' => explode(PHP_EOL, $e->getTraceAsString()), 
                ]); 
            } 
            $Customer = new Customer(); 
            $AddFlg = true; 
        } 
 
        $em = $this->Container->get('doctrine.orm.entity_manager'); 
 
        $CustomerStatus = $em->find(CustomerStatus::class, CustomerStatus::REGULAR); 
 
        $Pref = $em->find(Pref::class, $LmCustomer['customer_prefecture']); 
 
 
        $Customer->setStatus($CustomerStatus) 
            ->setName01($LmCustomer['customer_user_name'] ?? '') 
            ->setName02('') 
            ->setKana01($LmCustomer['customer_user_name_kana'] ?? '') 
            ->setKana02(null) 
            ->setCompanyName($LmCustomer['customer_company']) 
            ->setPostalCode($LmCustomer['customer_postcode']) 
            ->setAddr01($LmCustomer['customer_address1']) 
            ->setAddr02($LmCustomer['customer_address2']) 
            ->setEmail($LmCustomer['customer_mail']) 
            ->setPhoneNumber($LmCustomer['customer_tel']) 
            ->setCompanyKana($LmCustomer['customer_company_kana']) 
            ->setLastNameKana($LmCustomer['customer_last_name_kana']) 
            ->setMobileNumber($LmCustomer['customer_mobile_number']) 
            ->setUniformUsage($LmCustomer['customer_uniform_usage']) 
            ->setUniformUsageOther($LmCustomer['customer_uniform_usage_other']) 
            ->setUniformReplacementFrequency($LmCustomer['customer_uniform_replacement_frequency']) 
            ->setJobCategory($LmCustomer['customer_job_category']) 
            ->setJobSubcategory($LmCustomer['customer_job_subcategory']) 
            ->setCustomerType($LmCustomer['customer_type']) 
            ->setBirth(null) 
            ->setPassword('') 
            ->setSalt(null) 
            ->setSecretKey('') 
 
#                 ->setFirstBuyDate(null) 
#                 ->setLastBuyDate(null) 
#                 ->setBuyTimes(0) 
#                 ->setBuyTotal(0.00) 
 
            ->setNote($LmCustomer['customer_memo']) 
 
            #セキュリティ情報 パスワードリセットを行う 
            ->setSecretKey($this->CustomerRepository->getUniqueSecretKey()) 
            ->setCreateDate($this->CommonService->SetEcTime($LmCustomer['customer_cdate'])) 
            ->setUpdateDate($this->CommonService->SetEcTime($LmCustomer['customer_udate'])) 
            ->setSex(null) 
            ->setJob(null) 
            ->setCountry(null) 
            ->setPref($Pref) 
            ->setPoint(0) 
            ->setLmCustomerId($LmCustomer['customer_id']); 
 
        #LMでログイン済の場合は リセットキーを発行する 
        if ($Flg) { 
            $RetKey = $this->CustomerRepository->getUniqueResetKey(); 
            $Customer->setResetKey($RetKey) 
                ->setResetExpire(new \DateTime('+' . $this->CommonService->GetConfig('eccube_customer_reset_expire') . ' min')); 
        } 
 
        $em->persist($Customer); 
        $em->flush($Customer); 
 
        #新規登録の時だけ 配送先情報を追加する 
        if ($AddFlg) { 
            $this->SetCustomerAdds($Customer, $LmCustomer['customer_id']); 
        } 
 
        #LMでログイン済の場合は sessionに メールアドレスを覚えさせる 
        if ($Flg) { 
            $this->Session->set(self::LM_Customer_Email, $Customer->getEmail()); 
        } 
 
        return [$Customer, ($RetKey ?? null)]; 
 
 
    } 
 
    /** 
     * 2021/12/16 kakeru 
     * 配送先の設定 
     * 
     * @param int $lmCustomerId 
     */ 
    protected function SetCustomerAdds($Customer, $lmCustomerId) 
    { 
 
        if (!($lmCustomer = new \Lm\Entity\Customer($lmCustomerId))) { 
            // 
            return; 
        } 
 
        /** 
         * @var EntityManager $em 
         */ 
        $em = $this->Container->get('doctrine.orm.entity_manager'); 
 
        // 
        foreach ($lmCustomer->getCustomerShippingAddressList() as $lmCustomerShippingAddress) { 
            // 
            $CustomerAddress = (new CustomerAddress()) 
                ->setName01($lmCustomerShippingAddress->getCsaUserName() ?? '') 
                ->setName02('') 
                ->setCompanyName($lmCustomerShippingAddress->getCsaCompany()) 
                ->setPostalCode($lmCustomerShippingAddress->getCsaPostcode()) 
                ->setAddr01($lmCustomerShippingAddress->getCsaAddress1()) 
                ->setAddr02($lmCustomerShippingAddress->getCsaAddress2()) 
                ->setPhoneNumber($lmCustomerShippingAddress->getCsaTel()) 
                ->setCreateDate($this->CommonService->SetEcTime($lmCustomerShippingAddress->getAddDatetime())) 
                ->setUpdateDate($this->CommonService->SetEcTime($lmCustomerShippingAddress->getUpdDatetime())) 
                ->setCustomer($Customer) 
                ->setLmCsaId($lmCustomerShippingAddress->getCsaId()) 
                ->setPref($em->find(Pref::class, $lmCustomerShippingAddress->getCsaPrefecture())) 
            ; 
            // 
            $em->persist($CustomerAddress); 
            $em->flush($CustomerAddress); 
            // 
            $lmCustomerShippingAddress 
                ->setEcCustomerAddressId($CustomerAddress->getId()) 
                ->save() 
            ; 
        } 
    } 
 
    public function GetLmAddressId($CsaId) 
    { 
        $Sql = new SqlService(); 
 
        $Add = $Sql->Table('customer_shipping_address') 
            ->Set('csa_id', $CsaId) 
            ->Find(); 
 
 
        return $this->SetLMCustomerAddressTel($Add); 
 
    } 
 
    /** 
     * LM電話番号からハイフンを取る 
     * @param array Customer 
     * 
     * @return $Customer 
     */ 
    protected function SetLmCustomerTel($Customer) 
    { 
        if (!$Customer) { 
            return $Customer; 
        } 
        $Customer['customer_tel'] = str_replace('-', '', $Customer['customer_tel']); 
 
        return $Customer; 
    } 
 
    /** 
     * LM電話番号からハイフンを取る 
     * @param array Customer 
     * 
     * @return $Customer 
     */ 
    protected function SetLMCustomerAddressTel($Add) 
    { 
 
        if (!$Add) { 
            return $Add; 
        } 
        $Add['csa_tel'] = str_replace('-', '', $Add['csa_tel']); 
 
        return $Add; 
    } 
 
    /** 
     * 2022/02/16 
     * 初回ログインの フラッグをセットする 
     * 0 or null 通常 
     * 1 パスワードnull 
     * 2 初回ログイン 
     * 
     * `@param int $Flg 
     * 
     */ 
    public function SetFirstLoginFlg($Flg) 
    { 
        $SeveFlg = $this->GetFirstLoginFlg() ?? -1; 
 
        if ($SeveFlg >= $Flg) { 
            return; 
        } 
 
        $this->Session->set(self::FIRSTLOGINFLG, $Flg); 
        return; 
    } 
 
    /** 
     * 2022/02/16 
     * 初回ログインの フラッグを取得する 
     * 
     * `@return  int Flg 
     * 
     */ 
    public function GetFirstLoginFlg() 
    { 
        return $this->Session->get(self::FIRSTLOGINFLG); 
    } 
 
    /** 
     * 2022/02/18 
     * アマゾン ペイ CUSTOMER Statuses 
     * 0  すでにログイン  している 
     * 1  アマゾンからの 戻り値ののメールアドレス で顧客を決定 
     * 2  アマゾンIDでの取得 でも取得 
     * 3  LM DATAでの取得 
     * 4  新規会員登録 
     * 
     * 
     * 
     * `@param int $Flg 
     * 
     */ 
    public function SetAmazonLoginFlg($Flg) 
    { 
        $this->Session->set(self::AMAZONPAY_CUSTOMER_LOGIN_FLG, $Flg); 
        return; 
    } 
 
    /** 
     * 2022/02/16 
     * 初回ログインの フラッグを取得する 
     * 
     * `@return  int Flg 
     * 
     */ 
    public function GetAmazonLoginFlg() 
    { 
        //  return 3; 
        return $this->Session->get(self::AMAZONPAY_CUSTOMER_LOGIN_FLG); 
    } 
 
    public function GetAmazonAmazonProfileKey() 
    { 
        return unserialize($this->Session->get(self::AmazonProfileKey)); 
    } 
 
    /** 
     * $LmCustomerId で EC-CUBEのCustomer を取得 及び例外処理 
     * @param int $LmCustomerId 
     * 
     * @return obje $Customer 
     */ 
    public function GetCustomer($LmCustomerId) 
    { 
 
        if (!$Customer = $this->CustomerRepository->findOneBy(['LmCustomerId' => $LmCustomerId, 'Status' => CustomerStatus::REGULAR])) { 
 
            $LmCustomer = $this->GetLandMarkCustomerId($LmCustomerId); 
            list($Customer, $key) = $this->SetCustomer($Customer, $LmCustomer, false); 
        } 
 
        return $Customer; 
    } 
 
    /** 
     *  パスワードの変更をする場合の必要DATAの取得 
     * 
     * @param obje $Customer 
     * @param str $password 
     * 
     * @return array 
     *  1 str $Password 
     *  2 str $salt 
     *  3 str $secretKey 
     */ 
    public function SetPassword($Customer, $Password) 
    { 
 
        $encoder = $this->encoderFactory->getEncoder($Customer); 
        $salt = $encoder->createSalt(); 
        $Password = $encoder->encodePassword($Password, $salt); 
 
        $secretKey = $this->CustomerRepository->getUniqueSecretKey(); 
 
        return [$Password, $salt, $secretKey]; 
 
    } 
 
    /** 
     * @param $customerAddressId 
     * @return array|null 
     * @throws \Doctrine\ORM\NoResultException 
     * @throws \Doctrine\ORM\NonUniqueResultException 
     */ 
    public function getCustomerShippingAddressByCustomerAddressId($customerAddressId) 
    { 
        // 
        $customerShippingAddress = null; 
        // 
        if ($CA = $this->getCustomerAddressById($customerAddressId)) { 
            if ($csaId = $CA->getLmCsaId()) { 
                // 
                $customerShippingAddress = self::getCustomerShippingAddressById($csaId); 
            } 
        } 
        // 
        return $customerShippingAddress; 
    } 
 
    /** 
     * @param Shipping $shipping 
     * @param $fallbackCustomerWhenNotFound 
     * @return string|void 
     * @throws \Exception 
     */ 
    public function getShippingAddr03(Shipping $shipping, $fallbackCustomerWhenNotFound = true) 
    { 
        // TODO: マジックナンバー “12”. 
        if (($payment = $shipping->getOrder()->getPayment()) && $payment->getId() === 12) { 
            // Amazon Payの場合、Amazon Payから渡ってきた送付先情報のみを使用 
            return null; 
        } else if ($ecCustomerAddressId = $shipping->getCustomerAddressId()) { 
            // 別送先の指定あり 
            if ($csa = CustomerShippingAddress::getByEcCustomerAddressId($ecCustomerAddressId)) { 
                // 
                return $csa->getCsaAddress3(); 
            } 
        } else if ($fallbackCustomerWhenNotFound) { 
            // 別送先の指定なし 
            if ($order = $shipping->getOrder()) { 
                if ($customer = $order->getCustomer()) { 
                    if ($lmCustomer = $customer->getLmCustomer()) { 
                        if ($address3 = $lmCustomer->getCustomerAddress3()) { 
                            // 
                            return $address3; 
                        } 
                    } 
                } 
            } 
        } 
    } 
 
    /** 
     * @param $customerAddressId 
     * @return CustomerAddress 
     * @throws \Doctrine\ORM\NoResultException 
     * @throws \Doctrine\ORM\NonUniqueResultException 
     */ 
    public function getCustomerAddressById($customerAddressId) 
    { 
        // 
        $em = $this->Container->get('doctrine.orm.entity_manager'); 
        /** 
         * @var QueryBuilder $Qb 
         * @var CustomerAddress $CA 
         */ 
        $Qb = $em->createQueryBuilder(); 
        $CA  = $Qb 
            ->select('CA') 
            ->from("Eccube\\Entity\\CustomerAddress", 'CA') 
            ->andWhere('CA.id = :id') 
            ->setParameters([ 
                'id' => $customerAddressId, 
            ]) 
            ->getQuery() 
            ->getOneOrNullResult(); 
        // 
        return $CA; 
    } 
 
    /** 
     * @param $csaId 
     * @return array|null 
     */ 
    public static function getCustomerShippingAddressById($csaId) 
    { 
        return (new SqlService()) 
            ->Table('customer_shipping_address') 
            ->Set('csa_id', $csaId) 
            ->Find() 
            ; 
    } 
 
    /** 
     * Get customer's company name filter 
     */ 
    public function getNotAllowedCompanies() 
    { 
        $notAllowedCompanies = (new SqlService()) 
            ->Sql('SELECT filter_customer_name FROM customer_name_filter_table') 
            ->Fetch(); 
 
        if (empty($notAllowedCompanies['filter_customer_name'])) { 
            return []; 
        } 
 
        $notAllowedCompanies = explode("\r\n", $notAllowedCompanies['filter_customer_name']); 
        $notAllowedCompanies = array_map(function ($notAllowedCompany) { 
            return trim($notAllowedCompany); 
        }, $notAllowedCompanies); 
        $notAllowedCompanies = array_filter($notAllowedCompanies, function ($notAllowedCompany) { 
            return !empty($notAllowedCompany); 
        }); 
 
        return $notAllowedCompanies; 
    } 
 
    /** 
     * @param $value 
     * @param \Eccube\Entity\Customer|\Lm\Entity\Customer|null $user 
     * @return bool 
     * @throws \Exception 
     */ 
    public function isValidCustomerBangou($value, $user = null) 
    { 
        // 
        if ($user === null) { 
            // 
            $user = $this->CommonService->getUser(); 
        } 
        // 
        if ($user instanceof \Eccube\Entity\Customer) { 
            // 
            $customer = $user->getLmCustomer(); 
        } else if ($user instanceof \Lm\Entity\Customer) { 
            // 
            $customer = $user; 
        } else { 
            // 
            return false; 
        } 
        // 
        return (((int)$value) === $customer->getCustomerBangou()); 
    } 
 
}