<?php
namespace App\Controllers\Article;

use App\Controllers\BaseController;

use App\Libraries\Common;
use App\Libraries\MyUpload;
use App\Libraries\NaverApiClient;
use App\Models\article\DeptModel;
use App\Models\article\ReceiptModel;
use App\Models\common\CodeModel;
use Exception;

class Receipt extends BaseController
{
    private $model, $codeModel;

    public function __construct()
    {
        $this->model = new ReceiptModel();
        $this->codeModel = new CodeModel();
    }

    public function lists(): string
    {
        log_message('error', '========== Receipt::lists() CALLED ==========');
        
        $usr_id = $this->request->getGet('usr_id') ?: '';
        $sBonbu = $this->request->getGet('bonbu') ?: '';
        $sTeanm = $this->request->getGet('dept_sq') ?: '';

        $codes = $this->codeModel->getCodeLists(['NHN_DEAL_TYPE', 'CP_ID', 'ARTICLE_TYPE', 'VRFCREQ_WAY', 'STEP_VERIFICATION']); // 코드조회
        $sido = $this->model->getAreaList(); // 지역조회
        $bonbu = $this->model->getBonbuList();
        $team = $this->model->getTeamList();
        $user = $this->model->getUserList();


        $this->data['sido'] = $sido;
        $this->data['bonbu'] = $bonbu;
        $this->data['team'] = $team;
        $this->data['user'] = $user;
        $this->data['codes'] = $codes;

        if (!empty($usr_id)) {
            $srchUser = $this->model->getSrchUserInfo($usr_id);
            $this->data['srchUser'] = $srchUser;
        }

        $this->data['sBonbu'] = $sBonbu;
        $this->data['sTeanm'] = $sTeanm;


        return view("pages/article/receipt/lists", $this->data);
    }

    public function getResultList()
    {
        log_message('info', '========== Receipt::getResultList() CALLED ==========');
        
        $start = (int) $this->request->getGet('start') ?: 0;
        $end = (int) $this->request->getGet('length') ?: 10;

        $data = [
            'rcpt_atclno' => $this->request->getGet('rcpt_atclno'), // 매물ID
            'schDateGb' => $this->request->getGet('schDateGb'), // 일자유형
            'sdate' => $this->request->getGet('sdate'),           // 시작일
            'edate' => $this->request->getGet('edate'),           // 종료일

            'bonbu' => $this->request->getGet('bonbu'),           // 본부
            'team' => $this->request->getGet('team'),           // 팀
            'user' => $this->request->getGet('user'),             // 담당자

            'sido' => $this->request->getGet('sido'),          // 시도
            'gugun' => $this->request->getGet('gugun'),        // 시군구
            'dong' => $this->request->getGet('dong'),         // 읍면동

            'rcpt_stat1' => $this->request->getGet('rcpt_stat1'),     // 상태1
            'rcpt_stat2' => $this->request->getGet('rcpt_stat2'),     // 상태2
            'rcpt_stat3' => $this->request->getGet('rcpt_stat3'),     // 상태3

            'rcpt_product_info1' => $this->request->getGet('rcpt_product_info1'), // 거래구분
            'exp_movie_yn' => $this->request->getGet('exp_movie_yn'),             // 동영상촬영여부
            'conf_img_yn' => $this->request->getGet('conf_img_yn'),               // 홍보확인서여부
            'parcel_out_yn' => $this->request->getGet('parcel_out_yn'),           // 분양권
            'rcpt_cpid' => $this->request->getGet('rcpt_cpid'),                   // CPID
            'rcpt_product' => $this->request->getGet('rcpt_product'),             // 매물종류
            'exp_spc_yn' => $this->request->getGet('exp_spc_yn'),                 // 면적확인
            'check_list_img_yn' => $this->request->getGet('check_list_img_yn'),   // 체크리스트
            'ground_plan_yn' => $this->request->getGet('ground_plan_yn'),         // 평면도유무
            'ground_plan' => $this->request->getGet('ground_plan'),               // 평면도요청

            'direct_trad_yn' => $this->request->getGet('direct_trad_yn'),         // 직거래
            'image_360_yn' => $this->request->getGet('image_360_yn'),             // 360촬영여부
            'srchType' => $this->request->getGet('srchType'),                     // 검색유형
            'srchTxt' => $this->request->getGet('srchTxt'),                       // 검색어
        ];

        log_message('info', '[Receipt::getResultList] START - start=' . $start . ' length=' . $end);
        
        $totalCount = $this->model->getTotalCount($data);
        log_message('info', '[Receipt::getResultList] TotalCount = ' . $totalCount);

        $datas = $this->model->getResultList($start, $end, $data);
        log_message('info', '[Receipt::getResultList] END - returned ' . count($datas) . ' rows');

        return $this->response->setJSON(body: [
            'recordsTotal' => $totalCount,
            'recordsFiltered' => $totalCount,
            'data' => $datas,
        ]);
    }


