<?php

namespace App\Http\Controllers\Admin\User;

use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\Config;
use App\Models\UserRegister;
use App\Models\DTO\SearchData;
use App\Rules\NumberLength;
use App\Rules\SpecialCharLength;
use App\Rules\UppercaseLength;
use App\Rules\DeniedEmail;

class ListController extends Controller
{
    private User $userModel;
    private UserRegister $userRegisterModel;

    public function __construct(
        User $user,
        UserRegister $userRegister
    ) {
        $this->userModel = $user;
        $this->userRegisterModel = $userRegister;
    }

    /**
     * 회원 관리
     * @method GET
     * @see /admin/user/list
     */
    public function index(Request $request)
    {
        $params = SearchData::fromRequest($request);
        $params->activated = $request->get('activated');
        $params->isAdmin = $request->get('is_admin');
        $params->isDenied = $request->get('is_denied');
        $params->isWithdraw = $request->get('is_withdraw');

        $userData = $this->userModel->data($params);

        if ($userData->rows > 0) {
            $num = listNum($userData->total, $params->page, $params->perPage);
            foreach ($userData->list as $i => $row) {
                $row->num = $num--;
                $row->lastLoginAt = dateBr($row->last_login_at, '-');
                $row->deletedAt = dateBr($row->deleted_at, '-');
                $row->createdAt = dateBr($row->created_at);
                $row->editURL = route('admin.user.list.edit', $row->id);

                $userData->list[$i] = $row;
            }
        }

        return view('admin.user.list.index', [
            'userData' => $userData,
            'params' => $params
        ]);
    }

    /**
     * 회원 등록
     * @method GET
     * @see /admin/user/create
     */
    public function create()
    {
        return view('admin.user.list.write', [
            'actionURL' => route('admin.user.list.store'),
            'userData' => [],
            'uid' => null
        ]);
    }

    /**
     * 회원 수정
     * @method GET
     * @see /admin/user/{pk}/edit
     */
    public function edit(int $uid)
    {
        return view('admin.user.list.write', [
            'actionURL' => route('admin.user.list.update', $uid),
            'userData' => $this->userModel->find($uid),
            'uid' => $uid
        ]);
    }

    /**
     * 회원 등록 저장
     * @method POST
     * @see /admin/user/list
     */
    public function store(Request $request, Config $config)
    {
        // 비밀번호 유효성 검사 규칙 지정
        $passwordRule = ['required', 'confirmed'];
        $passwordMinLength = $config->item('password_min_length');

        // 비밀번호 최소 길이
        if($passwordMinLength > 0) {
            $passwordRule[] = 'min:' . $passwordMinLength;
            $passwordRule[] = new UppercaseLength;
            $passwordRule[] = new NumberLength;
            $passwordRule[] = new SpecialCharLength;
        }

        $rules = [
            'email' => ['required', 'email', 'unique:users,email', new DeniedEmail],
            'name' => 'required|string|min:2|max:20',
            'nickname' => 'required|string|min:2|max:20|unique:users,nickname',
            'password' => $passwordRule,
            'thumb_img' => 'nullable|mimes:jpg,jpeg,gif,png|max:3192',
            'about_me' => 'string|nullable|max:500',
            'receive_email' => 'nullable|numeric|in:0,1',
            'is_denied' => 'nullable|numeric|in:0,1',
            'is_withdraw' => 'nullable|numeric|in:0,1',
            'is_admin' => 'nullable|numeric|in:0,1',
            'is_open_profile' => 'nullable|numeric|in:0,1'
        ];

        $attributes = [
            'email' => '이메일',
            'name' => '이름',
            'nickname' => '닉네임',
            'password' => '비밀번호',
            'thumb_img' => '프로필 이미지',
            'about_me' => '자기소개',
            'receive_email' => '이메일 수신 여부',
            'is_denied' => '차단 여부',
            'is_withdraw' => '탈퇴 여부',
            'is_admin' => '관리자 여부',
            'is_open_profile' => '정보 공개 여부'
        ];

        $posts = $this->validate($request, $rules, [], $attributes);
        [$sid] = explode('@', $posts['email']);

        $saveData = [
            'sid' => $sid,
            'name' => $posts['name'],
            'nickname' => $posts['nickname'],
            'email' => $posts['email'],
            'email_verified_at' => now(),
            'password' => bcrypt($posts['password']),
            'thumb' => ($posts['thumb_img'] ?? 0),
            'about_me' => $posts['about_me'],
            'remember_token' => null,
            'is_email_cert' => 1,
            'is_denied' => ($posts['is_denied'] ?? 0),
            'is_withdraw' => ($posts['is_withdraw'] ?? 0),
            'is_admin' => ($posts['is_admin'] ?? 0),
            'is_open_profile' => ($posts['is_open_profile'] ?? 0),
            'receive_email' => ($posts['receive_email'] ?? 0),
            'register_ip' => IP_ADDRESS,
            'last_login_ip' => null,
            'last_login_at' => null,
            'password_updated_at' => now(),
            'deleted_at' => null,
            'created_at' => now(),
            'updated_at' => null,
        ];

        // 파일 저장
        if($request->hasFile('thumb')) {
            $thumb = $request->file('thumb');
            $thumb->store(UPLOAD_PATH_PUBLIC . DIRECTORY_SEPARATOR . UPLOAD_PATH_USER_THUMB);
            $saveData['thumb'] = (UPLOAD_PATH_STORAGE . DIRECTORY_SEPARATOR . UPLOAD_PATH_USER_THUMB . DIRECTORY_SEPARATOR . $thumb->hashName());
        }

        // 파일 삭제
        if($request->get('thumb_del')) {
            $thumbPath = $request->get('thumb_url');
            if(file_exists($thumbPath)) {
                unlink($thumbPath);
            }
            $saveData['thumb'] = null;
        }

        $uid = $this->userModel->insertGetId($saveData);

        $this->userRegisterModel->insert([
            'user_id' => $uid,
            'device' => DEVICE_TYPE,
            'language' => null,
            'browser' => BROWSER,
            'platform' => PLATFORM,
            'robot' => null,
            'ip_address' => IP_ADDRESS,
            'user_agent' => USER_AGENT,
            'referer' => REFERER
        ]);

        $message = '회원이 등록되었습니다.';
        return redirect()->route('admin.user.list.index')->with('message', $message);
    }

