<?php
/**
 * 바로빌 계좌 API 설정 파일
 * 
 * ⚠️ 중요: 바로빌은 SOAP 웹서비스를 사용합니다 (REST API가 아님)
 * 
 * 계좌 입출금내역 조회를 위해서는 바로빌 웹사이트(https://www.barobill.co.kr)에서
 * 계좌를 먼저 등록해야 합니다.
 * 
 * 설정 파일:
 * 1. apikey/barobill_cert_key.txt - CERTKEY (인증서 키)
 * 2. apikey/barobill_corp_num.txt - 사업자번호
 * 3. apikey/barobill_test_mode.txt - 테스트 모드 설정 (선택)
 */

// 인증서 키(CERTKEY) 파일 경로
// load .env file
require_once __DIR__ . '/../../lib/DotEnv.php';
(new DotEnv(__DIR__ . '/../../.env'))->load();

// 인증서 키(CERTKEY) 파일 경로
$documentRoot = getenv('DOCUMENT_ROOT');
$certKeyFile = $documentRoot . '/apikey/barobill_cert_key.txt';
$legacyApiKeyFile = $documentRoot . '/apikey/barobill_api_key.txt';
$corpNumFile = $documentRoot . '/apikey/barobill_corp_num.txt';
$testModeFile = $documentRoot . '/apikey/barobill_test_mode.txt';

// CERTKEY 읽기
$barobillCertKey = '';
if (file_exists($certKeyFile)) {
    $content = trim(file_get_contents($certKeyFile));
    
    // 설명 텍스트 필터링: 실제 CERTKEY만 추출
    // 설명 텍스트 패턴 체크
    $isPlaceholder = false;
    $placeholderPatterns = [
        '/^\[여기에/',                    // [여기에로 시작
        '/^=/',                           // =로 시작
        '/바로빌 CERTKEY/',                // '바로빌 CERTKEY' 문자열 포함
        '/================================/',  // 구분선 포함
        '/설정 방법:/',                    // '설정 방법:' 포함
        '/인증서 관리/',                   // '인증서 관리' 포함
        '/개발자센터/',                    // '개발자센터' 포함
        '/⚠️/',                           // 경고 이모지 포함
        '/참고:/',                        // '참고:' 포함
    ];
    
    foreach ($placeholderPatterns as $pattern) {
        if (preg_match($pattern, $content)) {
            $isPlaceholder = true;
            break;
        }
    }
    
    // 실제 CERTKEY는 보통 20자 이상의 영문/숫자 조합
    // 설명 텍스트가 아니고, 충분히 긴 경우에만 CERTKEY로 인식
    if (!empty($content) && !$isPlaceholder && strlen($content) >= 10) {
        // 추가 검증: 실제 CERTKEY는 보통 영문/숫자/하이픈 조합
        // 설명 텍스트는 한글이나 특수문자가 많음
        $koreanCharCount = preg_match_all('/[가-힣]/u', $content);
        $totalCharCount = mb_strlen($content, 'UTF-8');
        
        // 한글 비율이 10% 미만이고, 길이가 적절하면 CERTKEY로 인식
        if ($koreanCharCount / max($totalCharCount, 1) < 0.1) {
            $barobillCertKey = $content;
        }
    }
}
if (empty($barobillCertKey) && file_exists($legacyApiKeyFile)) {
    $barobillCertKey = trim(file_get_contents($legacyApiKeyFile));
}

// 사업자번호 읽기
$barobillCorpNum = '';
if (file_exists($corpNumFile)) {
    $content = trim(file_get_contents($corpNumFile));
    if (!empty($content) && !preg_match('/^\[여기에/', $content)) {
        $barobillCorpNum = str_replace('-', '', $content);
    }
}

// 테스트 모드 확인
$isTestMode = false;
if (file_exists($testModeFile)) {
    $testMode = trim(file_get_contents($testModeFile));
    $isTestMode = (strtolower($testMode) === 'test' || strtolower($testMode) === 'true');
}

// 바로빌 사용자 ID (계좌 사용내역 조회에 필요)
// 빈 값이면 전체 계좌 조회, 특정 사용자만 조회하려면 사용자 ID 입력
$barobillUserIdFile = getenv('DOCUMENT_ROOT') . '/apikey/barobill_user_id.txt';
$barobillUserId = '';
if (file_exists($barobillUserIdFile)) {
    $content = trim(file_get_contents($barobillUserIdFile));
    if (!empty($content) && !preg_match('/^\[여기에/', $content)) {
        $barobillUserId = $content;
    }
}

// 테넌트별 설정 (DB에서 가져오기)
require_once(getenv('DOCUMENT_ROOT') . '/session.php');
require_once(getenv('DOCUMENT_ROOT') . '/lib/mydb.php');

$selectedTenantId = $_SESSION['eaccount_tenant_id'] ?? null;