    // 엑셀 다운로드
    public function excel()
    {
        try {

            $data = [
                'rcpt_atclno' => $this->request->getGet('rcpt_atclno'), // 매물ID
                'schDateGb' => $this->request->getGet('schDateGb'), // 일자유형
                'sdate' => $this->request->getGet('sdate'),           // 시작일
                'edate' => $this->request->getGet('edate'),           // 종료일

                'bonbu' => $this->request->getGet('bonbu'),           // 본부
                'team' => $this->request->getGet('team'),           // 팀
                'user' => $this->request->getGet('user'),             // 담당자

                'sido' => $this->request->getGet('sido'),          // 시도
                'gugun' => $this->request->getGet('gugun'),        // 시군구
                'dong' => $this->request->getGet('dong'),         // 읍면동

                'rcpt_stat1' => $this->request->getGet('rcpt_stat1'),     // 상태1
                'rcpt_stat2' => $this->request->getGet('rcpt_stat2'),     // 상태2
                'rcpt_stat3' => $this->request->getGet('rcpt_stat3'),     // 상태3

                'rcpt_product_info1' => $this->request->getGet('rcpt_product_info1'), // 거래구분
                'exp_movie_yn' => $this->request->getGet('exp_movie_yn'),             // 동영상촬영여부
                'conf_img_yn' => $this->request->getGet('conf_img_yn'),               // 홍보확인서여부
                'parcel_out_yn' => $this->request->getGet('parcel_out_yn'),           // 분양권
                'rcpt_cpid' => $this->request->getGet('rcpt_cpid'),                   // CPID
                'rcpt_product' => $this->request->getGet('rcpt_product'),             // 매물종류
                'exp_spc_yn' => $this->request->getGet('exp_spc_yn'),                 // 면적확인
                'check_list_img_yn' => $this->request->getGet('check_list_img_yn'),   // 체크리스트
                'ground_plan_yn' => $this->request->getGet('ground_plan_yn'),         // 평면도유무
                'ground_plan' => $this->request->getGet('ground_plan'),               // 평면도요청

                'direct_trad_yn' => $this->request->getGet('direct_trad_yn'),         // 직거래
                'image_360_yn' => $this->request->getGet('image_360_yn'),             // 360촬영여부
                'srchType' => $this->request->getGet('srchType'),                     // 검색유형
                'srchTxt' => $this->request->getGet('srchTxt'),                       // 검색어
            ];

            $datas = $this->model->getExcelList($data);

            return $this->response->setJSON(body: [
                'data' => $datas,
            ]);

        } catch (\Exception $e) {
            $e->getPrevious()->getTraceAsString();
        }
    }


    // 상세화면
    public function detail($id)
    {
        $naver = new NaverApiClient();
        $id = (string) $id;

        if ($id === '') {
            throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
        }

        $t0 = microtime(true);
        $codes = $this->codeModel->getCodeLists(['TRADE_TYPE', 'RECEIPT_STATUS2', 'RECEIPT_STATUS3', 'SMS_MSG_TYPE', 'SMS_MSG_TYPE2']); // 코드조회
        log_message('info', '[Receipt::detail] getCodeLists {ms}ms', ['ms' => (int) ((microtime(true) - $t0) * 1000)]);

        $t1 = microtime(true);
        $bonbu = $this->model->getBonbuList();
        log_message('info', '[Receipt::detail] getBonbuList {ms}ms', ['ms' => (int) ((microtime(true) - $t1) * 1000)]);

        $t2 = microtime(true);
        $team = $this->model->getTeamList();
        log_message('info', '[Receipt::detail] getTeamList {ms}ms', ['ms' => (int) ((microtime(true) - $t2) * 1000)]);

        $damdang = $this->model->getUserList();



        // sms 코드
        $sms = [];
        foreach ($codes as $c) {
            if ($c['category'] === "SMS_MSG_TYPE2")
                array_push($sms, $c);
        }

        $t3 = microtime(true);
        $data = $this->model->getDetail($id);
        log_message('info', '[Receipt::detail] getDetail {ms}ms', ['ms' => (int) ((microtime(true) - $t3) * 1000)]);

        $t4 = microtime(true);
        // rcpt_sq를 사용하여 이력 조회
        $history = $this->model->getHistory($data['rcpt_sq'] ?? $id);
        log_message('info', '[Receipt::detail] getHistory {ms}ms', ['ms' => (int) ((microtime(true) - $t4) * 1000)]);

        $t5 = microtime(true);
        if ($data['rcpt_jibun_addr']) {
            $dupleGroundPlan = $this->model->getDupleGP_na($id, $data['rcpt_sido'], $data['rcpt_gugun'], $data['rcpt_dong'], $data['rcpt_hscp_nm'], $data['rcpt_dtl_addr'], $data['rcpt_li_addr'], $data['rcpt_jibun_addr'], $data['rcpt_etc_addr']);
        } else {
            $dupleGroundPlan = $this->model->getDupleGP($id, $data['rcpt_sido'], $data['rcpt_gugun'], $data['rcpt_dong'], $data['rcpt_hscp_nm'], $data['rcpt_dtl_addr'], $data['rcpt_ho']);
        }
        log_message('info', '[Receipt::detail] getDupleGP {ms}ms', ['ms' => (int) ((microtime(true) - $t5) * 1000)]);

        $t6 = microtime(true);
        $aptGround = $this->model->getAptGround($data['rcpt_dong'] ?? '');
        log_message('info', '[Receipt::detail] getAptGround {ms}ms', ['ms' => (int) ((microtime(true) - $t6) * 1000)]);


        // 이미지 파일리스트
        $t7 = microtime(true);
        $images = $this->model->getImageList2($data['rsrv_sq']);
        log_message('info', '[Receipt::detail] getImageList2 {ms}ms', ['ms' => (int) ((microtime(true) - $t7) * 1000)]);

        $t8 = microtime(true);
        $imgs_count = $this->model->getImageCountByType($data['rsrv_sq']);
        log_message('info', '[Receipt::detail] getImageCountByType {ms}ms', ['ms' => (int) ((microtime(true) - $t8) * 1000)]);
        $imgs_count = convertArrayToHashTable($imgs_count, 'img_type', 'img_cnt');

        //녹취파일
        $t9 = microtime(true);
        $record = $this->model->getRecordInfo($data['rsrv_sq']);
        log_message('info', '[Receipt::detail] getRecordInfo {ms}ms', ['ms' => (int) ((microtime(true) - $t9) * 1000)]);

        // 시간대별통계
        $t10 = microtime(true);
        $tmCount = $this->model->getUsrRsrvDateTmCount($id);
        log_message('info', '[Receipt::detail] getUsrRsrvDateTmCount {ms}ms', ['ms' => (int) ((microtime(true) - $t10) * 1000)]);

        // 당일 방문예정 매물.
        $assignList = $this->model->getAssignReceiptListByUser($data['rsrv_date'], $data['usr_sq'], array($id));

        // 체크리스트 조회
        $t11 = microtime(true);
        if ($data['exp_photo_yn'] === "N") {
            $result_check = $this->model->getChecklist($data['rsrv_sq']);
        } else {
            $result_check = [];
        }

        $pdept = '';
        if (!empty($data['dept_sq'])) {
            $pdept = $this->model->getDeptDetail($data['dept_sq']);
        } else {
            $pdept = $this->model->getDeptDetail($data['region_dept_sq']);
        }

        $complexList = [];
        $ptpList = [];

        // print_r($data);
        // exit;

        if ($data['comp_sq'] == '2') {
            // 아파트단지목록
            $complexList = $naver->complexList($data['rcpt_dong']);

            // 평형목록
            $ptpList = $naver->ptpList($data['rcpt_hscp_no']);
        }

        // print_r($ptpList);
        // exit;

        log_message('info', '[Receipt::detail] getChecklist {ms}ms', ['ms' => (int) ((microtime(true) - $t11) * 1000)]);

        log_message('info', '[Receipt::detail] total {ms}ms', ['ms' => (int) ((microtime(true) - $t0) * 1000)]);

        $this->data['codes'] = $codes;
        $this->data['bonbu'] = $bonbu;
        $this->data['team'] = $team;
        $this->data['damdang'] = $damdang;
        $this->data['pdept'] = $pdept;

        $this->data['sms'] = $sms;

        $this->data['data'] = $data;
        $this->data['assignList'] = $assignList;
        $this->data['history'] = $history;

        $this->data['dupleGroundPlan'] = $dupleGroundPlan;
        $this->data['apt_ground'] = $aptGround;

        $this->data['images'] = $images;
        $this->data['imgs_count'] = $imgs_count;

        $this->data['record'] = $record;

        $this->data['tmCount'] = $tmCount;
        $this->data['result_check'] = $result_check;

        $this->data['complexList'] = $complexList;
        $this->data['ptpList'] = $ptpList;


        return view("pages/article/receipt/detail", $this->data);
    }


