<?php

namespace App\Http\Controllers\Web\Auth;
namespace App\Http\Controllers\Web\Auth;

use App\Services\MailService;
use App\Http\Controllers\Controller;
use App\Models\MemInfo;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Log;

class FindPasswordController extends Controller
{
    public function show(Request $request)
    {
        $sess = $request->session()->get('find_pw', []);

        $step = 1;
        if (!empty($sess['verified'])) $step = 3;
        else if (!empty($sess['sent'])) $step = 2;

        return view('web.auth.find_password', [
            'initialStep' => $step,
            'email'       => $sess['email'] ?? null,
        ]);
    }

    public function sendCode(Request $request)
    {
        $v = Validator::make($request->all(), [
            'email' => ['required', 'email', 'max:120'],
        ], [
            'email.required' => '이메일을 입력해 주세요.',
            'email.email'    => '이메일 형식이 올바르지 않습니다.',
        ]);

        if ($v->fails()) {
            return response()->json(['ok' => false, 'message' => $v->errors()->first()], 422);
        }

        $email = mb_strtolower(trim((string) $request->input('email')));

        // 0) 가입된 이메일인지 확인 (MemInfo 기준)
        $exists = MemInfo::query()
            ->whereNotNull('email')
            ->where('email', '<>', '')
            ->whereRaw('LOWER(email) = ?', [$email])
            ->exists();

        if (!$exists) {
            return response()->json([
                'ok' => false,
                'code' => 'EMAIL_NOT_FOUND',
                'message' => '해당 이메일로 가입된 계정을 찾을 수 없습니다. 이메일을 다시 확인해 주세요.',
                'step' => 1,
            ], 404);
        }

        try {
            app(MailService::class)->sendTemplate(
                $email,
                '[PIN FOR YOU] 비밀번호 재설정 인증번호',
                'mail.legacy.noti_email_auth_1', // CI 템플릿명에 맞춰 선택
                [
                    'code' => $code,
                    'expires_min' => 3,
                    'email' => $email,
                ],
                queue: true
            );
        } catch (\Throwable $e) {
            $request->session()->forget('find_pw');
            Log::error('FindPassword sendCode failed', ['email' => $email, 'error' => $e->getMessage()]);
            return response()->json(['ok'=>false,'message'=>'인증번호 발송 중 오류가 발생했습니다.'], 500);
        }

        // 1) 레이트리밋(이메일 기준)
        $key = 'findpw:send:' . $email;
        if (RateLimiter::tooManyAttempts($key, 5)) { // 10분 5회 예시
            $sec = RateLimiter::availableIn($key);
            return response()->json(['ok' => false, 'message' => "요청이 너무 많습니다. {$sec}초 후 다시 시도해 주세요."], 429);
        }
        RateLimiter::hit($key, 600);

        // 2) OTP 생성
        $code = (string) random_int(100000, 999999);

        // 3) 세션 저장 (코드는 해시로)
        $request->session()->put('find_pw', [
            'sent' => true,
            'email' => $email,
            'code' => password_hash($code, PASSWORD_DEFAULT),
            'code_expires_at' => now()->addMinutes(3)->timestamp,
            'verified' => false,
            'verified_at' => null,
        ]);

        // 4) 실제 발송 연결 (메일/SMS 등)
        try {
            // TODO: 프로젝트에 맞게 구현
            // 예: Mail::to($email)->send(new PasswordOtpMail($code));
        } catch (\Throwable $e) {
            $request->session()->forget('find_pw');
            Log::error('FindPassword sendCode failed', [
                'email' => $email,
                'error' => $e->getMessage(),
            ]);
            return response()->json([
                'ok' => false,
                'message' => '인증번호 발송 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.',
            ], 500);
        }

        $isLocal = app()->environment(['local', 'development', 'testing']);

        return response()->json([
            'ok' => true,
            'message' => '인증번호를 발송했습니다.',
            'expires_in' => 180,
            'step' => 2,
            'dev_code' => $isLocal ? $code : null,
        ]);
    }

