<?php

namespace App\Http\Controllers\Web\Mypage;

use App\Http\Controllers\Controller;
use App\Services\MemInfoService;
use App\Services\Danal\DanalAuthtelService;
use App\Services\Dozn\DoznAccountAuthService;
use App\Repositories\Member\MemberAuthRepository;
use App\Support\LegacyCrypto\CiSeedCrypto;
use App\Support\LegacyCrypto\CiPassword;
use Illuminate\Validation\Rule;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Arr;


final class InfoGateController extends Controller
{
    public function __construct(
        private readonly CiSeedCrypto $seed,
    ) {}
    /**
     * 비밀번호 재인증 화면
     */
    public function show(Request $request)
    {
        $gate = (array) $request->session()->get('mypage_gate', []);
        $ok = (bool) ($gate['ok'] ?? false);
        $at = (int)  ($gate['at'] ?? 0);
        $ttlSeconds = 5 * 60;
        $isValid = $ok && $at > 0 && (time() - $at) <= $ttlSeconds;

        if ($isValid) {
            return redirect()->to('/mypage/info_renew');
        }

        return view('web.mypage.info.gate');
    }


    public function info_renew(Request $request, MemInfoService $memInfoService)
    {
        // gate (기존 그대로)
        $gate   = (array) $request->session()->get('mypage_gate', []);
        $gateOk = (bool) Arr::get($gate, 'ok', false);
        $gateAt = (int)  Arr::get($gate, 'at', 0);

        $ttlSec    = 5 * 60;
        $nowTs     = now()->timestamp;
        $expireTs  = ($gateOk && $gateAt > 0) ? ($gateAt + $ttlSec) : 0;
        $remainSec = ($expireTs > 0) ? max(0, $expireTs - $nowTs) : 0;
        $isGateValid = ($remainSec > 0);

        // 회원정보: _sess 기반
        $sess = (array) $request->session()->get('_sess', []);

        $memberName  = (string) Arr::get($sess, '_mname', '');
        $memberEmail = (string) Arr::get($sess, '_mid', '');
        $dtReg       = (string) Arr::get($sess, '_dt_reg', '');
        $memNo       = (int) Arr::get($sess, '_mno', 0);
        $rawPhone = (string) Arr::get($sess, '_mcell', '');

        // 전화번호 복호 (인증 완료 상태라 마스킹 제외)
        $memberPhone = (string) $this->seed->decrypt($rawPhone);
        $user = $request->user();
        $withdrawBankName = (string)($user->withdraw_bank_name ?? $user->bank_name ?? '');
        $withdrawAccount  = (string)($user->withdraw_account ?? $user->bank_account ?? '');
        $hasWithdrawAccount = ($withdrawBankName !== '' && $withdrawAccount !== '');

        $recv = $memNo > 0
            ? $memInfoService->getReceive($memNo)
            : ['rcv_email' => 'n', 'rcv_sms' => 'n', 'out_account' => null];

        $agreeEmail = $recv['rcv_email'];
        $agreeSms   = $recv['rcv_sms'];
        $outAccount = $recv['out_account'] ?? null;

        return view('web.mypage.info.renew', [
            // gate
            'ttlSec' => $ttlSec,
            'expireTs' => (int) $expireTs,
            'remainSec' => (int) $remainSec,
            'isGateValid' => (bool) $isGateValid,

            // member (sess)
            'memberName' => $memberName,
            'memberEmail' => $memberEmail,
            'memberPhone' => $memberPhone,
            'memberDtReg' => $dtReg,

            // etc
            'hasWithdrawAccount' => (bool) $hasWithdrawAccount,
            'agreeEmail' => $agreeEmail,
            'agreeSms' => $agreeSms,
            'outAccount' => $outAccount,
        ]);
    }


