<?php

namespace App\Services\Handlers;

use CodeIgniter\CLI\CLI;
use App\Services\ParameterMapper\TypeV2ParameterMapper;
use App\Models\Entities\VrfcReqModel;
use App\Models\Entities\V2articleinfoModel;
use App\Models\Entities\V2articleinfoetcModel;
use App\Models\Entities\V2modifyinfoModel;
use App\Models\Entities\V2urlimgsaveModel;
use App\Services\StatusService;
use Exception;

/**
 * Type V2 핸들러
 * 일반/서류/비공동 매물 (D04, F01 등) 데이터 처리
 */
class TypeV2Handler
{
    private $vrfcReqModel;
    private $articleInfoModel;
    private $articleInfoEtcModel;
    private $modifyInfoModel;
    private $urlImgSaveModel;
    private $statusService;
    private $db;
    private $parameterMapper;
    
    public function __construct()
    {
        $this->db = \Config\Database::connect();
        $this->vrfcReqModel = new VrfcReqModel();
        $this->articleInfoModel = new V2articleinfoModel();
        $this->articleInfoEtcModel = new V2articleinfoetcModel();
        $this->modifyInfoModel = new V2modifyinfoModel();
        $this->urlImgSaveModel = new V2urlimgsaveModel();
        $this->statusService = new StatusService();
        $this->parameterMapper = new TypeV2ParameterMapper();
        helper('log');
    }
    
    /**
     * Type V2 메인 처리 로직
     */
    public function handle(string $articleNumber, array $rawData, array $payload): int
    {
        CLI::write(CLI::color('🟢 Type V2 처리 시작 :: ' . $articleNumber, 'green'));
        write_custom_log("TypeV2Handler 진입 | Atcl: $articleNumber | Payload: " . json_encode($payload), 'INFO', 'service');
        
        try {
            $requestType = $payload['requestType'] ?? 'REG';
            CLI::write(CLI::color("🔵 RequestType: $requestType", 'cyan'));
            
            switch ($requestType) {
                case 'REG':
                    return $this->handleRegister($articleNumber, $rawData, $payload);
                case 'MOD':
                    return $this->handleModify($articleNumber, $rawData, $payload);
                case 'CNC':
                    return $this->handleCancel($articleNumber, $rawData, $payload);
                default:
                    throw new Exception("알 수 없는 requestType: $requestType");
            }
            
        } catch (Exception $e) {
            $errorDetail = "Type V2 처리 실패 | Atcl: $articleNumber | Error: " . $e->getMessage() . " | File: " . $e->getFile() . ":" . $e->getLine();
            write_custom_log($errorDetail, 'ERROR', 'service');
            CLI::write(CLI::color("❌ " . $errorDetail, 'red'));
            throw $e;
        }
    }
    
    /**
     * 신규 등록 처리
     */
    private function handleRegister(string $articleNumber, array $rawData, array $payload): int
    {
        CLI::write(CLI::color('🔵 V2 신규 등록 시작', 'cyan'));
        
        // 파라미터 준비
        $vrfcReqParam = $this->parameterMapper->mapVrfcReq($articleNumber, $rawData, $payload);
        $articleInfoParam = $this->parameterMapper->mapArticleInfo($articleNumber, $rawData, $payload);
        $articleInfoEtcParam = $this->parameterMapper->mapArticleInfoEtc($articleNumber, $rawData);
        $modifyInfoParam = $this->parameterMapper->mapModifyInfo($articleNumber, $rawData, $payload);
        
        // 검증 요청 저장 또는 업데이트
        $vrSq = $this->insertOrUpdateVrfcReq($vrfcReqParam);
        
        // 기사 정보 저장
        $articleInfoParam['vr_sq'] = $vrSq;
        if (!$this->articleInfoModel->replace($articleInfoParam)) {
            throw new Exception("ArticleInfo Insert 실패: " . json_encode($this->db->error()));
        }
        CLI::write(CLI::color('✅ ArticleInfo 저장 성공', 'blue'));
        
        // 기사 정보 추가 저장
        $articleInfoEtcParam['vr_sq'] = $vrSq;
        if (!$this->articleInfoEtcModel->replace($articleInfoEtcParam)) {
            CLI::write(CLI::color('❌ ArticleInfoEtc 저장 실패 :: ' . json_encode($articleInfoEtcParam), 'red'));
            throw new Exception("ArticleInfoEtc Insert 실패: " . json_encode($this->db->error()));
        }
        CLI::write(CLI::color('✅ ArticleInfoEtc 저장 성공', 'blue'));

        // 수정 정보 입력 (있으면 update, 없으면 insert)
        $modifyInfoParam['vr_sq'] = $vrSq;

        $sql = $this->modifyInfoModel->builder()->set($modifyInfoParam)->getCompiledInsert();
        CLI::write(CLI::color("\n[생성된 쿼리 예상안]:", 'yellow'));
        CLI::write($sql);

        if (!$this->modifyInfoModel->replace($modifyInfoParam)) {
            CLI::write(CLI::color('❌ modifyInfoParam 저장 실패 :: ' . json_encode($modifyInfoParam), 'red'));
            throw new Exception("ModifyInfo 저장 실패: " . json_encode($this->db->error() . " sql: " . $this->modifyInfoModel->getLastQuery()));
        }
        CLI::write(CLI::color('✅ ModifyInfo 저장 성공', 'blue'));
        
        // URL 이미지 저장 (v2_url_img_save 테이블)
        $files = $rawData['files'] ?? [];
        if (!empty($files)) {
            $fileExtracted = $this->parameterMapper->extractFilesByType($files);
            $this->saveUrlImagesToDb($fileExtracted, $articleNumber, $vrSq);
        }
        
        // 상태 기록
        $this->statusService->recordStatusAndHistory($vrSq, '10', 'C9', "NEW 신규접수 : 10");
        
        write_custom_log("V2 신규 등록 성공 | Atcl: $articleNumber | VR_SQ: $vrSq", 'INFO', 'service');
        
        return $vrSq;
    }
    
