<?php

namespace App\Repositories\Member;

use Illuminate\Support\Facades\DB;

class EmailAuthRepository
{
    /**
     * 메일 발송 전 처리:
     * - mem_auth upsert (email, N)
     * - mem_auth_log insert (P)
     * - mem_auth_info upsert (auth_info.email 세팅)
     * return: ['email' => ..., 'auth_key' => ..., 'expires_at' => 'Y-m-d H:i:s']
     */
    public function prepareEmailVerify(int $memNo, string $email, string $ip, int $expiresMinutes = 30): array
    {
        return DB::transaction(function () use ($memNo, $email, $ip, $expiresMinutes) {

            // 1) mem_auth: row lock (없으면 생성, 있으면 N으로 초기화)
            $row = DB::table('mem_auth')
                ->where('mem_no', $memNo)
                ->where('auth_type', 'email')
                ->lockForUpdate()
                ->first();

            $today = now()->toDateString();

            if (!$row) {
                DB::table('mem_auth')->insert([
                    'mem_no' => $memNo,
                    'auth_type' => 'email',
                    'auth_state' => 'N',
                    'auth_date' => $today,
                ]);
            } else {
                DB::table('mem_auth')
                    ->where('mem_no', $memNo)
                    ->where('auth_type', 'email')
                    ->update([
                        'auth_state' => 'N',
                        'auth_date' => $today,
                    ]);
            }

            // 2) auth_key 생성
            $authKey = now()->format('HisYmd') . $ip . '-' . bin2hex(random_bytes(8));
            $expiresAt = now()->addMinutes($expiresMinutes)->format('Y-m-d H:i:s');

            $emailInfo = [
                'type' => 'mem_level',
                'auth_hit' => 'n',
                'user_email' => $email,
                'auth_key' => $authKey,
                'auth_effective_time' => $expiresAt,
                'redate' => now()->format('Y-m-d H:i:s'),
            ];

            // 3) mem_auth_log: P (Pending)
            DB::table('mem_auth_log')->insert([
                'mem_no' => $memNo,
                'type' => 'email',
                'state' => 'P',
                'info' => json_encode($emailInfo, JSON_UNESCAPED_UNICODE),
                'rgdate' => now()->format('Y-m-d H:i:s'),
            ]);

            // 4) mem_auth_info upsert (auth_info JSON)
            $authInfoRow = DB::table('mem_auth_info')
                ->where('mem_no', $memNo)
                ->lockForUpdate()
                ->first();

            if (!$authInfoRow) {
                DB::table('mem_auth_info')->insert([
                    'mem_no' => $memNo,
                    'auth_info' => json_encode(['email' => $emailInfo], JSON_UNESCAPED_UNICODE),
                ]);
            } else {
                $current = json_decode((string)$authInfoRow->auth_info, true) ?: [];
                $current['email'] = $emailInfo;

                DB::table('mem_auth_info')
                    ->where('mem_no', $memNo)
                    ->update([
                        'auth_info' => json_encode($current, JSON_UNESCAPED_UNICODE),
                    ]);
            }

            return [
                'email' => $email,
                'auth_key' => $authKey,
                'expires_at' => $expiresAt,
            ];
        });
    }

    /**
     * 인증 완료 처리 (CI3 로직 동일):
     * - 이미 Y면 예외
     * - auth_info.email 존재/키/시간 체크
     * - mem_auth: Y 업데이트
     * - mem_auth_info: auth_hit=y + remote/agent/시간 merge
     * - mem_auth_log: S insert
     */
    public function confirmEmailVerify(int $memNo, string $encKey, string $ip, string $agent): array
    {
        return DB::transaction(function () use ($memNo, $encKey, $ip, $agent) {

            // 1) mem_auth 상태 확인 (lock)
            $auth = DB::table('mem_auth')
                ->where('mem_no', $memNo)
                ->where('auth_type', 'email')
                ->lockForUpdate()
                ->first();

            if ($auth && $auth->auth_state === 'Y') {
                return ['ok' => false, 'message' => '이미 인증이 완료되었습니다.'];
            }

            // 2) mem_auth_info 가져오기 (lock)
            $infoRow = DB::table('mem_auth_info')
                ->where('mem_no', $memNo)
                ->lockForUpdate()
                ->first();

            if (!$infoRow || empty($infoRow->auth_info)) {
                return ['ok' => false, 'message' => '잘못된 접근입니다.'];
            }

            $authJson = json_decode((string)$infoRow->auth_info, true);
            $emailAuth = $authJson['email'] ?? null;

            if (!$emailAuth || empty($emailAuth['auth_hit'])) {
                return ['ok' => false, 'message' => '정상적인 경로로 이용하세요.'];
            }
            if (($emailAuth['auth_hit'] ?? '') === 'y') {
                return ['ok' => false, 'message' => '이미 인증되었습니다.'];
            }

            if (($emailAuth['auth_key'] ?? '') !== $encKey) {
                return ['ok' => false, 'message' => '잘못된 접근입니다.'];
            }

            $effective = (string)($emailAuth['auth_effective_time'] ?? '');
            if ($effective === '' || $effective < now()->format('Y-m-d H:i:s')) {
                return ['ok' => false, 'message' => '인증시간이 초과되었습니다.'];
            }

            // 3) auth_hit = y + merge info
            $emailAuth['auth_hit'] = 'y';
            $emailAuth = array_merge($emailAuth, [
                'remote_addr' => $ip,
                'agent' => $agent,
                'auth_redate' => now()->format('Y-m-d H:i:s'),
            ]);

            $authJson['email'] = $emailAuth;

            // 4) mem_auth: Y 업데이트 (없으면 insert)
            $today = now()->toDateString();
            if (!$auth) {
                DB::table('mem_auth')->insert([
                    'mem_no' => $memNo,
                    'auth_type' => 'email',
                    'auth_state' => 'Y',
                    'auth_date' => $today,
                ]);
            } else {
                DB::table('mem_auth')
                    ->where('mem_no', $memNo)
                    ->where('auth_type', 'email')
                    ->update([
                        'auth_state' => 'Y',
                        'auth_date' => $today,
                    ]);
            }

            // 5) mem_auth_info 업데이트
            DB::table('mem_auth_info')
                ->where('mem_no', $memNo)
                ->update([
                    'auth_info' => json_encode($authJson, JSON_UNESCAPED_UNICODE),
                ]);

            // 6) mem_auth_log: S (Success)
            $logInfo = [
                'remote_addr' => $ip,
                'agent' => $agent,
                'auth_redate' => now()->format('Y-m-d H:i:s'),
            ];

            DB::table('mem_auth_log')->insert([
                'mem_no' => $memNo,
                'type' => 'email',
                'state' => 'S',
                'info' => json_encode($logInfo, JSON_UNESCAPED_UNICODE),
                'rgdate' => now()->format('Y-m-d H:i:s'),
            ]);

            return [
                'ok' => true,
                'message' => '이메일 인증이 확인되었습니다.',
                'email' => (string)($emailAuth['user_email'] ?? ''),
            ];
        });
    }
}