    /**
     * 재인증을 위한 연장 및 세셔초기화
     */
    public function gateReset(Request $request)
    {
        $ttlSec = 5 * 60;
        $now    = time();

        $gate   = (array) $request->session()->get('mypage_gate', []);
        $gateOk = (bool)($gate['ok'] ?? false);
        $gateAt = (int) ($gate['at'] ?? 0);

        $expireTs  = ($gateOk && $gateAt > 0) ? ($gateAt + $ttlSec) : 0;
        $isValid   = ($expireTs > 0) && ($expireTs > $now);

        if ($isValid) {
            //  남은 시간이 있으면: 5분 연장(= at를 현재로 갱신)
            $request->session()->put('mypage_gate', [
                'ok'    => true,
                'email' => (string)($gate['email'] ?? ''),
                'at'    => $now,
            ]);
            $request->session()->save();

        }else{
            // 시간이 끝났으면: 초기화
            $request->session()->forget('mypage_gate');
            $request->session()->save();
        }
        // 인덱스로 보내기
        return redirect()->route('web.mypage.info.index');
    }

    /**
     * 비밀번호 재인증 처리
     */
    public function verify(Request $request, MemInfoService $memInfoService)
    {
        $request->validate([
            'password' => ['required', 'string'],
        ], [
            'password.required' => '비밀번호를 입력해 주세요.',
        ]);

        $sess    = (array) $request->session()->get('_sess', []);
        $isLogin = (bool) ($sess['_login_'] ?? false);
        $email   = (string) ($sess['_mid'] ?? '');

        if (!$isLogin || $email === '') {
            return redirect()->route('web.auth.login', ['return_url' => url('/mypage/info')]);
        }

        $pw = (string) $request->input('password');

        $res = $memInfoService->attemptLegacyLogin([
            'email' => $email,
            'password' => $pw,
            'ip' => $request->ip(),
            'ua' => substr((string) $request->userAgent(), 0, 500),
            'return_url' => url('/mypage/info'),
        ]);

        $ok = (bool)($res['ok'] ?? $res['success'] ?? false);

        if (!$ok) {
            $msg = (string)($res['message'] ?? '비밀번호가 일치하지 않습니다.');
            return back()
                ->withErrors(['password' => $msg])   // 레이어 알림 스크립트가 이걸 잡음
                ->withInput($request->except('password'));
        }

        // 게이트 통과 세션 (예: 30분)
        $request->session()->put('mypage_gate', [
            'ok' => true,
            'email' => $email,
            'at' => time(),
        ]);

        return redirect()->route('web.mypage.info.renew');
    }

    public function passReady(Request $request)
    {
        // 목적 저장 (result에서 분기용)
        $purpose = (string) $request->input('purpose', 'mypage_phone_change');
        $request->session()->put('mypage.pass_purpose', $purpose);
        $request->session()->save();

        $danal = app(\App\Services\Danal\DanalAuthtelService::class)->prepare([
            'targetUrl' => route('web.mypage.info.danal.result'),
            'backUrl'   => route('web.mypage.info.renew'), // 취소/뒤로가기
            'cpTitle'   => request()->getHost(),
        ]);

        if (!($danal['ok'] ?? false)) {
            return response()->json([
                'ok' => false,
                'message' => $danal['message'] ?? '본인인증 준비에 실패했습니다. 잠시 후 다시 시도해 주세요.',
            ], 500);
        }

        // 필요하면 txid 저장 (회원가입과 동일)
        $request->session()->put('mypage.danal', [
            'txid' => $danal['txid'] ?? null,
            'created_at' => now()->toDateTimeString(),
            'purpose' => $purpose,
        ]);
        $request->session()->save();

        return response()->json([
            'ok' => true,
            'reason' => 'danal_ready',
            'popup' => [
                'url' => route('web.mypage.info.danal.start'),
                'fields' => $danal['fields'],
            ],
        ]);
    }