    public function verify(Request $request)
    {
        $v = Validator::make($request->all(), [
            'code' => ['required', 'digits:6'],
        ], [
            'code.required' => '인증번호를 입력해 주세요.',
            'code.digits' => '인증번호 6자리를 입력해 주세요.',
        ]);

        if ($v->fails()) {
            return response()->json(['ok' => false, 'message' => $v->errors()->first()], 422);
        }

        $sess = $request->session()->get('find_pw');
        if (!$sess || empty($sess['sent']) || empty($sess['email'])) {
            return response()->json(['ok' => false, 'message' => '먼저 인증번호를 요청해 주세요.'], 400);
        }

        if (empty($sess['code_expires_at']) || now()->timestamp > (int)$sess['code_expires_at']) {
            return response()->json(['ok' => false, 'message' => '인증번호가 만료되었습니다. 다시 요청해 주세요.'], 400);
        }

        // 검증 시도 레이트리밋
        $key = 'findpw:verify:' . $sess['email'];
        if (RateLimiter::tooManyAttempts($key, 10)) { // 10분 10회 예시
            $sec = RateLimiter::availableIn($key);
            return response()->json(['ok' => false, 'message' => "시도 횟수가 많습니다. {$sec}초 후 다시 시도해 주세요."], 429);
        }
        RateLimiter::hit($key, 600);

        $code = (string) $request->input('code');
        $ok = password_verify($code, $sess['code'] ?? '');

        if (!$ok) {
            return response()->json(['ok' => false, 'message' => '인증번호가 일치하지 않습니다.'], 422);
        }

        // 인증 성공 → step3 허용
        $sess['verified'] = true;
        $sess['verified_at'] = now()->timestamp;
        $request->session()->put('find_pw', $sess);

        return response()->json([
            'ok' => true,
            'message' => '인증이 완료되었습니다. 새 비밀번호를 설정해 주세요.',
            'step' => 3,
        ]);
    }

    public function reset(Request $request)
    {
        $v = Validator::make($request->all(), [
            'new_password' => ['required', 'string', 'min:8', 'max:72', 'confirmed'],
        ], [
            'new_password.required' => '새 비밀번호를 입력해 주세요.',
            'new_password.min' => '비밀번호는 8자 이상으로 입력해 주세요.',
            'new_password.confirmed' => '비밀번호 확인이 일치하지 않습니다.',
        ]);

        if ($v->fails()) {
            return response()->json(['ok' => false, 'message' => $v->errors()->first()], 422);
        }

        $sess = $request->session()->get('find_pw');
        if (!$sess || empty($sess['email']) || empty($sess['verified'])) {
            return response()->json(['ok' => false, 'message' => '인증이 필요합니다.'], 403);
        }

        $email = (string) $sess['email'];

        // (선택) 인증 후 너무 오래 지나면 재인증 요구
        $verifiedAt = (int)($sess['verified_at'] ?? 0);
        if ($verifiedAt > 0 && now()->timestamp - $verifiedAt > 10 * 60) { // 10분 예시
            $request->session()->forget('find_pw');
            return response()->json(['ok' => false, 'message' => '인증이 만료되었습니다. 다시 진행해 주세요.'], 403);
        }

        $newPassword = (string) $request->input('new_password');

        // 실제 비밀번호 저장 컬럼은 프로젝트마다 다를 수 있어 안전하게 처리
        $member = MemInfo::query()
            ->whereNotNull('email')
            ->where('email', '<>', '')
            ->whereRaw('LOWER(email) = ?', [mb_strtolower($email)])
            ->orderByDesc('mem_no')
            ->first();

        if (!$member) {
            $request->session()->forget('find_pw');
            return response()->json(['ok' => false, 'message' => '계정을 찾을 수 없습니다. 다시 진행해 주세요.'], 404);
        }

        // ✅ 여기서부터가 “진짜 저장 로직”
        // MemInfo의 실제 컬럼명에 맞게 1개만 쓰면 됩니다.
        // - password 컬럼을 쓰면 아래처럼
        // - 레거시 passwd 컬럼이면 passwd로 교체
        try {
            if (isset($member->password)) {
                $member->password = Hash::make($newPassword);
            } elseif (isset($member->passwd)) {
                $member->passwd = Hash::make($newPassword); // 레거시 규격이면 여기를 교체
            } else {
                // 컬럼을 모르면 여기서 명시적으로 막는게 안전
                return response()->json([
                    'ok' => false,
                    'message' => '비밀번호 저장 컬럼 설정이 필요합니다. (MemInfo password/passwd 확인)',
                ], 500);
            }

            $member->save();
        } catch (\Throwable $e) {
            Log::error('FindPassword reset failed', [
                'email' => $email,
                'error' => $e->getMessage(),
            ]);
            return response()->json(['ok' => false, 'message' => '비밀번호 변경 중 오류가 발생했습니다.'], 500);
        }

        $request->session()->forget('find_pw');
        $request->session()->save();

        return response()->json([
            'ok' => true,
            'message' => '비밀번호가 변경되었습니다. 로그인해 주세요.',
            'redirect_url' => route('web.auth.login'),
        ]);
    }

    public function resetSession(Request $request)
    {
        $request->session()->forget('find_pw');
        return response()->json(['ok' => true]);
    }
}
