<?php

namespace App\Http\Controllers\Api\Customers;

use App\Common\Http;
use App\Http\Requests\Customer\Api\CustomerLoginViaAlipayRequest;
use App\Modules\Enums\ErrorCode;
use App\Exceptions\Api\ApiException;
use App\Http\Controllers\Controller;
use App\Http\Requests\Customer\Api\CustomerLoginRequest;
use App\Http\Requests\Customer\Api\CustomerLoginViaSmsRequest;
use App\Http\Requests\Customer\Api\QiniuCallbackRequest;
use App\Http\Requests\Customer\Api\SmsRequest;
use App\Http\Requests\Customer\Api\StoreCustomerRequest;
use App\Http\Requests\Customer\Api\UpdateCustomerPasswordRequest;
use App\Modules\Models\Customer\Customer;
use App\Repositories\Customers\CustomerRepository;
use App\Util\PhoneUtil;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;

/**
 * Class CustomerController
 * @package App\Http\Controllers\Api
 */
class CustomerController extends Controller
{
    /**
     * @var CustomerRepository
     */
    protected $customers;

    /**
     * @param CustomerRepository $customers
     */
    public function __construct(CustomerRepository $customers)
    {
        $this->customers = $customers;
    }

    /**
     * Authenticate User
     * @param CustomerLoginRequest $request
     * @return string
     */
    public function login(CustomerLoginRequest $request)
    {
        Log::info("params" . json_encode($request->all()));

        $response = $this->customers->login($request->only("telephone", "password"));

        return $this->responseSuccess($response);
    }


    /**
     * Authenticate User via sms
     * @param CustomerLoginViaSmsRequest $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function loginViaSms(CustomerLoginViaSmsRequest $request)
    {
        Log::info("params" . json_encode($request->all()));

        $response = $this->customers->login($request->only("telephone", "sms"));

        return $this->responseSuccess($response);
    }

    /**
     * @param CustomerLoginViaAlipayRequest $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function loginViaAlipay(CustomerLoginViaAlipayRequest $request)
    {
        Log::info("params" . json_encode($request->all()));

        $response = $this->customers->loginViaAlipay($request->all());

        return $this->responseSuccess($response);
    }

    /**
     * @param $session_key
     * @param $encryptedData
     * @param $iv
     * @return bool|mixed
     */
    public function decryptData($session_key, $encryptedData, $iv)
    {
        if (strlen($session_key) != 24) {
            return false;
        }
        $aesKey = base64_decode($session_key);


        if (strlen($iv) != 24) {
            return false;
        }
        $aesIV = base64_decode($iv);

        $aesCipher = base64_decode($encryptedData);

        $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
        Log::info("[decryptData] data:" . $result);
        $dataArr = json_decode($result, true);
        if (!$dataArr) {
            return false;
        }
        if ($dataArr['watermark']['appid'] != config('constants.wechat.mini_program_id')) {
            return false;
        }

        return $dataArr;
    }


    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @throws ApiException
     */
    public function loginWechatViaMiniprogram(Request $request)
    {
        Log::info("[loginWechatViaMiniprogram] params:" . json_encode($request->all()));

        $code = $request->get('code');

        $url = sprintf(config('constants.wechat.open_id_url') . '?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code', config('constants.wechat.mini_program_id'), config('constants.wechat.mini_program_secret'), $code);

        $response = Http::WechatPostWithSecurity("", $url);

        Log::info("[wechatOpenId] response:" . $response);
        $response = json_decode($response, true);
        if(!isset($response['session_key'])){
            throw new ApiException(ErrorCode::CODE_ERROR, trans('api.error.code_error'));
        }
        $decryptData = $this->decryptData($response['session_key'], $request->get('encryptedData'), $request->get('iv'));
        if (!$decryptData) {
            Log::info('login failed');
            throw new ApiException(ErrorCode::LOGIN_FAILED, trans('api.error.login_failed'));
        }
        //decrypt data
        $response = $this->customers->wechat_miniprogram_login($decryptData);

        return $this->responseSuccess($response);
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function wechatOpenId(Request $request)
    {
        $code = $request->get('code');

        $url = sprintf(config('constants.wechat.open_id_url') . '?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code', config('constants.wechat.mini_program_id'), config('constants.wechat.mini_program_secret'), $code);

        $response = Http::WechatPostWithSecurity("", $url);
        Log::info("[wechatOpenId] response:" . $response);
        $response = json_decode($response, true);

        $customer = Auth::User();
        if (empty($customer->mini_program_open_id) && isset($response['openid'])) {
            $customer->mini_program_open_id = $response['openid'];
            $customer->save();
        }

        return $this->responseSuccess($response);
    }

    /**
     * Get current user info
     * @param Request $request
     * @return string
     */
    public function current(Request $request)
    {
        $user = Auth::User();
        if ($user->username == $user->telephone) {
            $user->username = PhoneUtil::maskPhone($user->username);
        }
        $user->telephone = PhoneUtil::maskPhone($user->telephone);
        $user->error_code = 0;

        return response()->json($user);
    }

    /**
     * Register user
     * @param StoreCustomerRequest $request
     * @return string
     */
    public function register(StoreCustomerRequest $request)
    {
        $this->customers->create($request->all());

        return $this->responseSuccess();
    }

    /**
     * Reset password
     * @param UpdateCustomerPasswordRequest $request
     * @return string
     */
    public function resetPassword(UpdateCustomerPasswordRequest $request)
    {
        $this->customers->updatePassword($request->all());
        return $this->responseSuccess();
    }

    /**
     * Get Other user info
     * @param string $id
     * @param Request $request
     * @return string
     */
    public function userDetail($id, Request $request)
    {
        return "detail" . $id;
    }

    /**
     * @param SmsRequest $request
     * @return \Illuminate\Http\JsonResponse
     * @throws ApiException
     */
    public function sms(SmsRequest $request)
    {
        $this->customers->sms($request->all());

        return $this->responseSuccess();
    }

    /**
     * Update user info
     * @param Request $request
     * @return string
     */
    public function update(Request $request)
    {
        $this->customers->update(Auth::User(), $request->all());

        return $this->responseSuccess();
    }

    /**
     * Logout User
     * @param Request $request
     * @return string
     */
    public function logout(Request $request)
    {
        $this->customers->logout();

        return $this->responseSuccess();
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function headImageUploadToken(Request $request)
    {
        $token = $this->customers->headImageUploadToken(Auth::User());

        return $this->responseSuccess(compact('token'));
    }

    /**
     * @param QiniuCallbackRequest $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function headerUpdateCallback(QiniuCallbackRequest $request)
    {
        Log::info("params" . json_encode($request->all()));

        $userId = $request->get('userId');
        $fileKey = $request->get('fkey');

        $customer = Customer::find($userId);
        $head_image = $fileKey;

        $this->customers->update($customer, compact('head_image'));

        $param = array('head_image' => config('constants.qiniu.user_bucket_url') . $head_image);

        return $this->responseSuccess($param);
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function refreshToken(Request $request)
    {
        $response = $this->customers->refreshToken();

        return $this->responseSuccess($response);
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function checkToken(Request $request)
    {
        $response = $this->customers->checkToken();

        return $this->responseSuccess($response);
    }
}