    public function danalStart(Request $request)
    {
        $fieldsJson = (string) $request->input('fields', '');
        $fields = json_decode($fieldsJson, true);

        if (!is_array($fields) || empty($fields)) {
            abort(400, 'Invalid Danal fields');
        }

        $platform = strtolower((string) $request->input('platform', ($fields['platform'] ?? '')));
        $isMobile = false;
        if ($platform === 'mobile') {
            $isMobile = true;
        } elseif ($platform === 'web') {
            $isMobile = false;
        } else {
            $ua = (string) $request->header('User-Agent', '');
            $isMobile = (bool) preg_match('/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i', $ua);
        }

        $action = $isMobile
            ? 'https://wauth.teledit.com/Danal/WebAuth/Mobile/Start.php'
            : 'https://wauth.teledit.com/Danal/WebAuth/Web/Start.php';

        unset($fields['platform']);

        // 기존 autosubmit 뷰 재사용 OK
        return view('web.auth.danal_autosubmit', [
            'action' => $action,
            'fields' => $fields,
            'isMobile' => $isMobile,
        ]);
    }


    public function danalResult(
        Request $request,
        DanalAuthtelService $danal,
        MemberAuthRepository $repo
    ) {
        $payload = $request->all();

        $tid = (string)($payload['TID'] ?? '');
        if ($tid === '') {
            return response()->view('web.auth.danal_finish_top', [
                'ok' => false,
                'message' => 'TID가 없습니다.',
                'redirect' => route('web.mypage.info.index'),
            ]);
        }

        // CI와 동일: TID로 CONFIRM
        $res = $danal->confirm($tid, 0, 1);

        // 로그 저장 (성공/실패 무조건)
        $logSeq = $repo->insertDanalAuthLog('M', (array) $res);
        if ($logSeq > 0) {
            $request->session()->put('mypage.pass.danal_log_seq', $logSeq);
        }

        $ok = (($res['RETURNCODE'] ?? '') === '0000');
        if (!$ok) {
            return response()->view('web.auth.danal_finish_top', [
                'ok' => false,
                'message' => ($res['RETURNMSG'] ?? '본인인증에 실패했습니다.') . ' (' . ($res['RETURNCODE'] ?? 'NO_CODE') . ')',
                'redirect' => route('web.mypage.info.index'),
            ]);
        }

        // 목적이 마이페이지 연락처 변경일 때만 추가 검증
        $purpose = (string) $request->session()->get('mypage.pass_purpose', '');
        if ($purpose === 'mypage_phone_change') {

            $sess = (array) $request->session()->get('_sess', []);
            $memNo = (int) ($sess['_mno'] ?? 0);

            if ($memNo <= 0) {
                return response()->view('web.auth.danal_finish_top', [
                    'ok' => false,
                    'message' => '로그인 정보가 확인되지 않습니다. 다시 로그인 후 시도해 주세요.',
                    'redirect' => route('web.auth.login'),
                ]);
            }

            $svc = app(\App\Services\MypageInfoService::class);

            //연락처 검증
            $check = $svc->validatePassPhoneChange($sess, (array) $res);
            if (!($check['ok'] ?? false)) {
                return response()->view('web.auth.danal_finish_top', [
                    'ok' => false,
                    'message' => $check['message'] ?? '연락처 변경 검증에 실패했습니다.',
                    'redirect' => route('web.mypage.info.index'),
                ]);
            }

            //전화번호 저장
            $check = $svc->commitPhoneChange($memNo, (array) $res);
            if (!($check['ok'] ?? false)) {
                return response()->view('web.auth.danal_finish_top', [
                    'ok' => false,
                    'message' => $check['message'] ?? '연락처 저장에 실패했습니다.',
                    'redirect' => route('web.mypage.info.index'),
                ]);
            }

            $request->session()->put('_sess._mcell', $check['_cell'] ?? '');        //전화번호 변경

        }else{
            return response()->view('web.auth.danal_finish_top', [
                'ok' => false,
                'message' => '요청이 올바르지 않습니다. 다시 시도해 주세요.',
                'redirect' => route('web.mypage.info.index'),
            ]);
        }

        // 성공: 마이페이지 인증 플래그 세션 저장
        $request->session()->forget('mypage.pass');
        $request->session()->forget('mypage.danal');

        $request->session()->save();

        return response()->view('web.auth.danal_finish_top', [
            'ok' => true,
            'message' => '본인인증이 완료되었습니다.',
            'redirect' => url('/mypage/info_renew'),
        ]);
    }

