<?php

namespace App\Libraries;

use App\Models\common\CommonModel;
use App\Models\v2\M712Model;
use CodeIgniter\Model;

class NaverApiClient
{
    protected $baseUrl = 'https://test-b2b.land.naver.com';
    protected $charger = '';

    private $commonModel;

    public function __construct()
    {
        $this->commonModel = new CommonModel();
    }

    /**
     * [GET] 매물 정보 조회
     */
    public function getArticleInfo(string $articleNumber): ?array
    {
        $this->charger = 'admin';
        $url = "{$this->baseUrl}/kiso/center/verification-article/{$articleNumber}?charger={$this->charger}";

        return $this->request('GET', $url);
    }

    /**
     * [PUT] 매물 정보 수정
     * @param string $articleNumber 매물번호
     * @param string charger 변경자
     * @param array $updateData 수정할 데이터 (tradeType, price, space 등)
     * string $tradeType 거래유형 (SALE:매매, JEONSE:전세, MONTHLY_RENT:월세, PRE_SALE:분양)
     * boolean $isResidntsExistence 거주여부
     * object $address 주소정보 공동 (complexNumber, pyeongTypeNumber, buildingName, hoName, correspondenceFloorCount) 비공동(legalDivisionNumber,jibunAddress,liAddress,etcAddress,referenceAddress,longitude,latitude,correspondenceFloorCount,totalFloorCount,undergroundFloorCount)
     * object $price 가격정보 (dealAmount,warrantyAmount,leaseAmount,preSaleAmount,premiumAmount,preSaleOptionAmount)
     * object $space 면적정보[비공동] (supplySpace,exclusiveSpace,totalSpace,groundSpace,buildingSpace)
     * object $facilities 비공동시설정보 (roomCount)
     */
    /** 현장확인 수정시 */
    public function updateArticleInfo(string $articleNumber, array $updateData, string $charger = 'admin'): ?array
    {
        $this->charger = $charger;
        $url = "{$this->baseUrl}/kiso/center/verification-site/{$articleNumber}?charger={$this->charger}";
        
        log_message('info', "[updateArticleInfo] 호출됨 - URL: {$url}, 데이터: " . json_encode($updateData, JSON_UNESCAPED_UNICODE));
        
        $result = $this->request('PUT', $url, $updateData);
        
        log_message('info', "[updateArticleInfo] 결과 - " . ($result === null ? 'NULL' : json_encode($result, JSON_UNESCAPED_UNICODE)));
        
        return $result;
    }

    /** 일반매물 수정시 */
    public function v2updateArticleInfo(string $articleNumber, array $updateData, string $charger = 'admin'): ?array
    {
        $this->charger = $charger;
        $url = "{$this->baseUrl}/kiso/center/verification-article/{$articleNumber}?charger={$this->charger}";
        
        log_message('info', "[v2updateArticleInfo] 호출됨 - URL: {$url}, 데이터: " . json_encode($updateData, JSON_UNESCAPED_UNICODE));
        
        $result = $this->request('PUT', $url, $updateData);
        
        log_message('info', "[v2updateArticleInfo] 결과 - " . ($result === null ? 'NULL' : json_encode($result, JSON_UNESCAPED_UNICODE)));
        
        return $result;
    }
    
    /**
     * [POST] 4.매물검증 결과관리
     * API:POST /kiso/center/verification-article/{매물번호}/report?charger={담당자명}
     * @param string $articleNumber 매물번호
     * @param string charger 변경자
     * @param array $reportData 검증결과데이터
     *  string $reportType 검증결과유형 (검증통과:VERIFIED, 검증실패:FAILED, 최종실패:REJECTED)
     *  array $verificationConfirms 검증결과목록
     *  string $ownerBirthDate 소유자 생년월일
     *  Boolean $isOwnerVerifiable 소유자 검증여부
     */
    public function postArticleVerificationReport(string $articleNumber, array $reportData, string $charger = 'admin'): ?array
    {
        $this->charger = $charger;
        $url = "{$this->baseUrl}/kiso/center/verification-article/{$articleNumber}/report?charger={$this->charger}";

        return $this->request('POST', $url, $reportData);
    }

