<?php

namespace App\Http\Controllers\Account;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\UserEmailLog;
use App\Models\DTO\ResponseData;
use App\Mail\VerifyCode;
use Exception;

class EmailController extends Controller
{
    private User $userModel;
    private UserEmailLog $userEmailLogModel;

    public function __construct(User $user, UserEmailLog $userEmailLogModel)
    {
        $this->middleware('auth');
        $this->middleware('throttle:verify')->only('index');

        $this->userModel = $user;
        $this->userEmailLogModel = $userEmailLogModel;
    }

    /**
     * 회원 이메일 수정
     * @method GET
     * @see /account/email
     */
    public function index(Request $request, ResponseData $response): ResponseData
    {
        try{

            $rules = [
                'email' => 'required|email|unique:users,email'
            ];

            $attributes = [
                'email' => '이메일'
            ];

            $messages = [
                'email.required' => '이메일을 입력해 주세요.',
                'email.email' => '이메일 형식이 옳지 않습니다.',
                'email.unique' => '이미 사용 중인 이메일 입니다.'
            ];

            $posts = $this->validate($request, $rules, $messages, $attributes);

            if($this->userEmailLogModel->isUpdateAble(UID)) {
                throw new Exception(
                    sprintf('이메일 변경은 %d일 지난 후 가능합니다.', $this->userEmailLogModel->getDayLeft(UID))
                );
            }

            // 이메일 인증번호/남은시간 생성
            $verifyCode = rand(100000, 999999);
            $verifyExpiresAt = now()->addMinutes(VERIFY_EXPIRES_AT)->diffInSeconds(now());

            // 이메일 인증번호 발송
            [$name] = explode('@', $posts['email']);

            $sender = (object)[
                'name' => $name,
                'email' => $posts['email'],
            ];
            Mail::to($sender)->send(new VerifyCode($verifyCode, $posts['email']));

            // 쿠키 생성
            $sender->verifyCode = $verifyCode;
            $sender = serialize($sender);
            $cookie = cookie('tmpVerifyData', $sender, VERIFY_EXPIRES_AT);
            $response->cookie($cookie);

            // 이메일 인증 화면
            $response->view = view(layout('account.email'), [
                'user' => $request->user(),
                'menuID' => 'MODIFY',
                'verifyExpiresAt' => $verifyExpiresAt,
            ])->render();

        }catch(Exception $e) {
            $response = $response::fromException($e);
        }

        return $response;
    }

    /**
     * 회원 정보 수정 처리
     * @method POST
     * @see /account/email/update
     */
    public function update(Request $request, ResponseData $response): ResponseData
    {
        try{

            $rules = [
                'code' => 'required|integer'
            ];

            $attributes = [
                'code' => '인증번호'
            ];

            $messages = [
                'code.required' => '인증번호를 입력해 주세요.',
                'code.integer' => '인증번호 형식이 옳지 않습니다.'
            ];

            $posts = $this->validate($request, $rules, $messages, $attributes);
            $user = $request->user();
            $tmpVerifyData = unserialize($request->cookie('tmpVerifyData'));

            if($posts['code'] != $tmpVerifyData->verifyCode) {
                throw new Exception('인증번호가 일치하지 않습니다.');
            }

            $this->userModel->info()->generateEmailVerified(
                $tmpVerifyData->email
            );

            // 이메일 변경 확인
            if($user->email != $tmpVerifyData->email) {
                $this->userEmailLogModel->setLog($user, $tmpVerifyData->email);
            }

        }catch(Exception $e) {
            $response = $response::fromException($e);
        }

        return $response;
    }
}