    /*비밀번호 변경 저장*/
    public function passwordUpdate(Request $request, MemInfoService $memInfoService, MemberAuthRepository $repo)
    {
        if (!$this->isGateOk($request)) {
            return $this->gateFailJson($request, '인증 시간이 만료되었습니다. 다시 인증해 주세요.');
        }

        // 로그인 세션
        $sess    = (array) $request->session()->get('_sess', []);
        $isLogin = (bool) ($sess['_login_'] ?? false);
        $email   = (string) ($sess['_mid'] ?? '');
        $memNo   = (int)    ($sess['_mno'] ?? 0);

        if (!$isLogin || $email === '' || $memNo <= 0) {
            return response()->json([
                'ok' => false,
                'message' => '로그인 정보가 확인되지 않습니다. 다시 로그인해 주세요.',
                'redirect' => route('web.auth.login'),
            ], 401);
        }

        // 검증 (요청하신 메시지 그대로)
        $request->validate([
            'current_password' => ['required', 'string'],
            'password' => [
                'required',
                'string',
                'min:8',
                'max:20',
                // 영문+숫자+특수문자 포함
                'regex:/^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,20}$/',
                'confirmed', // password_confirmation
            ],
        ], [
            'password.required' => '비밀번호를 입력해 주세요.',
            'password.min'      => '비밀번호는 8자리 이상이어야 합니다.',
            'password.max'      => '비밀번호는 20자리를 초과할 수 없습니다.',
            'password.regex'    => '비밀번호는 영문+숫자+특수문자를 포함해야 합니다.',
        ]);

        $currentPw = (string) $request->input('current_password');
        $newPw     = (string) $request->input('password');

        // 현재 비밀번호 확인(기존 attemptLegacyLogin 로직 재사용)
        $res = $memInfoService->attemptLegacyLogin([
            'email' => $email,
            'password' => $currentPw,
            'ip' => $request->ip(),
            'ua' => substr((string) $request->userAgent(), 0, 500),
            'return_url' => url('/mypage/info_renew'),
        ]);

        $ok = (bool)($res['ok'] ?? $res['success'] ?? false);
        if (!$ok) {
            // 레이어에서 보여줄 메시지
            return response()->json([
                'ok' => false,
                'message' => (string)($res['message'] ?? '현재 비밀번호가 일치하지 않습니다.'),
            ], 422);
        }

        // 변경 저장(레포 이미 존재) + 성공로그(레포 이미 존재)
        $repo->updatePasswordOnly($memNo, $newPw);
        $repo->logPasswordResetSuccess(
            $memNo,
            (string) $request->ip(),
            (string) $request->userAgent(),
            'S'
        );


        return response()->json([
            'ok' => true,
            'message' => '비밀번호가 변경되었습니다.',
        ]);
    }