    /**
     * [POST] 5.현장확인 정보 전송
     * API:POST /kiso/center//verification-article/media/{매물번호}
     * @param string $articleNumber 매물번호
     * @param array $movies 동영상 ($url)
     * @param array $photos 사진    ($fileName, $url)
     * @param array photo360s 360사진 ($fileName, $url, $desc)
     * @param string $charger 변경자
     */
    public function postArticleMediaInfo(string $articleNumber, array $movies, array $photos, array $photo360s, string $charger = 'admin'): ?array
    {
        $this->charger = $charger;
        $url = "{$this->baseUrl}/kiso/center/verification-article/media/{$articleNumber}?charger={$this->charger}";

        $data = [
            'movies' => $movies,
            'photos' => $photos,
            'photo360s' => $photo360s
        ];

        return $this->request('POST', $url, $data);
    }

    /**
     * [POST] 6.매물 정보 가격수정
     * @param string $articleNumber 매물번호
     * @param array $priceData 가격 수정 데이터
     *  API:PATCH /kiso/center/verification-article/price/{매물번호}?charger={변경자}
     * priceType int 가격유형 (DEAL:매매, WARRANTY:보증금, LEASE:월세, PRE_SALE:분양, PREMIUM:프리미엄, PRE_SALE_OPTION:분양옵션)
     * dealAmount Int 매매금액
     * warrantyAmount Int 보증금
     * leaseAmount Int 월세금액
     * preSaleAmount Int 분양금액
     * premiumAmount Int 프리미엄금액
     * preSaleOptionAmount Int 분양옵션금액
     */
    public function postArticlePriceUpdate(string $articleNumber, array $priceData, string $charger = 'admin'): ?array
    {
        $this->charger = $charger;
        $url = "{$this->baseUrl}/kiso/center/verification-article/price/{$articleNumber}?charger={$this->charger}";

        return $this->request('POST', $url, $priceData);
    }

    public function submitSyncResult(string $reserveNoList): ?array
    {
        $url = "{$this->baseUrl}/site/submitSyncResult.nhn";
        $url .= '?reserveNoList=' . $reserveNoList;
        return $this->request('GET', $url);
    }

    /**
     * 단지상세정보조회
     * hscpNo : 단지번호(숫자)
     */
    public function aptDetail($hscpNo)
    {
        $url = $this->commonModel->getCompanyInfo(3);
        $url = $url['api_server'] . "/confirms/APTDetail?hscpNo={$hscpNo}";
        return $this->request('GET', $url);
    }

    /**
     * 빌라 단지상세정보 조회
     * hscpNo : 단지번호(숫자)
     */

    public function villaDetail($hscpNo)
    {
        $url = $this->commonModel->getCompanyInfo(3);
        $url = $url['api_server'] . "/confirms/villa/{$hscpNo}";
        return $this->request('GET', $url);
    }


    /**
     * 단지목록
     * cortarNo	: 법정동코드
     */
    public function complexList($cortarNo)
    {
        $url = $this->commonModel->getCompanyInfo(2);
        $url = $url['api_server'] . "/common/complexList.nhn?cortarNo={$cortarNo}";
        return $this->request('GET', $url);
    }

    /**
     * 평형목록
     * rletNo	: 단지번호
     */
    public function ptpList($rletNo)
    {
        $url = $this->commonModel->getCompanyInfo(2);
        $url = $url['api_server'] . "/common/ptpList.nhn?rletNo={$rletNo}";
        return $this->request('GET', $url);
    }

    /**
     * 가격수정
     * @param String atclNo 	매물번호
     * @param integer dealAmt 	매매가, 전세(보증금) 단위 : 만원
     * @param integer wrrntAmt 	전세가(보증금) 단위 : 만원
     * @param integer leaseAmt 	월세가 단위 : 만원
     * @param integer isaleAmt  분양가 단위 : 만원
     * @param integer premAmt 	프리미엄 단위 : 만원
     * @param integer charger 	담당자id
     */
    public function priceChange($atclNo, $dealAmt, $wrrntAmt, $leaseAmt, $isaleAmt, $premAmt, $charger)
    {
        $url = $this->commonModel->getCompanyInfo(3);
        $url = $url['api_server'] . "/confirms/priceChange";

        $postData = [
            "atclNo" => $atclNo,
            "dealAmt" => $dealAmt,
            "wrrntAmt" => $wrrntAmt,
            "leaseAmt" => $leaseAmt,
            "isaleAmt" => $isaleAmt,
            "premAmt" => $premAmt,
            "charger" => $charger
        ];

        return $this->request('POST', $url, $postData);
    }