// DB에서 테넌트 정보 가져오기
if ($selectedTenantId) {
    try {
        $pdo = db_connect();
        if ($pdo) {
            $sql = "SELECT id, company_name, corp_num, barobill_user_id 
                    FROM {$DB}.barobill_companies 
                    WHERE id = ?";
            $stmt = $pdo->prepare($sql);
            $stmt->execute([$selectedTenantId]);
            $tenant = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($tenant) {
                $barobillUserId = $tenant['barobill_user_id'];
                $barobillCorpNum = $tenant['corp_num'];
            }
        }
    } catch (Exception $e) {
        error_log('테넌트 정보 로드 실패: ' . $e->getMessage());
    }
} else {
    // 세션에 테넌트 ID가 없으면 '(주)주일기업'을 기본값으로 찾기
    try {
        $pdo = db_connect();
        if ($pdo) {
            // '(주)주일기업' 또는 barobill_user_id가 'juil5130'인 회사 찾기
            $sql = "SELECT id, company_name, corp_num, barobill_user_id 
                    FROM {$DB}.barobill_companies 
                    WHERE company_name LIKE '%주일기업%' 
                       OR company_name LIKE '%주일%'
                       OR barobill_user_id = 'juil5130'
                    ORDER BY id ASC
                    LIMIT 1";
            $stmt = $pdo->query($sql);
            $tenant = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($tenant) {
                $barobillUserId = $tenant['barobill_user_id'];
                $barobillCorpNum = $tenant['corp_num'];
                $selectedTenantId = $tenant['id'];
                // 세션에 저장
                $_SESSION['eaccount_tenant_id'] = $selectedTenantId;
            }
        }
    } catch (Exception $e) {
        error_log('기본 테넌트 정보 로드 실패: ' . $e->getMessage());
    }
}

/**
 * 바로빌 사용자 ID 반환
 */
function getBarobillUserId() {
    global $barobillUserId;
    return $barobillUserId;
}

// 바로빌 계좌 SOAP 웹서비스 URL (BANK.asmx)
// 바로빌 계좌 SOAP 웹서비스 URL (BANKACCOUNT.asmx)
$barobillAccountSoapUrl = $isTestMode 
    ? 'https://testws.baroservice.com/BANKACCOUNT.asmx?WSDL'  // 테스트 환경
    : 'https://ws.baroservice.com/BANKACCOUNT.asmx?WSDL';    // 운영 환경

// SOAP 클라이언트 초기화
$barobillAccountSoapClient = null;
$barobillInitError = '';

if (!empty($barobillCertKey) || $isTestMode) {
    try {
        // SSL 검증 비활성화 및 타임아웃 설정
        $context = stream_context_create([
            'ssl' => [
                'verify_peer' => false,
                'verify_peer_name' => false,
                'allow_self_signed' => true
            ]
        ]);

        $barobillAccountSoapClient = new SoapClient($barobillAccountSoapUrl, [
            'trace' => true,
            'encoding' => 'UTF-8',
            'exceptions' => true,
            'connection_timeout' => 30,
            'stream_context' => $context,
            'cache_wsdl' => WSDL_CACHE_NONE // WSDL 캐시 비활성화
        ]);
    } catch (Throwable $e) {
        $barobillInitError = $e->getMessage();
        error_log('바로빌 계좌 SOAP 클라이언트 생성 실패: ' . $e->getMessage());
    }
}

/**
 * 바로빌 계좌 SOAP 웹서비스 호출 함수
 * 
 * @param string $method SOAP 메서드명
 * @param array $params SOAP 메서드 파라미터
 * @return array 응답 데이터
 */