    //2차 비밀번호 변경
    public function updatePin2(
        Request $request,
        MemInfoService $memInfoService,
        MemberAuthRepository $repo
    ) {
        if (!$this->isGateOk($request)) {
            return response()->json([
                'ok' => false,
                'message' => '인증 시간이 만료되었습니다. 다시 인증해 주세요.',
            ], 419);
        }

        // 입력 검증(메시지 그대로)
        $request->validate([
            'current_password' => ['required', 'string'],
            'current_pin2' => ['required', 'digits:4'],
            'pin2' => ['required', 'digits:4'],
            'pin2_confirmation' => ['required', 'same:pin2'],
        ], [
            'current_password.required' => '이전 비밀번호를 입력해 주세요.',

            'current_pin2.required' => '이전 2차 비밀번호(숫자 4자리)를 입력해 주세요.',
            'current_pin2.digits' => '이전 2차 비밀번호는 숫자 4자리여야 합니다.',

            'pin2.required' => '2차 비밀번호(숫자 4자리)를 입력해 주세요.',
            'pin2.digits' => '2차 비밀번호는 숫자 4자리여야 합니다.',
            'pin2_confirmation.required' => '2차 비밀번호 확인을 입력해 주세요.',
            'pin2_confirmation.same' => '2차 비밀번호 확인이 일치하지 않습니다.',
        ]);

        // 세션에서 mem_no/email 확보
        $sess = (array) $request->session()->get('_sess', []);
        $isLogin = (bool) ($sess['_login_'] ?? false);
        $email   = (string) ($sess['_mid'] ?? '');
        $memNo   = (int) ($sess['_mno'] ?? 0);

        if (!$isLogin || $email === '' || $memNo <= 0) {
            return response()->json([
                'ok' => false,
                'message' => '로그인 정보가 확인되지 않습니다. 다시 로그인 후 시도해 주세요.',
            ], 401);
        }

        // 1) 로그인 비밀번호(1차) 검증 (기존 attemptLegacyLogin 재사용)
        $currentPw = (string) $request->input('current_password');

        $res = $memInfoService->attemptLegacyLogin([
            'email' => $email,
            'password' => $currentPw,
            'ip' => $request->ip(),
            'ua' => substr((string) $request->userAgent(), 0, 500),
            'return_url' => url('/mypage/info_renew'),
        ]);

        $pwOk = (bool)($res['ok'] ?? $res['success'] ?? false);
        if (!$pwOk) {
            return response()->json([
                'ok' => false,
                'reason' => 'invalid_current_password',
                'message' => (string)($res['message'] ?? '이전 비밀번호가 일치하지 않습니다.'),
            ], 422);
        }

        // 2) 현재 2차 비밀번호 검증
        $currentPin2 = (string) $request->input('current_pin2');
        $pin2Ok = $repo->verifyPin2($memNo, $currentPin2);

        if (!$pin2Ok) {
            return response()->json([
                'ok' => false,
                'reason' => 'invalid_current_pin2',
                'message' => '이전 2차 비밀번호가 일치하지 않습니다.',
            ], 422);
        }

        // 3) 새 2차 비밀번호 저장
        $newPin2 = (string) $request->input('pin2');

        try {
            $repo->updatePin2Only($memNo, $newPin2);
        } catch (\Throwable $e) {
            Log::error('[mypage] pin2 update failed', [
                'mem_no' => $memNo,
                'err' => $e->getMessage(),
            ]);

            return response()->json([
                'ok' => false,
                'message' => '2차 비밀번호 변경에 실패했습니다. 잠시 후 다시 시도해 주세요.',
            ], 500);
        }

        return response()->json([
            'ok' => true,
            'message' => '2차 비밀번호가 변경되었습니다.',
        ]);
    }


