<?php

declare(strict_types=1);

namespace App\Services;

use App\Repositories\Mypage\MypageInfoRepository;
use App\Support\LegacyCrypto\CiSeedCrypto;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

final class MypageInfoService
{
    public function __construct(
        private readonly MypageInfoRepository $repo,
        private readonly CiSeedCrypto $seed,
    ) {}

    /**
     * 마이페이지 연락처 변경(PASS) 검증
     *
     * 입력:
     * - $sess: session('_sess') 배열
     * - $passPayload: session('mypage.pass.payload') 또는 session('pass.payload') 배열
     *
     * 반환:
     * - ['ok'=>bool, 'message'=>string, 'enc_phone'=>string, 'raw_phone'=>string, 'ci'=>string, 'carrier'=>string]
     */
    public function validatePassPhoneChange(array $sess, array $passPayload): array
    {
        $memNo = (int) ($sess['_mno'] ?? 0);
        if ($memNo <= 0) {
            return $this->fail('로그인 정보가 확인되지 않습니다. 다시 로그인 후 시도해 주세요.');
        }

        $rawPhone = $this->normalizePhone((string) Arr::get($passPayload, 'PHONE', ''));
        $ci       = (string) Arr::get($passPayload, 'CI', '');
        $carrier  = strtoupper((string) Arr::get($passPayload, 'CARRIER', ''));

        if ($rawPhone === '' || $ci === '') {
            return $this->fail('인증 정보가 올바르지 않습니다. 다시 시도해 주세요.');
        }

        // 통신사 제한: SKT/KTF/LGT만 허용, 나머지 전부 차단 + MVNO 차단
        $allowCarriers = ['SKT', 'KTF', 'LGT'];
        if (!in_array($carrier, $allowCarriers, true) || $carrier === 'MVNO') {
            return $this->fail('죄송합니다. SKT/KT/LG U+ 휴대전화만 인증할 수 있습니다. (알뜰폰/기타 통신사 불가)');
        }

        // PASS 전화번호 암호화 (CI 레거시 방식)
        $encPassPhone = (string) $this->seed->encrypt($rawPhone);

        // 기존 회원 전화번호와 동일하면 변경 불가
        $encMemberPhone = (string) ($sess['_mcell'] ?? '');
        if ($encMemberPhone !== '' && $encPassPhone !== '' && hash_equals($encMemberPhone, $encPassPhone)) {
            return $this->fail('현재 등록된 연락처와 동일합니다. 다른 번호로 인증해 주세요.');
        }

        // PASS 전화번호가 DB에 존재하면 변경 불가
        // "존재한다면 이전에 가입된 전화번호가 있습니다. 관리자 문의"
        if ($this->repo->existsEncryptedCell($encPassPhone, $memNo)) {
            return $this->fail('이미 가입된 휴대폰 번호가 있습니다. 관리자에게 문의해 주세요.');
        }

        // CI가 회원정보 mem_info.ci와 일치해야 통과
        $memberCi = $this->repo->getMemberCi($memNo);
        if ($memberCi === '' || !hash_equals($memberCi, $ci)) {
            return $this->fail('가입된 회원정보와 일치하지 않습니다. 관리자에게 문의해 주세요.');
        }

        return [
            'ok'        => true,
            'message'   => '검증이 완료되었습니다.',
            'enc_phone' => $encPassPhone,
            'raw_phone' => $rawPhone,
            'ci'        => $ci,
            'carrier'   => $carrier,
        ];
    }

    /**
     * 최종 저장: mem_info.cell 업데이트
     * @return array ['ok'=>bool, 'message'=>string, '_cell'=>string]
     */
    public function commitPhoneChange(int $memNo, array $passPayload): array
    {
        $Phone = $this->normalizePhone((string) Arr::get($passPayload, 'PHONE', ''));
        $encPhone = (string) $this->seed->encrypt($Phone);

        if ($memNo <= 0 || $encPhone === '') {
            return $this->fail('저장할 정보가 올바르지 않습니다.');
        }

        return DB::transaction(function () use ($memNo, $encPhone) {
            // 한번 더 중복 방어(레이스 컨디션)
            if ($this->repo->existsEncryptedCell($encPhone, $memNo)) {
                return $this->fail('이미 가입된 휴대폰 번호가 있습니다. 관리자에게 문의해 주세요.');
            }

            $affected = $this->repo->updateEncryptedCell($memNo, $encPhone);
            if ($affected < 1) {
                return $this->fail('연락처 저장에 실패했습니다. 잠시 후 다시 시도해 주세요.');
            }

            return [
                'ok'=>true,
                'message'=>'연락처가 변경되었습니다.',
                '_cell' => $encPhone,
                ];
        });
    }

    /**
     * 휴대폰 정규화 (숫자만)
     */
    private function normalizePhone(string $v): string
    {
        return preg_replace('/\D+/', '', $v) ?: '';
    }

    private function fail(string $message): array
    {
        return [
            'ok' => false,
            'message' => $message,
            'enc_phone' => '',
            'raw_phone' => '',
            'ci' => '',
            'carrier' => '',
        ];
    }
}