    /**
     * 수정 처리
     */
    private function handleModify(string $articleNumber, array $rawData, array $payload): int
    {
        CLI::write(CLI::color('🔵 V2 수정 시작', 'cyan'));
        
        // 기존 검증 요청 확인
        $existing = $this->vrfcReqModel->where('atcl_no', $articleNumber)->first();
        if (!$existing) {
            CLI::write(CLI::color("⚠️  수정할 기존 데이터가 없음 → 신규 등록으로 전환 (Atcl: $articleNumber)", 'yellow'));
            write_custom_log("MOD → REG 자동 전환 | Atcl: $articleNumber | 사유: 기존 데이터 없음", 'WARNING', 'service');
            return $this->handleRegister($articleNumber, $rawData, $payload);
        }   
        $vrSq = $existing['vr_sq'];
        $stat_cd = $existing['stat_cd'];
        
        // 파라미터 준비 (MOD 타입)
        $vrfcReqParam = $this->parameterMapper->mapVrfcReq($articleNumber, $rawData, $payload);
        $articleInfoParam = $this->parameterMapper->mapArticleInfo($articleNumber, $rawData, $payload);
        $articleInfoEtcParam = $this->parameterMapper->mapArticleInfoEtc($articleNumber, $rawData);
        $modifyInfoParam = $this->parameterMapper->mapModifyInfo($articleNumber, $rawData, $payload);

        $vrfcReqParam['stat_cd'] = '30';
        $vrfcReqParam['insert_tm'] = date('Y-m-d H:i:s');
        $vrfcReqParam['sync_yn'] = 'Y';
        
        // 데이터 업데이트
        if (!$this->vrfcReqModel->update($vrSq, $vrfcReqParam)) {
            throw new Exception("VrfcReq Update 실패");
        }

        // 기사 정보 저장
        $articleInfoParam['vr_sq'] = $vrSq;
        if (!$this->articleInfoModel->replace($articleInfoParam)) {
            throw new Exception("ArticleInfo Insert 실패: " . json_encode($this->db->error()));
        }
        CLI::write(CLI::color('✅ ArticleInfo 저장 성공', 'blue'));
        
        // 기사 정보 추가 저장
        $articleInfoEtcParam['vr_sq'] = $vrSq;
        if (!$this->articleInfoEtcModel->replace($articleInfoEtcParam)) {
            throw new Exception("ArticleInfoEtc Insert 실패: " . json_encode($this->db->error()));
        }
        CLI::write(CLI::color('✅ ArticleInfoEtc 저장 성공', 'blue'));

        // 수정 정보 입력 (있으면 update, 없으면 insert)
        if (!$this->modifyInfoModel->saveModifyInfo($vrSq, $modifyInfoParam)) {
            throw new Exception("ModifyInfo 저장 실패: " . json_encode($this->db->error()));
        }
        CLI::write(CLI::color('✅ ModifyInfo 저장 성공', 'blue'));
        
        // URL 이미지 저장 (v2_url_img_save 테이블)
        $files = $rawData['files'] ?? [];
        if (!empty($files)) {
            $fileExtracted = $this->parameterMapper->extractFilesByType($files);
            $this->saveUrlImagesToDb($fileExtracted, $articleNumber, $vrSq);
        }
        
        $this->statusService->recordStatusAndHistory($vrSq, '30', 'C9', "재접수 상태변경 : {$stat_cd} => 30");
        CLI::write(CLI::color('✅ VrfcReq 수정 성공', 'blue'));
        
        return $vrSq;
    }
    