    public function verifyOut(Request $request, DoznAccountAuthService $dozn, MemberAuthRepository $repo)
    {
        // 게이트 만료 처리(프로젝트 정책대로)
        if (!$this->isGateOk($request)) {
            return $this->gateFailJson($request, '인증이 만료되었습니다. 다시 인증해 주세요.');
        }

        // 레거시 세션 기준으로 memNo / 실명 확정
        $sess = (array) $request->session()->get('_sess', []);
        $memNo = (int) ($sess['_mno'] ?? 0);
        $memberName = trim((string) ($sess['_mname'] ?? ''));

        if ($memNo <= 0 || $memberName === '') {
            return response()->json([
                'ok' => false,
                'message' => '로그인 정보가 확인되지 않습니다. 다시 로그인 후 시도해 주세요.',
                'redirect' => route('web.auth.login'),
            ], 401);
        }

        $request->validate([
            'pin2'      => ['required','digits:4'],
            'bank_code' => ['required','string'],
            'account'   => ['required','regex:/^\d+$/'],
            'depositor' => ['required','string','max:50'],
        ], [
            'pin2.required' => '2차 비밀번호(숫자 4자리)를 입력해 주세요.',
            'pin2.digits' => '2차 비밀번호는 숫자 4자리여야 합니다.',
            'bank_code.required' => '은행을 선택해 주세요.',
            'account.required' => '계좌번호를 입력해 주세요.',
            'account.regex' => '계좌번호는 숫자만 입력해 주세요.',
            'depositor.required' => '예금주(성명)를 입력해 주세요.',
        ]);

        $pin2 = trim((string) $request->input('pin2', ''));
        $bankCode = trim((string) $request->input('bank_code', ''));
        $account = trim((string) $request->input('account', ''));
        $depositor = trim((string) $request->input('depositor', ''));

        if ($depositor !== $memberName) {
            return response()->json([
                'ok' => false,
                'message' => '가입자 성명과 예금주가 일치하지 않습니다.',
                'errors' => ['depositor' => ['가입자 성명과 예금주가 일치하지 않습니다.']],
            ], 422);
        }

        // 1) 2차비번 검증 먼저
        $okPin2 = $repo->verifyPin2($memNo, $pin2);
        if (!$okPin2) {
            return response()->json([
                'ok' => false,
                'message' => '2차 비밀번호가 올바르지 않습니다.',
                'errors' => ['pin2' => ['2차 비밀번호가 올바르지 않습니다.']],
            ], 422);
        }

        // 2) Dozn 인증 + 저장
        $res = $dozn->verifyAndSaveOutAccount(
            $memNo,
            $memberName,   // 세션 실명
            $depositor,    // 위에서 실명 일치 확인됨
            $bankCode,
            $account,
            true
        );

        return response()->json($res, 200);
    }

    /**
     * 마케팅 수신 동의 저장 (email/sms 각각 변경 시 해당 dt만 업데이트)
     * - gate(5분) 유효해야 함
     * - mem_info: rcv_email, rcv_sms, dt_rcv_email, dt_rcv_sms
     */
    public function marketingUpdate(Request $request, MemInfoService $memInfoService)
    {
        if (!$this->isGateOk($request)) {
            return $this->gateFailJson($request, '인증 시간이 만료되었습니다. 다시 인증해 주세요.');
        }

        // 레거시 세션 기준
        $sess    = (array) $request->session()->get('_sess', []);
        $isLogin = (bool) ($sess['_login_'] ?? false);
        $memNo   = (int)  ($sess['_mno'] ?? 0);

        if (!$isLogin || $memNo <= 0) {
            return response()->json([
                'ok' => false,
                'message' => '로그인 정보가 확인되지 않습니다. 다시 로그인해 주세요.',
                'redirect' => route('web.auth.login'),
            ], 401);
        }

        $request->validate([
            'rcv_email' => ['required', Rule::in(['y','n'])],
            'rcv_sms'   => ['required', Rule::in(['y','n'])],
        ], [
            'rcv_email.required' => '이메일 수신 동의 값을 선택해 주세요.',
            'rcv_sms.required'   => 'SMS 수신 동의 값을 선택해 주세요.',
            'rcv_email.in'       => '이메일 수신 동의 값이 올바르지 않습니다.',
            'rcv_sms.in'         => 'SMS 수신 동의 값이 올바르지 않습니다.',
        ]);

        $rcvEmail = (string) $request->input('rcv_email', 'n');
        $rcvSms   = (string) $request->input('rcv_sms', 'n');

        try {
            $result = $memInfoService->setReceiveSelective($memNo, $rcvEmail, $rcvSms);

            // 세션/표시용 값이 따로 있으면 여기서 같이 갱신해도 됨(선택)
            // 예: $request->session()->put('_sess.rcv_email', $rcvEmail);

            return response()->json([
                'ok' => true,
                'message' => $result['message'] ?? '수신 동의 설정이 저장되었습니다.',
                'changed' => $result['changed'] ?? [],
            ], 200);

        } catch (\Throwable $e) {
            Log::error('[mypage] marketing consent update failed', [
                'mem_no' => $memNo,
                'err' => $e->getMessage(),
            ]);

            return response()->json([
                'ok' => false,
                'message' => '수신 동의 저장에 실패했습니다. 잠시 후 다시 시도해 주세요.',
            ], 500);
        }
    }