    // 연락처 저장
    public function saveTel()
    {
        try {

            $tel = $this->request->getPost('agent_tel');

            $this->model->saveTel($tel);


            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success'
            ]);

        } catch (\Exception $e) {
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }

    // 거주여부 저장
    public function resDbYn()
    {
        $naver = new NaverApiClient();

        try {

            $rcpt_key = $this->request->getPost('rcpt_key');
            $rcpt_sq = $this->request->getPost('rcpt_sq');
            $rsrv_sq = $this->request->getPost('rsrv_sq');
            $res_yn = $this->request->getPost('resYn');
            $dbUsageAgrYn = $this->request->getPost('dbUsageAgrYn');

            $this->model->saveResDB($rcpt_sq, $rsrv_sq, $res_yn, $dbUsageAgrYn);

            $receipt = $this->model->getDetail($rcpt_key);
            if ($res_yn == 'Y') {
                $isResidentsExist = true;
            } else {
                $isResidentsExist = false;
            }

            $updateData = [
                'residentsExistence' => $isResidentsExist
            ];

            $charger = session('usr_id');

            log_message('info', '[resDbYn] 네이버 API 호출 시작 - rcpt_key: ' . $rcpt_key . ', charger: ' . $charger . ', updateData: ' . json_encode($updateData, JSON_UNESCAPED_UNICODE));
            
            $api_result = $naver->updateArticleInfo($rcpt_key, $updateData, $charger);
            
            log_message('info', '[resDbYn] 네이버 API 응답 - result: ' . json_encode($api_result, JSON_UNESCAPED_UNICODE) . ' (type: ' . gettype($api_result) . ')');

            // API 호출 실패 체크
            if (isset($api_result['error']) && $api_result['error'] === true) {
                // 에러 정보를 상세하게 표시
                if ($api_result['error_type'] === 'CURL_ERROR') {
                    $errorMsg = "네이버 API 통신 실패 (CURL 오류)\n";
                    $errorMsg .= "오류코드: {$api_result['curl_errno']}\n";
                    $errorMsg .= "오류내용: {$api_result['curl_error']}\n";
                    $errorMsg .= "URL: {$api_result['url']}";
                } else {
                    $errorMsg = "네이버 API 응답 오류 (HTTP {$api_result['http_code']})\n";
                    $errorMsg .= "응답내용: {$api_result['response']}\n";
                    $errorMsg .= "URL: {$api_result['url']}";
                }
                throw new \Exception($errorMsg);
            }
            
            // 정상 응답이지만 성공이 아닌 경우
            if (!isset($api_result['code']) || $api_result['code'] !== 'success') {
                $errorMsg = "네이버 API 응답 오류\n";
                $errorMsg .= "응답: " . json_encode($api_result, JSON_UNESCAPED_UNICODE);
                throw new \Exception($errorMsg);
            }

            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success'
            ]);

        } catch (\Exception $e) {
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }

    // 평면도요청 저장
    public function resGround()
    {
        try {

            $rcpt_sq = $this->request->getPost('rcpt_sq');
            $ground_plan = $this->request->getPost('ground_plan');

            $this->model->saveGround($rcpt_sq, $ground_plan);


            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success'
            ]);

        } catch (\Exception $e) {
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }

    // 예약확정 저장
    public function assignRegist()
    {
        $naver = new NaverApiClient();
        $deptModel = new DeptModel();

        try {

            //전달받은 값
            $rcpt_sq = $this->request->getPost('rcpt_sq');
            $rcpt_key = $this->request->getPost('rcpt_key');
            $rsrv_sq = $this->request->getPost('rsrv_sq');
            $rsrv_date = $this->request->getPost('rsrv_date');
            $rsrv_tm_ap = $this->request->getPost('rsrv_tm_ap');
            $rsrv_tm_hour = $this->request->getPost('rsrv_tm_hour');
            $bonbu = $this->request->getPost('bonbu');
            $dept_sq = $this->request->getPost('dept_sq');
            $usr_sq = $this->request->getPost('usr_sq');

            $bonbuInfo = $deptModel->getDeptDetail($bonbu);
            $deptInfo = $deptModel->getDeptDetail($dept_sq);
            $userInfo = $this->model->getUserDetail($usr_sq);
            $receipt = $this->model->getDetail($rcpt_key);

            /*** 네이버 연동[s] ***/
            $na_result = $naver->reserveSuccess($rcpt_key, 'Y', $bonbuInfo['dept_nm'], $deptInfo['dept_nm'], $userInfo['usr_nm'], $userInfo['usr_tel1'], $rsrv_date, $rsrv_tm_ap);
            /*** 네이버 연동[e] ***/

            if (isset($na_result['code']) && $na_result['code'] === 'success') { //네이버연동 상태변경 완료
                $result = $this->model->assignRegist($rcpt_sq, $rsrv_date, $rsrv_tm_ap, $rsrv_tm_hour, $dept_sq, $usr_sq, $receipt);

                return $this->response->setJSON([
                    'code' => '0',
                    'msg' => 'success'
                ]);
            } else {
                throw new \Exception($na_result['message'] ?? '네이버 API 연동 실패');
            }


        } catch (\Exception $e) {
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }

    // 동영상촬영여부 저장
    public function requestMovie()
    {
        try {

            $rcpt_sq = $this->request->getPost('rcpt_sq');
            $rsrv_sq = $this->request->getPost('rsrv_sq');
            $exp_movie_yn = $this->request->getPost('exp_movie_yn');

            $this->model->saveRequestMovie($rcpt_sq, $rsrv_sq, $exp_movie_yn);


            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success'
            ]);

        } catch (\Exception $e) {
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }

    // 중개사메모 저장
    public function requestMessage()
    {
        try {

            $rcpt_sq = $this->request->getPost('rcpt_sq');
            $rsrv_sq = $this->request->getPost('rsrv_sq');
            $request_msg = $this->request->getPost('request_msg');

            $this->model->saveRequestMessage($rcpt_sq, $rsrv_sq, $request_msg);


            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success'
            ]);

        } catch (\Exception $e) {
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }

    // 예약취소
    public function rsrvcancel()
    {
        $naver = new NaverApiClient();

        try {
            //전달받은 값
            $rcpt_sq = $this->request->getPost('rcpt_sq');
            $rsrv_sq = $this->request->getPost('rsrv_sq');
            $rcpt_key = $this->request->getPost('rcpt_key');
            $result_cd2 = $this->request->getPost('result_cd2');
            $result_cd3 = $this->request->getPost('result_cd3');
            $result_msg = $this->request->getPost('result_msg');
            $rcpt_stat1 = $this->request->getPost('rcpt_stat1');

            $receipt = $this->model->getDetail($rcpt_key);

            /*** 네이버 연동[s] ***/
            if ($result_cd2 == '9010' || $result_cd2 == '9020') {	//예약취소
                $na_result = $naver->reserveFail($rcpt_key, "E11", $result_msg);
            } else if ($result_cd2 == '9030') {
                if ($rcpt_stat1 == '70') {
                    throw new \Exception('방문전 취소 할 수 없습니다.');
                } else {
                    $na_result = $naver->shootFail($rcpt_key, "E21", $result_msg);
                }
            } else if ($result_cd2 == '9040') {
                $na_result = $naver->shootFail($rcpt_key, "E22", $result_msg);
            } else if ($result_cd2 == '9045') {
                $na_result = $naver->shootFail($rcpt_key, "E23", $result_msg);
            } else if ($result_cd2 == '9050') {
                $na_result = $naver->inspectFail($rcpt_key, 'E31', $result_msg);
            }
            /*** 네이버 연동[e] ***/

            if (isset($na_result['code']) && $na_result['code'] === 'success') { //네이버연동 상태변경 완료
                $result = $this->model->rsrvcancel($rcpt_sq, $rsrv_sq, $result_cd2, $result_cd3, $result_msg, $receipt);

            } else {
                throw new \Exception($na_result['message'] ?? '네이버 API 연동 실패');
            }

            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success'
            ]);

        } catch (\Exception $e) {
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }

    // 상태변경
    public function chgStatus()
    {
        try {

            $rcpt_sq = $this->request->getPost('rcpt_sq');
            $rcpt_key = $this->request->getPost('rcpt_key');
            $rcpt_stat = $this->request->getGet('rcpt_stat');
            $rsrv_sq = $this->request->getPost('rsrv_sq');
            $req_rec_yn = $this->request->getGet('reqRecYn');

            $rsrv_date = $this->request->getPost('rsrv_date');
            $rsrv_tm_ap = $this->request->getPost('rsrv_tm_ap');
            $rsrv_tm_hour = $this->request->getPost('rsrv_tm_hour');
            $bonbu = $this->request->getPost('bonbu');
            $dept_sq = $this->request->getPost('dept_sq');
            $usr_sq = $this->request->getPost('usr_sq');

            $rletTypeCd = $this->request->getGet('rletTypeCd');

            // 파라미터 디버그 로깅
            $p = [
                'rcpt_sq' => $rcpt_sq,
                'rcpt_key' => $rcpt_key,
                'rcpt_stat' => $rcpt_stat,
                'rsrv_sq' => $rsrv_sq,
                'req_rec_yn' => $req_rec_yn,
                'rsrv_date' => $rsrv_date,
                'rsrv_tm_ap' => $rsrv_tm_ap,
                'rsrv_tm_hour' => $rsrv_tm_hour,
                'bonbu' => $bonbu,
                'dept_sq' => $dept_sq,
                'usr_sq' => $usr_sq,
                'rletTypeCd' => $rletTypeCd,
            ];


            print_r($p);
            exit;


        } catch (\Exception $e) {
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }


    // 문자발송
    public function sendSms()
    {
        try {
            $rcpt_key = $this->request->getPost('rcpt_key');
            $rcpt_sq = $this->request->getPost('rcpt_sq');
            $rsrv_sq = $this->request->getPost('rsrv_sq');
            $cd = $this->request->getPost('cd');

            $send_phone = "1600-5749";
            $phone = $this->request->getPost('phone');
            $content = $this->request->getPost('content');
            $send_nm = session('usr_nm');

            $data = $this->model->getDetail($rcpt_key);

            $dest_name = "";
            if ($cd == "S7" || $cd == "S14") {
                $dest_name = "(거주인)" . $data['rec_nm'];
            } else {
                $dest_name = "(중개인)" . $data['agent_nm'];
            }

            $this->model->sendSms($phone, "", $send_phone, $send_nm, $dest_name, $rsrv_sq, $rcpt_sq, $cd, $data);

            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success'
            ]);

        } catch (\Exception $e) {
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }

    // 거주인정보저장
    public function saveRecInfo()
    {
        $lib = new MyUpload();

        try {
            $rcpt_sq = $this->request->getPost('rcpt_sq');
            $rcpt_key = $this->request->getPost('rcpt_key');
            $rsrv_sq = $this->request->getPost('rsrv_sq');

            $rec_tel1 = $this->request->getPost('rec_tel1');
            $rec_tel2 = $this->request->getPost('rec_tel2');
            $rec_tel3 = $this->request->getPost('rec_tel3');
            $rec_tel = $rec_tel1 . '-' . $rec_tel2 . '-' . $rec_tel3;

            $rec_nm = $this->request->getPost('rec_nm');
            $rec_remark = $this->request->getPost('rec_remark');

            $data = [
                'rcpt_sq' => $rcpt_sq,
                'rsrv_sq' => $rsrv_sq,
                'rcpt_key' => $rcpt_key,
                'rec_tel' => $rec_tel,
                'rec_nm' => $rec_nm,
                'rec_remark' => $rec_remark,
            ];

            // 파일 업로드 처리
            $file = $this->request->getFile('rec_file');
            if ($file && $file->isValid() && !$file->hasMoved()) {
                $uploadPath = "/upload/result/" . $rsrv_sq . "/";
                $uploadData = $lib->do_upload2($file, $uploadPath);

                if ($uploadData !== false && is_array($uploadData)) {
                    // do_upload2 반환값 구조: object_key, object_storage_url, origin_name, file_name, base_name, ext
                    $data['file'] = [
                        'upload_path' => $uploadPath,
                        'file_name' => isset($uploadData['file_name']) ? $uploadData['file_name'] : '',
                        'origin_name' => isset($uploadData['origin_name']) ? $uploadData['origin_name'] : '',
                        'ext' => isset($uploadData['ext']) ? $uploadData['ext'] : '',
                        'size' => $file->getSize(),
                    ];
                } else {
                    throw new \Exception('파일 업로드에 실패했습니다.');
                }
            }

            $result = $this->model->saveRecInfo($data);

            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success',
                'data' => [
                    'rec_tel' => $result['rec_tel'] ?? '',
                    'rec_nm' => $result['rec_nm'] ?? '',
                    'remark' => $result['remark'] ?? '',
                    'record' => $result['record'] ?? null
                ]
            ]);

        } catch (\Exception $e) {
            log_message('error', '[Receipt::saveRecInfo] Error: ' . $e->getMessage());
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }

    // 거주인 정보 조회
    public function getRecInfo()
    {
        try {
            $rcpt_sq = $this->request->getGet('rcpt_sq');
            
            if (empty($rcpt_sq)) {
                throw new \Exception('rcpt_sq가 필요합니다.');
            }

            // 거주인 정보 조회
            $recInfo = $this->model->getRecInfoByRcptSq($rcpt_sq);
            
            if (empty($recInfo)) {
                throw new \Exception('거주인 정보를 찾을 수 없습니다.');
            }

            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success',
                'data' => $recInfo
            ]);

        } catch (\Exception $e) {
            log_message('error', '[Receipt::getRecInfo] Error: ' . $e->getMessage());
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }

    // 정보변경 이력 조회
    public function getHistory()
    {
        try {
            $rcpt_sq = $this->request->getGet('rcpt_sq');
            
            if (empty($rcpt_sq)) {
                throw new \Exception('rcpt_sq가 필요합니다.');
            }

            // 정보변경 이력 조회
            $history = $this->model->getHistory($rcpt_sq);

            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success',
                'data' => $history ?? []
            ]);

        } catch (\Exception $e) {
            log_message('error', '[Receipt::getHistory] Error: ' . $e->getMessage());
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }


    // 파일업로드
    public function uploadFile()
    {
        $lib = new MyUpload();
        $common = new Common();

        try {

            $rcpt_key = $this->request->getPost('rcpt_key');
            $rsrv_sq = $this->request->getPost('rsrv_sq');
            $rcpt_sq = $this->request->getPost('rcpt_sq');
            $img_type = $this->request->getPost('img_type');
            $img_sub_type = $this->request->getPost('img_sub_type');
            $file_order = $this->request->getPost('file_order');

            log_message('info', '[Receipt::uploadFile] Request received - rcpt_key:{rcpt_key}, rsrv_sq:{rsrv_sq}, rcpt_sq:{rcpt_sq}, img_type:{img_type}, img_sub_type:{img_sub_type}, file_order:{file_order}', [
                'rcpt_key' => $rcpt_key,
                'rsrv_sq' => $rsrv_sq,
                'rcpt_sq' => $rcpt_sq,
                'img_type' => $img_type,
                'img_sub_type' => $img_sub_type,
                'file_order' => $file_order,
            ]);

            // 필수 파라미터 검증
            if (empty($rsrv_sq)) {
                log_message('error', '[Receipt::uploadFile] rsrv_sq is empty');
                return $this->response->setJSON([
                    'code' => '9',
                    'msg' => 'rsrv_sq(예약일련번호)가 필요합니다.'
                ]);
            }

            $files = $this->request->getFiles();
            $uploadPath = "/upload/result/" . $rsrv_sq . "/";

            if (!isset($files['files'])) {
                return $this->response->setJSON([
                    'success' => false,
                    'msg' => '파일 없음'
                ]);
            }

            $uploadFiles = $files['files'];
            if ($uploadFiles instanceof \CodeIgniter\HTTP\Files\UploadedFile) {
                $uploadFiles = [$uploadFiles];
            }

            // 매물정보 가져오기
            $receipt = $this->model->getDetail($rcpt_key);

            // 워터마크 이미지 조회
            $watermark_info = [];
            if (!empty($receipt) && !empty($receipt['rcpt_cpid'])) {
                $watermark_info = $this->model->getWatermarkList($receipt['rcpt_cpid']);
            }

            $arrUploadfile = [];
            foreach ($uploadFiles as $file) {

                log_message('info', '[Receipt::uploadFile] upload start name={name} size={size} type={type} error={error}:{errorString} path={path}', [
                    'name' => $file->getName(),
                    'size' => $file->getSize(),
                    'type' => $file->getMimeType(),
                    'error' => $file->getError(),
                    'errorString' => $file->getErrorString(),
                    'path' => $uploadPath,
                ]);

                $uploadData = $lib->do_upload2($file, $uploadPath);

                if ($uploadData !== false) {
                    $arrUploadfile[] = $uploadData;
                    log_message('info', '[Receipt::uploadFile] upload success name={name} stored={stored} cloud_url={url}', [
                        'name' => $file->getName(),
                        'stored' => $uploadData['file_name'] ?? '(unknown)',
                        'url' => $uploadData['object_storage_url'] ?? '(none)',
                    ]);
                } else {
                    log_message('error', '[Receipt::uploadFile] Cloud upload failed name={name}', [
                        'name' => $file->getName(),
                    ]);
                    
                    // 클라우드 업로드 실패 시 즉시 에러 반환
                    return $this->response->setJSON([
                        'code' => '9',
                        'msg' => '클라우드 스토리지 업로드 실패: ' . $file->getName() . '\n네트워크 연결 또는 권한을 확인해주세요.'
                    ]);
                }

            }

            $gps_lat = null;
            $gps_lon = null;
            $camDate = null;
            if (!empty($arrUploadfile)) {
                foreach ($arrUploadfile as $key => $uploadFile) {
                    $object_storage_url = $uploadFile['object_storage_url'];
                    $imgWidth = '';
                    $imgHeight = '';

                    if ($img_type !== 'V1') {
                        $base = $uploadFile['base_name'];     // xxxx
                        $dir = rtrim(dirname($uploadFile['object_key']), '/'); // upload/result/*
                        $thumbKey = $dir . '/' . $base . '_thumb.jpg';

                        try {
                            // 원본 이미지 다운로드 (클라우드에서)
                            $imageDataBlob = file_get_contents($object_storage_url);
                            
                            if (!$imageDataBlob) {
                                throw new \Exception('Failed to download original image from cloud storage');
                            }
                            
                            if (class_exists('\Imagick')) {
                                // Imagick 사용
                                $im = new \Imagick();
                                $im->readImageBlob($imageDataBlob);
                                $imgWidth = $im->getImageWidth();
                                $imgHeight = $im->getImageHeight();
                                $im->thumbnailImage(105, 80, false);
                                $thumb_im = $im->getImageBlob();
                                $im->destroy();
                                
                                // 썸네일 클라우드 업로드
                                $thumbUploaded = $lib->upload_object_storage_imagick2($thumbKey, $thumb_im);
                                if (!$thumbUploaded) {
                                    log_message('warning', '[Receipt::uploadFile] Thumbnail cloud upload failed: {key}', ['key' => $thumbKey]);
                                }
                                
                            } elseif (extension_loaded('gd')) {
                                // GD 라이브러리 사용
                                $source = imagecreatefromstring($imageDataBlob);
                                if ($source !== false) {
                                    $imgWidth = imagesx($source);
                                    $imgHeight = imagesy($source);
                                    
                                    // 썸네일 크기 계산 (105x80 비율 유지)
                                    $thumb_width = 105;
                                    $thumb_height = 80;
                                    
                                    // 썸네일 이미지 생성
                                    $thumb = imagecreatetruecolor($thumb_width, $thumb_height);
                                    imagecopyresampled($thumb, $source, 0, 0, 0, 0, $thumb_width, $thumb_height, $imgWidth, $imgHeight);
                                    
                                    // JPEG로 변환
                                    ob_start();
                                    imagejpeg($thumb, null, 85);
                                    $thumb_im = ob_get_clean();
                                    
                                    // 메모리 해제
                                    imagedestroy($source);
                                    imagedestroy($thumb);
                                    
                                    // 썸네일 클라우드 업로드
                                    $thumbUploaded = $lib->upload_object_storage_imagick2($thumbKey, $thumb_im);
                                    if (!$thumbUploaded) {
                                        log_message('warning', '[Receipt::uploadFile] Thumbnail cloud upload failed: {key}', ['key' => $thumbKey]);
                                    }
                                    
                                    log_message('info', '[Receipt::uploadFile] Thumbnail created with GD: {key}', ['key' => $thumbKey]);
                                } else {
                                    log_message('warning', '[Receipt::uploadFile] GD failed to create image from string');
                                }
                            } else {
                                log_message('warning', '[Receipt::uploadFile] No image library available (Imagick or GD), skipping thumbnail generation');
                            }
                        } catch (\Exception $e) {
                            log_message('error', '[Receipt::uploadFile] Thumbnail generation failed: {message}', [
                                'message' => $e->getMessage(),
                            ]);
                        }
                    }


                    // 워터마크 삽입
                    $watermark_imgs = ['I3', 'I4'];
                    if (in_array($img_type, $watermark_imgs) && !empty($watermark_info)) {
                        $common->watermarking($object_storage_url, $watermark_info, '', $receipt['rcpt_cpid'], $uploadFile['object_key']);
                    }

                    // 촬영정보 가져오기
                    $arrExifData = @exif_read_data($object_storage_url);
                    if (!is_array($arrExifData)) {
                        $arrExifData = [];
                    }
                    if (!isset($arrExifData['COMPUTED']) || !is_array($arrExifData['COMPUTED'])) {
                        $arrExifData['COMPUTED'] = [];
                    }
                    $notFound = "Unavailable";

                    // Make - 카메라 제조사
                    if (@array_key_exists('Make', $arrExifData)) {
                        $camMake = $arrExifData['Make'];
                    } else {
                        $camMake = $notFound;
                    }

                    // Model - 카메라 모델
                    if (@array_key_exists('Model', $arrExifData)) {
                        $camModel = $arrExifData['Model'];
                    } else {
                        $camModel = $notFound;
                    }

                    // Date - 촬영일시
                    if (@array_key_exists('DateTime', $arrExifData)) {
                        $camDate = $arrExifData['DateTime'];
                    } else {
                        $camDate = $notFound;
                    }

                    // COMPUTED.Height - 세로크기
                    if (@array_key_exists('Height', $arrExifData['COMPUTED'])) {
                        $camHeight = $arrExifData['COMPUTED']['Height'];
                    } else {
                        $camHeight = $notFound;
                    }

                    // COMPUTED.Width - 가로크기
                    if (@array_key_exists('Width', $arrExifData['COMPUTED'])) {
                        $camWidth = $arrExifData['COMPUTED']['Width'];
                    } else {
                        $camWidth = $notFound;
                    }

                    $imageMetaData = "카메라 제조사: " . $camMake;
                    $imageMetaData .= "\n카메라 모델: " . $camModel;
                    $imageMetaData .= "\n촬영일시: " . $camDate;
                    $imageMetaData .= "\n가로: " . $camWidth;
                    $imageMetaData .= "\n세로: " . $camHeight;

                    $metaData = $imageMetaData;

                    /** 
                     * 파일업로드 내용 저장
                     */
                    $uploadParam = [
                        'rcpt_key' => $rcpt_key, // 접수번호
                        'rsrv_sq' => $rsrv_sq, // 예약일련번호
                        'rcpt_sq' => $rcpt_sq, // 접수일련번호
                        // 'gps_lat' => $gps_lat, // latitude
                        // 'gps_lon' => $gps_lon, // longitude
                        'origin_name' => $uploadFile['origin_name'], // 원본파일명
                        'file_name' => $uploadFile['file_name'], // 저장파일명
                        'upload_path' => $uploadPath, // 저장경로
                        'size' => $file->getSize(),
                        'width' => $imgWidth,
                        'height' => $imgHeight,
                        // 'thumb_name' => $base . '_thumb.jpg',
                        'cam_date' => $camDate, // 촬영일
                        'meta_data' => $metaData, // 이미지메타데이터
                        'receipt' => $receipt,
                        'img_type' => $img_type,
                        'cloud_upload_yn' => 'Y', // 클라우드 업로드 성공 (여기까지 왔으면 성공)
                    ];

                    $img_sq = $this->model->saveImg($uploadParam);

                }
            }

            // 성공 응답 - JavaScript에서 사용할 이미지 정보 포함
            $lastUploadedFile = end($arrUploadfile);
            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success',
                'img_sq' => $img_sq ?? null,
                'img_path' => $uploadPath,
                'img_filenm' => $lastUploadedFile['file_name'] ?? '',
                'cloud_upload_yn' => 'Y',
                'img_location' => ''
            ]);

        } catch (\Exception $e) {
            log_message('error', '[Receipt::uploadFile] Exception occurred: {message} at {file}:{line}', [
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString(),
            ]);
            
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);

        }
    }

    // 매물사진 일괄 다운로드 (zip)
    public function downloadAllImages()
    {
        $rsrv_sq = $this->request->getGet('rsrv_sq');
        $img_type = $this->request->getGet('img_type') ?? 'I4';

        if (empty($rsrv_sq)) {
            return $this->response->setStatusCode(400)->setBody('rsrv_sq required');
        }

        $images = $this->model->getImageListByType($rsrv_sq, $img_type);
        if (empty($images)) {
            return $this->response->setStatusCode(404)->setBody('No files');
        }

        $zip = new \ZipArchive();
        $zipName = 'images_' . $rsrv_sq . '_' . $img_type . '_' . date('Ymd_His') . '.zip';
        $zipPath = WRITEPATH . 'cache/' . $zipName;

        if ($zip->open($zipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
            return $this->response->setStatusCode(500)->setBody('Failed to create zip');
        }

        foreach ($images as $index => $img) {
            $filePath = $img['img_path'] . $img['img_filenm'];
            $zipFileName = sprintf('%02d_%s', $index + 1, basename($img['img_filenm']));

            if (($img['cloud_upload_yn'] ?? 'N') === 'Y') {
                $sourceUrl = NCLOUD_OBJECT_STORAGE_URL . $filePath;
                $content = @file_get_contents($sourceUrl);
                if ($content !== false) {
                    $zip->addFromString($zipFileName, $content);
                }
                continue;
            }

            $localPath = FCPATH . ltrim($filePath, '/');
            if (is_file($localPath)) {
                $zip->addFile($localPath, $zipFileName);
                continue;
            }

            $content = @file_get_contents($filePath);
            if ($content !== false) {
                $zip->addFromString($zipFileName, $content);
            }
        }

        $zip->close();

        if (!is_file($zipPath)) {
            return $this->response->setStatusCode(500)->setBody('Zip not found');
        }

        register_shutdown_function(static function () use ($zipPath) {
            if (is_file($zipPath)) {
                @unlink($zipPath);
            }
        });

        return $this->response->download($zipPath, null)->setFileName($zipName);
    }

    // 촬영위치 저장
    public function saveImgLocation()
    {
        try {

            $img_sq = $this->request->getPost('img_sq');
            $rsrv_sq = $this->request->getPost('rsrv_sq');
            $location = $this->request->getPost('location');

            $this->model->saveImgLocation($img_sq, $rsrv_sq, $location);

            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success'
            ]);

        } catch (\Exception $e) {
            return $this->response->setJSON([
                'code' => '9',
                'msg' => $e->getMessage(),
            ]);
        }
    }

    // 업로드파일 목록 조회 (AJAX용)
    public function getImages()
    {
        try {
            $rsrv_sq = $this->request->getGet('rsrv_sq') ?? $this->request->getPost('rsrv_sq');
            $img_type = $this->request->getGet('img_type') ?? $this->request->getPost('img_type');

            if (empty($rsrv_sq)) {
                return $this->response->setJSON([
                    'success' => false,
                    'msg' => 'rsrv_sq가 필요합니다.'
                ]);
            }

            // 전체 이미지 리스트 조회
            $images = $this->model->getImageList2($rsrv_sq);

            // img_type이 지정된 경우 필터링
            if (!empty($img_type)) {
                $images = array_filter($images, function($img) use ($img_type) {
                    return $img['img_type'] === $img_type;
                });
                $images = array_values($images); // 인덱스 재정렬
            }

            // 이미지 URL 생성
            foreach ($images as &$img) {
                $temp = explode(".", $img['img_filenm']);
                $thumbName = $temp[0] . "_thumb.jpg";
                
                $localOriginalPath = $img['img_path'] . $img['img_filenm'];
                $localThumbPath = $img['img_path'] . $thumbName;
                
                // 모든 파일은 클라우드에 저장됨
                if (($img['cloud_upload_yn'] ?? 'Y') === 'Y') {
                    $img['original_url'] = NCLOUD_OBJECT_STORAGE_URL . $localOriginalPath;
                    $img['thumbnail_url'] = NCLOUD_OBJECT_STORAGE_URL . $localThumbPath;
                } else {
                    // 혹시 모를 레거시 로컬 파일 (로컬 파일 시스템 체크)
                    $localThumbFullPath = FCPATH . $localThumbPath;
                    if (file_exists($localThumbFullPath)) {
                        $img['thumbnail_url'] = $localThumbPath;
                    } else {
                        $img['thumbnail_url'] = $localOriginalPath;
                    }
                    $img['original_url'] = $localOriginalPath;
                }
            }

            return $this->response->setJSON([
                'success' => true,
                'images' => $images
            ]);

        } catch (\Exception $e) {
            log_message('error', '[Receipt::getImages] Error: ' . $e->getMessage());
            return $this->response->setJSON([
                'success' => false,
                'msg' => $e->getMessage()
            ]);
        }
    }

    // 업로드파일 삭제
    public function removeUploadFile()
    {

        try {

            $rcpt_sq = $this->request->getPost('rcpt_sq');
            $img_sq = $this->request->getPost('img_sq');

            // 파일정보 조회
            $file = $this->model->getUploadFileInfo($img_sq);
            if (!empty($file)) {
                $lib = new MyUpload();

                $path = $file['img_path'] . "" . $file['img_filenm'];


                $thumb = explode(".", $file['img_filenm']);
                $thumbPath = $file['img_path'] . "" . $thumb[0] . "_thumb." . $thumb[1];

                // if ($file['cloud_upload_yn'] == "Y") {
                //     $path = NCLOUD_OBJECT_STORAGE_URL . $path;
                // }

                $lib->deleteFile($path);
                $lib->deleteFile($thumbPath);
            }

            $result = $this->model->removeUploadFile($rcpt_sq, $img_sq);

            if (!$result['success']) {
                return $this->response->setJSON([
                    'code' => '1',
                    'msg' => $result['msg'] ?? '삭제 실패'
                ]);
            }

            return $this->response->setJSON([
                'code' => '0',
                'msg' => 'success'
            ]);
        } catch (\Exception $e) {
            log_message('error', 'removeUploadFile error: ' . $e->getMessage());
            return $this->response->setJSON([
                'code' => '1',
                'msg' => '삭제 중 에러가 발생했습니다: ' . $e->getMessage()
            ]);
        }
    }
    
    // 이미지 순서 업데이트
    public function updateImageOrder()
    {
        try {
            $rcpt_sq = $this->request->getPost('rcpt_sq');
            $img_type = $this->request->getPost('img_type');
            $orders = $this->request->getPost('orders');
            
            log_message('info', '[updateImageOrder] 요청 데이터 - rcpt_sq: ' . $rcpt_sq . ', img_type: ' . $img_type . ', orders: ' . $orders);
            
            if (!$rcpt_sq || !$img_type || !$orders) {
                log_message('error', '[updateImageOrder] 필수 파라미터 누락');
                return $this->response->setJSON([
                    'code' => '1',
                    'msg' => '필수 파라미터가 누락되었습니다.'
                ]);
            }
            
            // JSON 파싱
            $orderData = json_decode($orders, true);
            if (!is_array($orderData)) {
                return $this->response->setJSON([
                    'code' => '1',
                    'msg' => '순서 데이터 형식이 올바르지 않습니다.'
                ]);
            }
            
            // 순서 업데이트
            $result = $this->model->updateImageOrder($rcpt_sq, $img_type, $orderData);
            
            if (!$result['success']) {
                return $this->response->setJSON([
                    'code' => '1',
                    'msg' => $result['msg'] ?? '순서 업데이트 실패'
                ]);
            }
            
            return $this->response->setJSON([
                'code' => '0',
                'success' => true,
                'msg' => '순서가 저장되었습니다.'
            ]);
            
        } catch (\Exception $e) {
            log_message('error', 'updateImageOrder error: ' . $e->getMessage());
            return $this->response->setJSON([
                'code' => '1',
                'msg' => '순서 업데이트 중 에러가 발생했습니다: ' . $e->getMessage()
            ]);
        }
    }
}