    /**
     * 취소 처리
     */
    private function handleCancel(string $articleNumber, array $rawData, array $payload): int
    {
        CLI::write(CLI::color('🔵 V2 취소 시작', 'cyan'));
        
        // 기존 검증 요청 확인
        $existing = $this->vrfcReqModel->where('atcl_no', $articleNumber)->first();
        if (!$existing) {
            CLI::write(CLI::color("⚠️  취소할 데이터가 없음 → 무시 (Atcl: $articleNumber)", 'yellow'));
            write_custom_log("CNC 무시 | Atcl: $articleNumber | 사유: 기존 데이터 없음", 'WARNING', 'service');
            return 0; // 취소할 데이터가 없으므로 0 반환
        }
        
        $vrSq = $existing['vr_sq'];
        $stat_cd = $existing['stat_cd'];
        
        // 파라미터 준비 (MOD 타입)
        $vrfcReqParam = $this->parameterMapper->mapVrfcReq($articleNumber, $rawData, $payload);
        $vrfcReqParam['stat_cd'] = '19';
        $vrfcReqParam['insert_tm'] = date('Y-m-d H:i:s');
        $vrfcReqParam['req_type'] = 'D';
        
        // 상태를 취소로 업데이트
        if (!$this->vrfcReqModel->update($vrSq, $vrfcReqParam)) {
            throw new Exception("VrfcReq Cancel 실패");
        }

        $this->statusService->recordStatusAndHistory($vrSq, '19', 'C9', "재접수 상태변경 : {$stat_cd} => 19");
        CLI::write(CLI::color('✅ 취소 처리 완료', 'blue'));
                
        write_custom_log("V2 취소 성공 | Atcl: $articleNumber | VR_SQ: $vrSq", 'INFO', 'service');
        
        return $vrSq;
    }
    
    /**
     * 검증 요청 저장 또는 업데이트
     */
    private function insertOrUpdateVrfcReq(array $vrfcReqParam): int
    {
        $articleNumber = $vrfcReqParam['atcl_no'];
        $existing = $this->vrfcReqModel->where('atcl_no', $articleNumber)->first();
        
        if ($existing) {
            // 업데이트
            $vrSq = $existing['vr_sq'] ?? $existing['id'];
            CLI::write(CLI::color("🟡 기존 데이터 발견 (atcl_no: $articleNumber) -> 업데이트", 'yellow'));
            
            if (!$this->vrfcReqModel->update($vrSq, $vrfcReqParam)) {
                $this->logAndThrowError($vrfcReqParam, "VrfcReq Update 실패 :: $articleNumber");
            }
            CLI::write(CLI::color("✅ Update 성공 (vr_sq: $vrSq)", 'blue'));
            
            return $vrSq;
        } else {
            // 신규 등록
            if (!$this->vrfcReqModel->insert($vrfcReqParam)) {
                $this->logAndThrowError($vrfcReqParam, "VrfcReq Insert 실패 :: $articleNumber");
            }
            
            $vrSq = $this->vrfcReqModel->getInsertID();
            CLI::write(CLI::color("✅ Insert 성공 (vr_sq: $vrSq, atcl_no: $articleNumber)", 'blue'));
            
            return $vrSq;
        }
    }
    
    /**
     * 에러 로깅 및 예외 발생
     */
    private function logAndThrowError(array $data, string $message): void
    {
        $dbError = $this->db->error();
        CLI::write(CLI::color('❌ SQL ERROR', 'red', 'bold'));
        CLI::write(CLI::color('메시지: ', 'white') . $dbError['message']);
        CLI::write(CLI::color('쿼리: ', 'white') . (string)$this->vrfcReqModel->getLastQuery());
        
        throw new Exception($message . ": " . $dbError['message']);
    }
    
    /**
     * URL 이미지를 v2_url_img_save 테이블에 저장
     * 
     * @param array $fileExtracted extractFilesByType로 추출된 파일 배열
     * @param string $atclNo 기사번호
     * @param int $vrSq 검증요청ID
     */
    private function saveUrlImagesToDb(array $fileExtracted, string $atclNo, int $vrSq): void
    {
        $fileTypes = [
            'certRegister' => '2',      // 등기부등본
            'confirmDocImgUrl' => '2',  // 확인서이미지
            'referenceFileUrl' => '1'   // 홍보자료
        ];
        
        $saveCount = 0;
        
        foreach ($fileTypes as $key => $type) {
            if (!empty($fileExtracted[$key]) && is_array($fileExtracted[$key])) {
                foreach ($fileExtracted[$key] as $url) {
                    if (!empty($url)) {
                        $insertData = [
                            'url' => $url,
                            'type' => $type,
                            'atcl_no' => $atclNo,
                            'vr_sq' => $vrSq,
                            'status' => 'save',
                            'try_cnt' => 0
                        ];
                        
                        if ($this->urlImgSaveModel->insert($insertData)) {
                            $saveCount++;
                        } else {
                            CLI::write(CLI::color("⚠️  URL 저장 실패: $url", 'yellow'));
                        }
                    }
                }
            }
        }
        
        if ($saveCount > 0) {
            CLI::write(CLI::color("✅ URL 이미지 저장 완료: $saveCount개", 'blue'));
            write_custom_log("URL 이미지 저장 | Atcl: $atclNo | VR_SQ: $vrSq | Count: $saveCount", 'INFO', 'service');
        }
    }
}