    /**
     * 매물정보수정
     * @param String atclNo 		매물번호
     * @param integer hscpNo 		단지번호
     * @param integer ptpNo			평형번호
     * @param String bildNm	 		동이름
     * @param String rmNo 			호수
     * @param String tradeType 		거래종류(A1,B1,B2 / 변경시 B1 <-> B2만 가능)
     * @param integer dealAmt 		매매가, 전세(보증금) 단위 : 만원
     * @param integer wrrntAmt 		전세가(보증금) 단위 : 만원
     * @param integer leaseAmt 		월세가 단위 : 만원
     * @param integer isaleAmt  	분양가 단위 : 만원
     * @param integer premAmt 		프리미엄 단위 : 만원
     * @param integer floor 		층
     * @param integer charger 		담당자id
     * 
     * @param String addressCode 	주소코드 : 비공동 주택 법정동 코드
     * @param String address2		지번주소 : 비공동 주택 지번 주소
     * @param String address3 		기타주소 : 비공동 주택 기타 주소
     * @param float	splySpc			공급면적
     * @param float	exclsSpc		대지면적
     * @param float	totSpc			전체면적
     * @param float	grndSpc			대지면적
     * @param float	bldgSpc			건축면적
     * 
     */
    public function modifyInfo($atclNo, $hscpNo, $ptpNo, $bildNm, $rmNo, $tradeType, $dealAmt, $wrrntAmt, $leaseAmt, $isaleAmt, $premAmt, $floor, $floor2, $charger, $addressCode, $address2, $address2a, $address2b, $address3, $splySpc, $exclsSpc, $totSpc, $grndSpc, $bldgSpc)
    {
        $url = $this->commonModel->getCompanyInfo(3);
        $url = $url['api_server'] . "/confirms/modifyInfo";

        // 공통
        $postData = [
            "atclNo" => $atclNo,
            "tradeType" => $tradeType,
            "dealAmt" => $dealAmt,
            "wrrntAmt" => $wrrntAmt,
            "leaseAmt" => $leaseAmt,
            "isaleAmt" => $isaleAmt,
            "charger" => $charger
        ];

        // 공동주택
        $apartData["hscpNo"] = $hscpNo;
        $apartData["ptpNo"] = $ptpNo;
        $apartData["bildNm"] = $address2;	// 네이버에서 보내주는거랑 수정되어 전달하는 거랑 다른 타입임. 2014년 11월 13일 수정
        $apartData["rmNo"] = $address3;	// 네이버에서 보내주는거랑 수정되어 전달하는 거랑 다른 타입임. 2014년 11월 13일 수정
//		$apartData["bildNm"]	= $bildNm;
//		$apartData["rmNo"]		= $rmNo;
        $apartData["premAmt"] = $premAmt;
        $apartData["floor"] = $floor;
        $apartData["floor2"] = $floor2;

        // 비공동주택 연동
        $detachData["addressCode"] = $addressCode;
        $detachData["address2"] = $address2;
        $detachData["address2a"] = $address2a;
        $detachData["address2b"] = $address2b;
        $detachData["address3"] = $address3;
        $detachData["splySpc"] = $splySpc;
        $detachData["exclsSpc"] = $exclsSpc;
        $detachData["totSpc"] = $totSpc;
        $detachData["grndSpc"] = $grndSpc;
        $detachData["bldgSpc"] = $bldgSpc;
        $detachData["floor"] = $floor;
        $detachData["floor2"] = $floor2;

        if (!empty($hscpNo)) {	//공동주택일 때
            $postData = array_merge($postData, $apartData);
        } else {						//비공동주택일 때
            $postData = array_merge($postData, $detachData);
        }

        return $this->request('POST', $url, $postData);
    }


    /**
     * 검증결과 전송
     * @param String atclNo 	매물번호
     * @param boolean success 	성공여부
     * @param array checkList 	확인정보 array('type'=>'T11','code'=>'10000','comment'=>'01|02|03'); 또는 array('type'=>'T11','code'=>'10000','comment'=>'코멘트');
     * @param String charger 	담당자 사번
     * @param array modifyInfo 	공동 비공동에 따라 다른 배열을 넘긴다.
     * @param String date 		상담일시
     */
    public function confirm($atclNo, $success, $checkList, $charger, $modifyInfo, $date)
    {
        $url = $this->commonModel->getCompanyInfo(3);
        $url = $url['api_server'] . "/confirms/confirm";

        $postData = [
            "atclNo" => $atclNo,
            "success" => $success,
            "checkList" => $checkList,
            "charger" => $charger,
            "modifyInfo" => $modifyInfo,
            "date" => $date,
        ];

        return $this->request('POST', $url, $postData);
    }