    /**
     * 회원 수정 저장
     * @method PUT
     * @see /admin/user/list/{pk}
     */
    public function update(int $uid, Request $request, Config $config)
    {
        // 비밀번호 유효성 검사 규칙 지정
        $passwordRule = ['nullable', 'confirmed'];
        $passwordMinLength = $config->item('password_min_length');

        // 비밀번호 최소 길이
        if($passwordMinLength > 0) {
            $passwordRule[] = 'min:' . $passwordMinLength;
            $passwordRule[] = new UppercaseLength;
            $passwordRule[] = new NumberLength;
            $passwordRule[] = new SpecialCharLength;
        }

        $rules = [
            'uid' => 'required|numeric|exists:users,id',
            'email' => [
                'required',
                'email',
                Rule::unique('users', 'email')->ignore($uid, 'id'),
                new DeniedEmail
            ],
            'name' => 'required|string|min:2|max:20',
            'nickname' => 'required|string|min:2|max:20|' . Rule::unique('users', 'nickname')->ignore($uid, 'id'),
            'password' => $passwordRule,
            'thumb_img' => 'nullable|mimes:jpg,jpeg,gif,png|max:3192',
            'about_me' => 'string|nullable|max:500',
            'receive_email' => 'nullable|numeric|in:0,1',
            'is_denied' => 'nullable|numeric|in:0,1',
            'is_withdraw' => 'nullable|numeric|in:0,1',
            'is_admin' => 'nullable|numeric|in:0,1',
            'is_open_profile' => 'nullable|numeric|in:0,1'
        ];

        $attributes = [
            'uid' => '회원 ID',
            'email' => '이메일',
            'name' => '이름',
            'nickname' => '닉네임',
            'password' => '비밀번호',
            'thumb_img' => '프로필 이미지',
            'about_me' => '자기소개',
            'receive_email' => '이메일 수신 여부',
            'is_denied' => '차단 여부',
            'is_withdraw' => '탈퇴 여부',
            'is_admin' => '관리자 여부',
            'is_open_profile' => '정보 공개 여부'
        ];

        $posts = $this->validate($request, $rules, [], $attributes);
        $user = $this->userModel->find($uid);

        $saveData = [
            'name' => $posts['name'],
            'nickname' => $posts['nickname'],
            'email' => $posts['email'],
            'password' => bcrypt($posts['password']),
            'thumb' => ($posts['thumb_img'] ?? 0),
            'about_me' => $posts['about_me'],
            'receive_email' => ($posts['receive_email'] ?? 0),
            'is_denied' => ($posts['is_denied'] ?? 0),
            'is_withdraw' => ($posts['is_withdraw'] ?? 0),
            'is_admin' => ($posts['is_admin'] ?? 0),
            'is_open_profile' => ($posts['is_open_profile'] ?? 0),
            'deleted_at' => null,
            'updated_at' => now()
        ];

        if($user->password != $saveData['password']) {
            $saveData['password_updated_at'] = now();
        }

        // 파일 저장
        if($request->hasFile('thumb')) {
            $thumb = $request->file('thumb');
            $thumb->store(UPLOAD_PATH_PUBLIC . DIRECTORY_SEPARATOR . UPLOAD_PATH_USER_THUMB);
            $saveData['thumb'] = (UPLOAD_PATH_STORAGE . DIRECTORY_SEPARATOR . UPLOAD_PATH_USER_THUMB . DIRECTORY_SEPARATOR . $thumb->hashName());
        }

        // 파일 삭제
        if($request->get('thumb_del')) {
            $thumbPath = $request->get('thumb_url');
            if(file_exists($thumbPath)) {
                unlink($thumbPath);
            }
            $saveData['thumb'] = null;
        }

        $this->userModel->updater($uid, $saveData);

        $message = '회원 정보가 수정되었습니다.';
        return redirect()->route('admin.user.list.edit', $uid)->with('message', $message);
    }

    /**
     * 회원 삭제
     * @method DELETE
     * @see /admin/user/list/destroy
     */
    public function destroy(Request $request)
    {
        $chk = $request->post('chk');

        if ($chk) {
            foreach ($chk as $uid) {

                $user = $this->userModel->findOrNew($uid);

                if($user->exists) {
                    // 프로필 이미지 삭제
                    if(file_exists($user->thumb)) {
                        unlink($user->thumb);
                    }

                    $user->delete();
                }
            }
        }

        $message = '회원 정보가 삭제되었습니다.';
        return redirect()->route('admin.user.list.index')->with('message', $message);
    }

    /**
     * 회원 탈퇴
     * @method POST
     * @see /admin/user/list/withdraw
     */
    public function withdraw(Request $request)
    {
        $chk = $request->post('chk');

        if ($chk) {
            foreach ($chk as $uid) {
                $this->userModel->find($uid)->update([
                    'is_withdraw' => 1,
                    'deleted_at' => now()
                ]);
            }
        }

        $message = '선택 회원이 탈퇴 처리되었습니다.';
        return redirect()->route('admin.user.list.index')->with('message', $message);
    }
}