    /**
     * gate 유효성 체크 (mypage_gate.at만 사용, TTL=5분)
     */
    private function isGateOk(Request $request, int $ttlSec = 300): bool
    {
        $gate = (array) $request->session()->get('mypage_gate', []);
        $ok   = (bool)($gate['ok'] ?? false);
        $at   = (int)($gate['at'] ?? 0);

        if (!$ok || $at <= 0) return false;

        return (time() - $at) <= $ttlSec;
    }

    /**
     * gate 만료 공통 JSON 응답
     */
    private function gateFailJson(Request $request, string $message = '인증이 필요합니다.')
    {
        return response()->json([
            'ok' => false,
            'message' => $message,
            'redirect' => route('web.mypage.info.index'), // gate 페이지로 유도
        ], 401);
    }

    //회원탈퇴
    public function withdraw(
        Request $request,
        MemInfoService $memInfoService,
        MemberAuthRepository $repo
    ) {
        // gate(5분) 유효해야 함 (지금 페이지가 info_renew니까 정책 그대로)
        if (!$this->isGateOk($request)) {
            return $this->gateFailJson($request, '인증 시간이 만료되었습니다. 다시 인증해 주세요.');
        }

        // 입력 검증
        $request->validate([
            'agree'    => ['required', 'in:1'],
            'password' => ['required', 'string'],
            'pin2'     => ['required', 'digits:4'],
        ], [
            'agree.required' => '안내사항 동의가 필요합니다.',
            'agree.in'       => '안내사항 동의가 필요합니다.',
            'password.required' => '비밀번호를 입력해 주세요.',
            'pin2.required'     => '2차 비밀번호(숫자 4자리)를 입력해 주세요.',
            'pin2.digits'       => '2차 비밀번호는 숫자 4자리여야 합니다.',
        ]);

        $sess  = (array) $request->session()->get('_sess', []);
        $memNo = (int) Arr::get($sess, '_mno', 0);

        if ($memNo <= 0) {
            return response()->json([
                'ok' => false,
                'message' => '로그인 정보가 확인되지 않습니다. 다시 로그인해 주세요.',
                'redirect' => route('web.auth.login'),
            ], 401);
        }

        $pw   = (string) $request->input('password');
        $pin2 = (string) $request->input('pin2');

        // ✅ 1차 비밀번호 검증(Repo)
        if (!$repo->verifyLegacyPassword($memNo, $pw)) {
            return response()->json([
                'ok' => false,
                'message' => '비밀번호가 일치하지 않습니다.',
                'errors' => ['password' => ['비밀번호가 일치하지 않습니다.']],
            ], 422);
        }

        // ✅ 2차 비밀번호 검증(Repo)
        if (!$repo->verifyPin2($memNo, $pin2)) {
            return response()->json([
                'ok' => false,
                'message' => '2차 비밀번호가 일치하지 않습니다.',
                'errors' => ['pin2' => ['2차 비밀번호가 일치하지 않습니다.']],
            ], 422);
        }

        // ✅ 탈퇴 가능 조건 검증 + 처리(Service)
        try {
            $res = $memInfoService->withdrawMember($memNo);

            if (!($res['ok'] ?? false)) {
                return response()->json([
                    'ok' => false,
                    'message' => $res['message'] ?? '회원탈퇴가 불가합니다.',
                ], 422);
            }

            // 세션 종료 (레거시 세션 포함)
            $request->session()->flush();
            $request->session()->invalidate();
            $request->session()->regenerateToken();

            return response()->json([
                'ok' => true,
                'message' => $res['message'] ?? '회원탈퇴가 완료되었습니다.',
                'redirect' => route('web.auth.login'),
            ]);

        } catch (\Throwable $e) {
            Log::error('[mypage] withdraw failed', [
                'mem_no' => $memNo,
                'err' => $e->getMessage(),
            ]);

            return response()->json([
                'ok' => false,
                'message' => '회원탈퇴 처리 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.',
            ], 500);
        }
    }


}