    /**
     * 등기부 등본 확인 결과
     * @param String atclNo 		매물번호
     * @param String type 			1: 1차 확인(등기부확인) / 2: 2차 확인(최종확인 또는 중개업소 TM)
     * @param boolean success 		성공여부
     * @param array checkList 		확인정보
     * @param String charger 		담당자 사번
     * @param String date 			상담일시
     * @param array modifyInfo 		수정정보 - success:true 에서만 허용
     */
    public function certification($atclNo, $type, $success, $checkList, $charger, $date, $modifyInfo, $ownerVerifiable)
    {
        $url = $this->commonModel->getCompanyInfo(3);
        $url = $url['api_server'] . "/confirms/certification";

        $postData = [
            "atclNo" => $atclNo,
            "type" => $type,
            "success" => $success,
            "checkList" => $checkList,
            "charger" => $charger,
            "date" => $date,
            "modifyInfo" => $modifyInfo,
            "ownerVerifiable" => $ownerVerifiable
        ];

        return $this->request('POST', $url, $postData);
    }

    /**
     * 등기부 등본 확인 결과
     * 712 OwnerVerifiable 전송 오류 우회 테스트
     */
    public function certification_712($atclNo, $type, $success, $checkList, $charger, $date, $modifyInfo, $ownerVerifiable)
    {
        $url = $this->commonModel->getCompanyInfo(3);
        $url = $url['api_server'] . "/confirms/certification";

        $model712 = new M712Model();
        $data = $model712->getOwnerVerifiable($atclNo);

        $ov = $data['OwnerVerifiable_change'];
        if (isset($ov)) {
            if ($ov > 0) {
                $ownerVerifiable = true;
            } else {
                $ownerVerifiable = false;
            }
        } else {
            $ownerVerifiable = null;
        }

        $postData = [
            "atclNo" => $atclNo,
            "type" => $type,
            "success" => $success,
            "checkList" => $checkList,
            "charger" => $charger,
            "date" => $date,
            "modifyInfo" => $modifyInfo,
            "ownerVerifiable" => $ownerVerifiable
        ];

        log_message('debug', '712 certification_712 => ' . $atclNo . ' ::: ' . json_encode($postData) . PHP_EOL);

        return $this->request('POST', $url, $postData);
    }

    /**
     * 현장확인 거주인 여부 변경
     */
    public function residentsExistence($reserveNumber, $isResidentsExist)
    {
        $url = $this->commonModel->getCompanyInfo(3);
        $url = $url['api_server'] . "/residents/existence";

        $postData = [
            'reserveNumber' => $reserveNumber,
            'isResidentsExist' => $isResidentsExist
        ];

        return $this->request('POST', $url, $postData);
    }

    /**
     * 예약확인 완료
     */
    public function reserveSuccess($reserveNo, $modyfyYn, $agency, $team, $staff, $staffTel, $reserveYmd, $apm)
    {
        $url = $this->commonModel->getCompanyInfo(3);
        $url = $url['api_server'] . "/site/reserveSuccess.nhn";

        $getData = ['reserveNo' => $reserveNo, 'modyfyYn' => $modyfyYn, 'agency' => $agency, 'team' => $team, 'staff' => $staff, 'staffTel' => $staffTel, 'reserveYmd' => $reserveYmd, 'apm' => $apm];

        return $this->request('POST', $url, $getData);
    }

    /**
     * 예약확인 실패
     */
    public function reserveFail($reserveNo, $errorCode, $etcTxt)
    {
        $url = $this->commonModel->getCompanyInfo(3);
        $url = $url['api_server'] . "/site/reserveFail.nhn";

        $getData = ['reserveNo' => $reserveNo, 'errorCode' => $errorCode, 'errorDesc' => $etcTxt];

        return $this->request('POST', $url, $getData);
    }

