<?php

namespace App\Controllers;

use CodeIgniter\RESTful\ResourceController;
use App\Libraries\JwtLib\JWT;
use App\Libraries\JwtLib\Key;
use App\Models\LoginModel;

class Roulette extends ResourceController
{
    public function login()
    {
        // JSON 데이터 받기
        $data = $this->request->getJSON(true);

        $id = $data['id'] ?? null;
        $password = $data['password'] ?? null;
        $logintype = $data['logintype'] ?? null;

        if (!$id || !$password) {
            return $this->fail([
              'errorCode' => 1000,
              'message' => '아이디 또는 비밀번호가 누락되었습니다.'
            ], 400);
        }

        $loginModel = new LoginModel();
        $builder = $loginModel->getBuilderFor($logintype); // 모델을 통해 빌더를 가져옴

        
        $user = $builder->where('ID', $id)->get()->getRowArray();

        if (!$user) {
            return $this->fail([
              'errorCode' => 1001,
              'message' => '존재하지 않는 아이디입니다.'
            ], 404);
        }

        // 비밀번호 검증
        if (!password_verify($password, $user['PASSWORD'])) {
            return $this->fail([
              'errorCode' => 1002,
              'message' => '비밀번호가 틀렸습니다.'
          ], 401);
        }

        unset($user['PASSWORD']); // 비밀번호 노출 방지

        // JWT 토큰 생성에 필요한 값 로드
        $jwtSecret = env('JWT_SECRET');
        $kid = env('JWT_KID');

        if (empty($jwtSecret) || empty($kid)) {
            return $this->failServerError('환경변수가 누락되었습니다. 관리자에게 문의하세요.');
        }

        if (!class_exists('\App\Libraries\JwtLib\JWT')) {
            return $this->failServerError('JWT 라이브러리를 찾을 수 없습니다.');
        }

        $issuedAt = time();
        $accessExpire = $issuedAt + 60 * 15; // 15분
        //$accessExpire = $issuedAt + 5; // 15분
        $refreshExpire = $issuedAt + 60 * 60 * 24 * 14; // 14일
        //$refreshExpire = $issuedAt + 5; // 14일


        $accessPayload = [
            'iat' => $issuedAt,
            'exp' => $accessExpire,
            'sub' => $user['ID'],
            'name' => $user['NAME'] ?? '',
        ];

        // 리프레시 토큰 existing check
        $currentRefreshToken = $user['REFRESH_TOKEN'] ?? null;
        $validRefreshToken = null;

        // 토큰이 **없거나** (빈 값, null), 존재하지만 만료된 경우 모두 새로 발급
        $needIssueRefresh = !$currentRefreshToken; // null 또는 빈 문자열 등

        if ($currentRefreshToken) {
            // 기존 리프레시 토큰 유효성 검사
            try {
                $key = new Key($jwtSecret, 'HS256');
                $decoded = JWT::decode($currentRefreshToken, $key);

                if (isset($decoded->exp) && $decoded->exp > time()) {
                    // 만료되지 않음, 재사용
                    $validRefreshToken = $currentRefreshToken;
                    $needIssueRefresh = false;
                } else {
                    // 만료됨
                    $needIssueRefresh = true;
                }
            } catch (\Throwable $e) {
                // 토큰이 변조됐거나 잘못된 경우에도 새로 발급
                $needIssueRefresh = true;
            }
        }

        if ($needIssueRefresh) {
            // 없거나 만료/무효화 시 새로 발급 및 DB 업데이트
            $refreshPayload = [
                'iat' => $issuedAt,
                'exp' => $refreshExpire,
                'sub' => $user['ID'],
            ];

            try {
                $validRefreshToken = JWT::encode($refreshPayload, $jwtSecret, 'HS256', $kid);

                // ADM_LIST에 리프레시 토큰 값 업데이트 (신규 발급 포함)
                $builder->where('ID', $user['ID'])->update(['REFRESH_TOKEN' => $validRefreshToken]);
            } catch (\Throwable $e) {
                return $this->failServerError('JWT 생성 오류: ' . $e->getMessage());
            }
        }

        try {
            $accessToken = JWT::encode($accessPayload, $jwtSecret, 'HS256', $kid);
        } catch (\Throwable $e) {
            return $this->failServerError('JWT 생성 오류: ' . $e->getMessage());
        }

        // 벤더 로그인시 COMPANY_NUMBER 필드 추가
        if ($logintype === 'vendor' && isset($user['COMPANY_NUMBER'])) {
            // COMPANY_NUMBER가 이미 있으면 그대로 사용
        } elseif ($logintype === 'vendor') {
            // COMPANY_NUMBER가 없으면 기본값 설정 (필요시)
            $user['COMPANY_NUMBER'] = $user['COMPANY_NUMBER'] ?? '';
        }

        return $this->respond([
            'status' => 'active',
            'accessToken' => $accessToken,
            'refreshToken' => $validRefreshToken,
            'user' => $user,
        ]);
    }

    public function refreshToken() 
    {
        $data = $this->request->getJSON(true);
        $refreshToken = $data['refreshToken'] ?? null;
        if (!$refreshToken) {
            return $this->fail('리프레시 토큰이 필요합니다.', 400);
        }

        $jwtSecret = env('JWT_SECRET');
        $kid = env('JWT_KID');

        try {
            $key = new Key($jwtSecret, 'HS256');
            $headers = null;
            $decoded = JWT::decode($refreshToken, $key, $headers);

            if ($decoded->exp < time()) {
                return $this->fail('리프레시 토큰이 만료되었습니다.', 401);
            }

            $userId = $decoded->sub ?? null;
            if (!$userId) {
                return $this->fail('유효하지 않은 토큰입니다.', 401);
            }

            // ADM_LIST에서 해당 유저와 REFRESH_TOKEN 비교
            $db = \Config\Database::connect();
            $builder = $db->table('ADM_LIST');
            $user = $builder->where('ID', $userId)->get()->getRowArray();

            if (!$user) {
                return $this->fail('사용자를 찾을 수 없습니다.', 404);
            }

            unset($user['PASSWORD']);

            // DB에 저장된 리프레시 토큰과 요청 리프레시 토큰이 일치하지 않으면 거절
            if (!isset($user['REFRESH_TOKEN']) || $user['REFRESH_TOKEN'] !== $refreshToken) {
                return $this->fail('리프레시 토큰 불일치 또는 무효한 요청입니다.', 401);
            }

            // 일치하면 액세스 토큰 발급
            $issuedAt = time();
            $expire = $issuedAt + 60 * 15; // 15분
            //$expire = $issuedAt + 5; // 15분
            $accessPayload = [
                'iat' => $issuedAt,
                'exp' => $expire,
                'sub' => $userId,
                'name' => $user['NAME'] ?? '',
            ];
            $accessToken = JWT::encode($accessPayload, $jwtSecret, 'HS256', $kid);

            return $this->respond([
                'accessToken' => $accessToken,
                'user' => $user,
            ]);
        } catch (\Throwable $e) {
            return $this->fail('유효하지 않은 리프레시 토큰입니다.', 401);
        }
    }
       
}