function callBarobillAccountSOAP($method, $params = []) {
    global $barobillAccountSoapClient, $barobillCertKey, $barobillCorpNum, $isTestMode, $barobillInitError, $barobillAccountSoapUrl;
    
    if (!$barobillAccountSoapClient) {
        $errorMsg = $isTestMode 
            ? '바로빌 계좌 SOAP 클라이언트가 초기화되지 않았습니다. (' . ($barobillInitError ?: '알 수 없는 오류') . ')'
            : '바로빌 계좌 SOAP 클라이언트가 초기화되지 않았습니다. CERTKEY를 확인하세요. (' . ($barobillInitError ?: '알 수 없는 오류') . ')';
        
        return [
            'success' => false,
            'error' => $errorMsg,
            'error_detail' => [
                'cert_key_file' => getenv('DOCUMENT_ROOT') . '/apikey/barobill_cert_key.txt',
                'soap_url' => $barobillAccountSoapUrl,
                'init_error' => $barobillInitError,
                'test_mode' => $isTestMode
            ]
        ];
    }
    
    if (empty($barobillCertKey) && !$isTestMode) {
        return [
            'success' => false,
            'error' => 'CERTKEY가 설정되지 않았습니다. apikey/barobill_cert_key.txt 파일을 확인하세요.'
        ];
    }
    
    if (empty($barobillCorpNum)) {
        return [
            'success' => false,
            'error' => '사업자번호가 설정되지 않았습니다. apikey/barobill_corp_num.txt 파일을 확인하세요.'
        ];
    }
    
    // CERTKEY와 CorpNum 자동 추가
    // 테스트 모드에서도 CERTKEY가 있으면 사용 (일부 API는 테스트 모드에서도 CERTKEY 필요)
    if (!isset($params['CERTKEY'])) {
        if ($isTestMode) {
            // 테스트 모드: CERTKEY가 있으면 사용, 없으면 빈 값
            // 주의: 일부 API는 테스트 모드에서도 CERTKEY가 필요할 수 있음
            $params['CERTKEY'] = !empty($barobillCertKey) ? $barobillCertKey : '';
        } else {
            // 운영 모드: CERTKEY 필수
            $params['CERTKEY'] = $barobillCertKey;
        }
    }
    if (!isset($params['CorpNum'])) {
        $params['CorpNum'] = $barobillCorpNum;
    }
    
    try {
        error_log('바로빌 계좌 API 호출 - Method: ' . $method . ', CorpNum: ' . $barobillCorpNum);
        
        // SOAP 요청 로그 수집 (CERTKEY는 마스킹)
        $logParams = $params;
        if (isset($logParams['CERTKEY'])) {
            $logParams['CERTKEY'] = substr($logParams['CERTKEY'], 0, 8) . '...' . substr($logParams['CERTKEY'], -4);
        }
        
        $soapRequest = [
            'method' => $method,
            'url' => $barobillAccountSoapUrl,
            'params' => $logParams,
            'timestamp' => date('Y-m-d H:i:s')
        ];
        
        $result = $barobillAccountSoapClient->$method($params);
        
        // SOAP 요청/응답 XML 로그 수집
        $soapRequestXml = $barobillAccountSoapClient->__getLastRequest();
        $soapResponseXml = $barobillAccountSoapClient->__getLastResponse();
        
        $resultProperty = $method . 'Result';
        if (isset($result->$resultProperty)) {
            $resultData = $result->$resultProperty;
            
            // 에러 코드 체크 (음수 값 또는 객체 내부의 음수 값)
            $errorCode = null;
            
            // 직접 숫자로 반환된 경우
            if (is_numeric($resultData) && $resultData < 0) {
                $errorCode = $resultData;
            }
            // 객체 내부에 BankAccountNum이 음수인 경우 (예: -10002)
            elseif (is_object($resultData)) {
                if (isset($resultData->BankAccountNum) && is_numeric($resultData->BankAccountNum) && $resultData->BankAccountNum < 0) {
                    $errorCode = $resultData->BankAccountNum;
                }
                // 다른 필드에서도 음수 값 체크
                foreach (get_object_vars($resultData) as $key => $value) {
                    if (is_numeric($value) && $value < 0 && ($key == 'CurrentPage' || $key == 'ErrorCode' || $key == 'ResultCode')) {
                        $errorCode = $value;
                        break;
                    }
                }
            }
            
            if ($errorCode !== null) {
                $errorMsg = '바로빌 계좌 API 오류 코드: ' . $errorCode;
                
                // 상세 에러 메시지 매핑
                $errorMessages = [
                    -10002 => '인증 실패 (-10002). CERTKEY가 올바르지 않거나 만료되었습니다. 바로빌 개발자센터에서 CERTKEY를 확인하세요.',
                    -50214 => '은행 로그인 실패 (-50214). 바로빌 사이트에서 계좌 비밀번호/인증서를 점검해주세요.',
                    -24005 => '사용자 정보 불일치 (-24005). 사업자번호를 확인해주세요.',
                    -25001 => '등록된 계좌가 없습니다 (-25001). 바로빌 사이트에서 계좌를 등록해주세요.',
                    -25005 => '조회된 데이터가 없습니다 (-25005).',
                    -25006 => '계좌번호가 잘못되었습니다 (-25006).',
                    -25007 => '조회 기간이 잘못되었습니다 (-25007).',
                ];
                
                if (isset($errorMessages[$errorCode])) {
                    $errorMsg = $errorMessages[$errorCode];
                }
                
                return [
                    'success' => false,
                    'error' => $errorMsg,
                    'error_code' => $errorCode,
                    'debug' => [
                        'request' => $soapRequest,
                        'request_xml' => $soapRequestXml,
                        'response_xml' => $soapResponseXml
                    ]
                ];
            }
            
            return [
                'success' => true,
                'data' => $resultData,
                'debug' => [
                    'request' => $soapRequest,
                    'request_xml' => $soapRequestXml,
                    'response_xml' => $soapResponseXml
                ]
            ];
        }
        
        return [
            'success' => true,
            'data' => $result,
            'debug' => [
                'request' => $soapRequest,
                'request_xml' => $soapRequestXml,
                'response_xml' => $soapResponseXml
            ]
        ];
        
    } catch (SoapFault $e) {
        return [
            'success' => false,
            'error' => 'SOAP 오류: ' . $e->getMessage(),
            'error_code' => $e->getCode()
        ];
    } catch (Throwable $e) {
        return [
            'success' => false,
            'error' => 'API 호출 오류 (치명적): ' . $e->getMessage()
        ];
    }
}
?>