    /**
     * 촬영 실패
     */
    public function shootFail($reserveNo, $errorCode, $etcTxt)
    {
        $url = $this->commonModel->getCompanyInfo(3);
        $url = $url['api_server'] . "/site/shootFail.nhn";

        $getData = ['reserveNo' => $reserveNo, 'errorCode' => $errorCode, 'errorDesc' => $etcTxt];

        return $this->request('POST', $url, $getData);
    }

    /**
     * 현장확인2 및 썸네일 검수 실패
     */
    public function inspectFail($reserveNumber, $failDescription)
    {
        $url = $this->commonModel->getCompanyInfo(3);
        $url = $url['api_server'] . "/site/vr/inspect/fail";

        $postData = [
            'reserveNumber' => $reserveNumber,
            'failDescription' => $failDescription
        ];

        return $this->request('POST', $url, $postData);
    }

    /**
     * 현장확인 슬롯 동기화 
     * API (가) - /kiso/center/site-slot
     * 신규/변경 일자별 데이터 전송
     * @syncData array
     * @param string $baseDate 기준일자(ISO 8601 형식: YYYY-MM-DD  예: 2024-01-31)
     * @param string $legalDivisionNumber 구역번호 "1111000000"
     * @param object slots 오전/오후/ 슬롯 정보 
     [ 
        { 
            "baseDate": "2025-04-30", 
            "legalDivisionNumber": "1111000000", 
            "slots": { 
                "am": { "max": 10, "reserved": 0 }, 
                "pm": { "max": 100, "reserved": 0 } 
            } 
        } 
    ]      
    */
    public function syncSiteSlot($syncData){
        $url = $this->baseUrl . "/kiso/center/site-verification/slots";
        return $this->request('POST', $url, $syncData);
    }


    /**
     * CURL 공통 실행 함수
     */
    private function request(string $method, string $url, ?array $data = null): ?array
    {
        // 요청 데이터 로깅
        if ($data) {
            log_message('info', "[Naver API $method REQUEST] URL: $url | Data: " . json_encode($data, JSON_UNESCAPED_UNICODE));
        } else {
            log_message('info', "[Naver API $method REQUEST] URL: $url");
        }

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);

        if ($method === 'PUT') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
            if ($data) {
                $payload = json_encode($data);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
                curl_setopt($ch, CURLOPT_HTTPHEADER, [
                    'Content-Type: application/json',
                    'Content-Length: ' . strlen($payload),
                    'X-Naver-Client-Id: yqBbvQZ123_hjH3b3Df9'
                ]);
            }
        } elseif ($method === 'GET') {
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'X-Naver-Client-Id: yqBbvQZ123_hjH3b3Df9'
            ]);
        } elseif ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            if ($data) {
                $payload = json_encode($data);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
                curl_setopt($ch, CURLOPT_HTTPHEADER, [
                    'Content-Type: application/json',
                    'Content-Length: ' . strlen($payload),
                    'X-Naver-Client-Id: yqBbvQZ123_hjH3b3Df9'
                ]);
            }
        } elseif ($method === 'PATCH') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
            if ($data) {
                $payload = json_encode($data);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
                curl_setopt($ch, CURLOPT_HTTPHEADER, [
                    'Content-Type: application/json',
                    'Content-Length: ' . strlen($payload),
                    'X-Naver-Client-Id: yqBbvQZ123_hjH3b3Df9'
                ]);
            }
        }

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlError = curl_error($ch);
        $curlErrno = curl_errno($ch);
        curl_close($ch);

        // CURL 오류 체크
        if ($curlErrno !== 0) {
            log_message('error', "[Naver API $method CURL ERROR] URL: $url | Error ($curlErrno): $curlError");
            return [
                'error' => true,
                'error_type' => 'CURL_ERROR',
                'curl_errno' => $curlErrno,
                'curl_error' => $curlError,
                'url' => $url
            ];
        }

        // 결과 로그 기록 (성공/실패 모두 기록하여 추적 가능하게 함)
        if ($httpCode === 200 || $httpCode === 202) {
            log_message('info', "[Naver API $method SUCCESS] URL: $url | Code: $httpCode | Response: $response");
        } else {
            log_message('error', "[Naver API $method FAIL] URL: $url | Code: $httpCode | Response: $response");
            return [
                'error' => true,
                'error_type' => 'HTTP_ERROR',
                'http_code' => $httpCode,
                'response' => $response,
                'url' => $url
            ];
        }

        return json_decode($response, true);
    }
}