<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="dateUtil" uri="http://egovframework.go.kr/functions/date-util" %>

<!-- Main body -->
<div class="main_body">
    <section id="section8" class="main_bars">
        <div class="bgs-main">
            <section id="section5">
                <div class="sub_title"></div>
                <button type="button" id="registerBtn" class="newbtn bg1">PRN 등록</button>
                <button type="button" id="downloadBtn" class="newbtn bg3 iconz">
                    <span class="mdi mdi-file-document"></span>PRN 다운로드
                </button>
                <button type="button" id="excelDownloadBtn" class="newbtn bg3 iconz">
                    <span class="mdi mdi-microsoft-excel"></span>엑셀 다운로드
                </button>
            </section>
        </div>
    </section>
    <div class="contants_body">
        <div class="gs_b_top">
            <ul class="lef">
                <li class="th">접수일자</li>
                <li>
                    <input type="text" id="schRcptYmdStart" name="schRcptYmdStart" class="input calender datepicker" style="width: 120px;" autocomplete="off" value="${dateUtil:getCurrentDateAddDays('yyyy-MM-dd', -10)}"/> ~
                    <input type="text" id="schRcptYmdEnd" name="schRcptYmdEnd" class="input calender datepicker" style="width: 120px;" autocomplete="off" value="${dateUtil:getCurrentDateTime('yyyy-MM-dd')}"/>
                </li>
                <li class="th">검사일자</li>
                <li>
                    <input type="text" id="schInspYmdStart" name="schInspYmdStart" class="input calender datepicker" style="width: 120px;" autocomplete="off" value=""/> ~
                    <input type="text" id="schInspYmdEnd" name="schInspYmdEnd" class="input calender datepicker" style="width: 120px;" autocomplete="off" value=""/>
                </li>
                <li class="th">차량번호</li>
                <li>
                    <input type="text" id="schVhclno" name="schVhclno" class="input" style="width: 150px;" maxlength="30" autocomplete="off" placeholder="예: 12가3456"/>
                </li>
                <li class="th">소유자명</li>
                <li>
                    <input type="text" id="schOwnrNm" name="schOwnrNm" class="input" style="width: 150px;" maxlength="75" autocomplete="off"/>
                </li>
            </ul>
            <ul class="rig2">
                <li><button type="button" id="search_btn" class="newbtnss bg1">검색</button></li>
                <li><button type="button" id="reset_btn" class="newbtnss bg5" style="margin-left: 5px;">초기화</button></li>
            </ul>
            <ul class="lef2">
                <li class="th">처리상태</li>
                <li>
                    <c:forEach var="code" items="${taskPrcsSttsCdList}">
                        <label style="margin-right: 10px; cursor: pointer;">
                            <input type="checkbox" name="schTaskPrcsSttsCd" value="${code.cdId}" class="schTaskPrcsSttsCdCheckbox"/>
                            ${code.cdNm}
                        </label>
                    </c:forEach>
                </li>
                <li class="th">재검여부</li>
                <li>
                    <label style="margin-right: 10px; cursor: pointer;">
                        <input type="checkbox" name="schReinspYn" value="Y"/> 재검(Y)
                    </label>
                    <label style="margin-right: 10px; cursor: pointer;">
                        <input type="checkbox" name="schReinspYn" value="N"/> 미재검(N)
                    </label>
                </li>
            </ul>
        </div>
        <div class="gs_booking">
            <div class="row">
                <div class="col-sm-12">
                    <div class="box_column">
                        <ul class="box_title" style="display: flex; justify-content: space-between; align-items: center;">
                            <li class="tit">과태료 대상 목록</li>
                            <li class="rig">
                                <button type="button" id="callApiAllBtn" class="newbtn bg2-1">검색조건 전체 API 호출</button>
                                <button type="button" id="callApiBtn" class="newbtn bg2-1">선택 API 호출</button>
                                <button type="button" id="deleteBtn" class="newbtn bg6">선택 삭제</button>
                                <button type="button" id="btn_cancel" class="newbtn bg6">수정 취소</button>
                                <button type="button" id="btn_save" class="newbtn bg4">저장</button>

                                <span id="totalCount" class="total-count" style="padding-left: 25px;padding-right: 25px;">총 0건</span>
                            </li>
                        </ul>
                        <div class="containers">
                            <div id="grid"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<!-- /Main body -->

<!-- 비고 레이어 팝업 -->
<div id="rmrkLayerPopup" style="display: none; position: fixed; z-index: 10000; background: white; border: 2px solid #2196F3; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); min-width: 400px; max-width: 600px;">
    <div id="rmrkPopupHeader" style="background: #2196F3; color: white; padding: 12px 15px; cursor: move; border-radius: 6px 6px 0 0; display: flex; justify-content: space-between; align-items: center;">
        <span style="font-weight: bold;">비고 상세</span>
        <span id="rmrkPopupClose" onclick="closeRmrkPopup()" style="cursor: pointer; font-size: 20px; line-height: 1;">&times;</span>
    </div>
    <div style="padding: 20px; max-height: 400px; overflow-y: auto;">
        <pre id="rmrkPopupContent" style="white-space: pre-wrap; word-wrap: break-word; margin: 0; font-family: inherit; font-size: 14px; line-height: 1.6;"></pre>
    </div>
</div>

<script type="text/javascript">

    /**
     * 과태료 대상 목록 관리 모듈
     */
    (function(window, $) {
        'use strict';

        var SEARCH_COND = {};

        // 그리드 조회 시 사용된 마지막 검색조건 저장
        var LAST_GRID_SEARCH_COND = {};

        // 검색정보 설정
        var setSearchCond = function() {
            var schRcptYmdStart = $.trim(nvl($("#schRcptYmdStart").val(), ""));
            var schRcptYmdEnd = $.trim(nvl($("#schRcptYmdEnd").val(), ""));
            var schInspYmdStart = $.trim(nvl($("#schInspYmdStart").val(), ""));
            var schInspYmdEnd = $.trim(nvl($("#schInspYmdEnd").val(), ""));
            var schVhclno = $.trim(nvl($("#schVhclno").val(), ""));
            var schOwnrNm = $.trim(nvl($("#schOwnrNm").val(), ""));

            // 체크박스에서 선택된 값들을 배열로 수집
            var schTaskPrcsSttsCd = [];
            $("input[name='schTaskPrcsSttsCd']:checked").each(function() {
                schTaskPrcsSttsCd.push($(this).val());
            });

            var schReinspYn = [];
            $("input[name='schReinspYn']:checked").each(function() {
                schReinspYn.push($(this).val());
            });

            SEARCH_COND.schRcptYmdStart = schRcptYmdStart;
            SEARCH_COND.schRcptYmdEnd = schRcptYmdEnd;
            SEARCH_COND.schInspYmdStart = schInspYmdStart;
            SEARCH_COND.schInspYmdEnd = schInspYmdEnd;
            SEARCH_COND.schVhclno = schVhclno;
            SEARCH_COND.schOwnrNm = schOwnrNm;
            SEARCH_COND.schTaskPrcsSttsCd = schTaskPrcsSttsCd;
            SEARCH_COND.schReinspYn = schReinspYn;
        };

        // 다운로드 URL 생성 (현재 검색조건을 쿼리스트링으로 부여)
        var buildDownloadUrl = function() {
            setSearchCond();
            var baseUrl = '<c:url value="/carInspectionPenalty/registration/download.do"/>';
            var params = [];
            if (SEARCH_COND.schRcptYmdStart) params.push('schRcptYmdStart=' + encodeURIComponent(SEARCH_COND.schRcptYmdStart));
            if (SEARCH_COND.schRcptYmdEnd) params.push('schRcptYmdEnd=' + encodeURIComponent(SEARCH_COND.schRcptYmdEnd));
            if (SEARCH_COND.schInspYmdStart) params.push('schInspYmdStart=' + encodeURIComponent(SEARCH_COND.schInspYmdStart));
            if (SEARCH_COND.schInspYmdEnd) params.push('schInspYmdEnd=' + encodeURIComponent(SEARCH_COND.schInspYmdEnd));
            if (SEARCH_COND.schVhclno) params.push('schVhclno=' + encodeURIComponent(SEARCH_COND.schVhclno));
            if (SEARCH_COND.schOwnrNm) params.push('schOwnrNm=' + encodeURIComponent(SEARCH_COND.schOwnrNm));
            // 배열로 전달
            if (SEARCH_COND.schTaskPrcsSttsCd && SEARCH_COND.schTaskPrcsSttsCd.length > 0) {
                SEARCH_COND.schTaskPrcsSttsCd.forEach(function(val) {
                    params.push('schTaskPrcsSttsCd=' + encodeURIComponent(val));
                });
            }
            if (SEARCH_COND.schReinspYn && SEARCH_COND.schReinspYn.length > 0) {
                SEARCH_COND.schReinspYn.forEach(function(val) {
                    params.push('schReinspYn=' + encodeURIComponent(val));
                });
            }
            return baseUrl + (params.length ? ('?' + params.join('&')) : '');
        };

        // 검색조건 비교 및 확인
        var compareSearchConditions = function() {
            // 현재 폼의 검색조건 수집
            setSearchCond();

            // 그리드 조회 이력이 없는 경우
            if (!LAST_GRID_SEARCH_COND || Object.keys(LAST_GRID_SEARCH_COND).length === 0) {
                alert("먼저 검색 버튼을 눌러 그리드를 조회해주세요.");
                return false;
            }

            // 검색조건 레이블 매핑
            var fieldLabels = {
                schRcptYmdStart: '접수일자 시작',
                schRcptYmdEnd: '접수일자 종료',
                schInspYmdStart: '검사일자 시작',
                schInspYmdEnd: '검사일자 종료',
                schVhclno: '차량번호',
                schOwnrNm: '소유자명',
                schTaskPrcsSttsCd: '처리상태',
                schReinspYn: '재검여부'
            };

            // 날짜 포맷 변환 함수 (YYYYMMDD -> YYYY-MM-DD)
            var formatDate = function(dateStr) {
                if (!dateStr || dateStr.length !== 8) return dateStr;
                return dateStr.substring(0, 4) + '-' + dateStr.substring(4, 6) + '-' + dateStr.substring(6, 8);
            };

            // 처리상태 코드 -> 텍스트 변환
            var getTaskPrcsSttsCdText = function(codeArray) {
                if (!codeArray || codeArray.length === 0) return '전체';
                var textArray = [];
                codeArray.forEach(function(code) {
                    var $checkbox = $("input[name='schTaskPrcsSttsCd'][value='" + code + "']");
                    if ($checkbox.length > 0) {
                        textArray.push($checkbox.parent().text().trim());
                    } else {
                        textArray.push(code);
                    }
                });
                return textArray.join(', ');
            };

            // 재검여부 -> 텍스트 변환
            var getReinspYnText = function(codeArray) {
                if (!codeArray || codeArray.length === 0) return '전체';
                var textArray = [];
                codeArray.forEach(function(code) {
                    if (code === 'Y') {
                        textArray.push('재검(Y)');
                    } else if (code === 'N') {
                        textArray.push('미재검(N)');
                    } else {
                        textArray.push(code);
                    }
                });
                return textArray.join(', ');
            };

            // 값 포맷팅 함수
            var formatValue = function(field, value) {
                if (field.indexOf('Ymd') > -1) {
                    return value ? formatDate(value) : '(공백)';
                }
                if (field === 'schTaskPrcsSttsCd') {
                    return getTaskPrcsSttsCdText(value);
                }
                if (field === 'schReinspYn') {
                    return getReinspYnText(value);
                }
                if (!value || (Array.isArray(value) && value.length === 0)) {
                    return '(공백)';
                }
                return value;
            };

            // 달라진 조건 찾기
            var differences = [];
            var searchFields = ['schRcptYmdStart', 'schRcptYmdEnd', 'schInspYmdStart', 'schInspYmdEnd',
                               'schVhclno', 'schOwnrNm', 'schTaskPrcsSttsCd', 'schReinspYn'];

            searchFields.forEach(function(field) {
                var currentValue = SEARCH_COND[field];
                var lastValue = LAST_GRID_SEARCH_COND[field];

                // 배열 비교 (처리상태, 재검여부)
                if (field === 'schTaskPrcsSttsCd' || field === 'schReinspYn') {
                    currentValue = currentValue || [];
                    lastValue = lastValue || [];

                    // 배열을 정렬해서 비교
                    var currentStr = currentValue.slice().sort().join(',');
                    var lastStr = lastValue.slice().sort().join(',');

                    if (currentStr !== lastStr) {
                        differences.push({
                            field: field,
                            label: fieldLabels[field],
                            oldValue: lastValue,
                            newValue: currentValue
                        });
                    }
                } else {
                    currentValue = currentValue || '';
                    lastValue = lastValue || '';

                    if (currentValue !== lastValue) {
                        differences.push({
                            field: field,
                            label: fieldLabels[field],
                            oldValue: lastValue,
                            newValue: currentValue
                        });
                    }
                }
            });

            // 검색조건이 동일한 경우
            if (differences.length === 0) {
                return true;
            }

            // 달라진 조건 메시지 생성
            var message = "검색 조건이 그리드 조회 시와 다릅니다.\n\n[변경된 조건]\n";
            differences.forEach(function(diff) {
                message += "• " + diff.label + "\n";
                message += "  이전: " + formatValue(diff.field, diff.oldValue) + "\n";
                message += "  현재: " + formatValue(diff.field, diff.newValue) + "\n\n";
            });
            message += "현재 조건으로 계속 진행하시겠습니까?";

            // 사용자 확인
            return confirm(message);
        };

        /**
         * 과태료 대상 목록 관리 네임스페이스
         */
        var CarFfnlgTrgtList = {
            /**
             * 선택된 행 정보
             */
            selectedRow: null,

            /**
             * 그리드 관련 객체
             */
            grid: {
                /**
                 * 그리드 인스턴스
                 */
                instance: null,

                /**
                 * 그리드 설정 초기화
                 * @returns {Object} 그리드 설정 객체
                 */
                initConfig: function() {
                    // 데이터 소스 설정
                    var dataSource = this.createDataSource();

                    // 그리드 설정 객체 생성
                    var gridConfig = new XitTuiGridConfig();

                    // 기본 설정
                    gridConfig.setOptDataSource(dataSource);
                    gridConfig.setOptGridId('grid');
                    gridConfig.setOptGridHeight(470);
                    gridConfig.setOptRowHeight(30);
                    gridConfig.setOptRowHeaderType('checkbox');
                    gridConfig.setOptUseClientSort(false);

                    // 페이징 옵션 설정
                    //gridConfig.setOptPageOptions({
                    //    useClient: true
                    //});

                    gridConfig.setOptColumnOptions({					//컬럼고정 옵션
                            frozenCount: 7								//고정컬럼 갯수
                            , frozenBorderWidth: 2						//고정컬럼 보더(border) 두께
                            , resizable: true							//최소 사이즈
                    });
                    
                    gridConfig.setOptColumns(this.getGridColumns());

                    return gridConfig;
                },

                /**
                 * 그리드 컬럼 정의
                 * @returns {Array} 그리드 컬럼 배열
                 */
                getGridColumns: function() {
                    return [
                        {
                            header: '번호',
                            name: '_rowNum',
                            align: 'center',
                            width: 60,
                            sortable: false,
                            formatter: function(e) {
                                return e.row.rowKey+1;
                            }
                        },
                        { header: '접수일자', name: 'rcptYmd', align: 'center', width: 100,
                            formatter: function(e) {
                                //return e.value ? moment(e.value, 'YYYYMMDD').format('YYYY-MM-DD') : '';
                                return e.value;
                            }
                        },
                        { header: '검사소코드', name: 'inspstnCd', align: 'center', width: 100 },
                        { header: '검사일자', name: 'inspYmd', align: 'center', width: 100,
                            formatter: function(e) {
                                //return e.value ? moment(e.value, 'YYYYMMDD').format('YYYY-MM-DD') : '';
                                return e.value;
                            }
                        },
                        { header: '차량번호', name: 'vhclno', align: 'center', width: 100 },
                        { header: '소유자명', name: 'ownrNm', align: 'center', width: 100 },
                        { header: '주민등록번호', name: 'rrno', align: 'center', width: 130 },
                        { header: '자동차명', name: 'carNm', align: 'left', width: 150 },
                        { header: '자동차종류', name: 'carKnd', align: 'center', width: 100 },
                        { header: '자동차용도', name: 'carUsg', align: 'center', width: 100 },
                        { header: '검사종료일자', name: 'inspEndYmd', align: 'center', width: 100,
                            formatter: function(e) {
                                //return e.value ? moment(e.value, 'YYYYMMDD').format('YYYY-MM-DD') : '';
                                return e.value;
                            }
                        },
                        { header: '일수', name: 'daycnt', align: 'right', width: 60 },
                        { header: '재검여부', name: 'reinspYn', align: 'center', width: 80 },
                        { header: '과태료금액', name: 'ffnlgAmt', align: 'right', width: 100,
                            formatter: function(e) {
                                return e.value ? parseInt(e.value).toLocaleString() + '원' : '';
                            }
                        },
                        { header: '최종등록일자', name: 'lastRegYmd', align: 'center', width: 100,
                            formatter: function(e) {
                                //return e.value ? moment(e.value, 'YYYYMMDD').format('YYYY-MM-DD') : '';
                                return e.value;
                            }
                        },
                        { header: '주소', name: 'addr', align: 'left', width: 250 },
                        { header: '유효기간만료일자', name: 'vldPrdExpryYmd', align: 'center', width: 120,
                            formatter: function(e) {
                                //return e.value ? moment(e.value, 'YYYYMMDD').format('YYYY-MM-DD') : '';
                                return e.value;
                            }
                        },
                        { header: '매매상품', name: 'trdGds', align: 'center', width: 100 },
                        { header: '처리일자', name: 'taskPrcsYmd', align: 'center', width: 100,
                            formatter: function(e) {
                                //return e.value ? moment(e.value, 'YYYYMMDD').format('YYYY-MM-DD') : '';
                                return e.value;
                            }
                        },
                        {
                            header: '처리상태',
                            name: 'taskPrcsSttsCd',
                            align: 'center',
                            width: 100,
                            editor: {
                                type: 'select',
                                options: {
                                    listItems: [
                                        <c:forEach var="code" items="${taskPrcsSttsCdList}" varStatus="status">
                                        {text: '${code.cdNm}', value: '${code.cdId}'}<c:if test="${!status.last}">,</c:if>
                                        </c:forEach>
                                    ]
                                }
                            },
                            formatter: function(props) {
                                var value = props.value;
                                var codeList = [
                                    <c:forEach var="code" items="${taskPrcsSttsCdList}" varStatus="status">
                                    {id: '${code.cdId}', nm: '${code.cdNm}'}<c:if test="${!status.last}">,</c:if>
                                    </c:forEach>
                                ];
                                var code = codeList.find(function(c) { return c.id === value; });
                                return code ? code.nm : value;
                            }
                        },
                        {
                            header: '비고',
                            name: 'rmrk',
                            align: 'left',
                            width: 300,
                            editor: 'text',
                            formatter: function(e) {
                                var rmrk = e.value || '';
                                var displayText = rmrk.length > 30 ? rmrk.substring(0, 30) + '...' : rmrk;

                                if (rmrk && rmrk.trim()) {
                                    // 비고 값이 있으면 아이콘 + 텍스트 표시
                                    var escapedRmrk = rmrk.replace(/'/g, "\\'").replace(/\n/g, '\\n').replace(/\r/g, '');
                                    return '<span class="mdi mdi-note-text" style="color: #2196F3; cursor: pointer; margin-right: 5px;" onclick="showRmrkPopup(\'' + escapedRmrk + '\')"></span>' +
                                           '<span style="cursor: pointer;" onclick="showRmrkPopup(\'' + escapedRmrk + '\')">' + displayText + '</span>';
                                }
                                return displayText;
                            }
                        },
                        {
                            header: '비고 상세',
                            name: 'rmrkDtl',
                            align: 'left',
                            width: 200,
                            formatter: function(e) {
                                var rmrkDtl = e.value || '';
                                var displayText = rmrkDtl.length > 30 ? rmrkDtl.substring(0, 30) + '...' : rmrkDtl;

                                if (rmrkDtl && rmrkDtl.trim()) {
                                    var escapedRmrkDtl = rmrkDtl.replace(/'/g, "\\'").replace(/\n/g, '\\n').replace(/\r/g, '');
                                    return '<span class="mdi mdi-note-text" style="color: #4CAF50; cursor: pointer; margin-right: 5px;" onclick="showRmrkPopup(\'' + escapedRmrkDtl + '\')"></span>' +
                                           '<span style="cursor: pointer;" onclick="showRmrkPopup(\'' + escapedRmrkDtl + '\')">' + displayText + '</span>';
                                }
                                return displayText;
                            }
                        },
                        { header: '기본사항조회성명', name: 'carBscMttrInqFlnm', align: 'center', width: 100 },
                        { header: '기본사항조회시군구코드', name: 'carBscMttrInqSggCd', align: 'center', width: 100, hidden: true },
                        { header: '기본사항조회시군구명', name: 'carBscMttrInqSggNm', align: 'center', width: 120 },
                        { header: '등록원부변경업무코드', name: 'carRegFrmbkChgTaskSeCd', align: 'center', width: 100, hidden: true },
                        { header: '등록원부변경업무명', name: 'carRegFrmbkChgTaskSeNm', align: 'center', width: 120 },
                        { header: '등록원부변경일자', name: 'carRegFrmbkChgYmd', align: 'center', width: 120 },
                        { header: '등록원부상세', name: 'carRegFrmbkDtl', align: 'left', width: 250 },
                        {
                            header: '과태료대상ID',
                            name: 'carFfnlgTrgtId',
                            align: 'center',
                            width: 150,
                            formatter: function(e) {
                                if (e.value) {
                                    return '<a href="javascript:void(0)" onclick="openHistoryWithCarFfnlgTrgtId(\'' + e.value + '\')" style="color: #0066cc; text-decoration: underline; cursor: pointer;">' + e.value + '</a>';
                                }
                                return '';
                            }
                        },
                        {
                            header: '차량기본사항조회ID',
                            name: 'carBassMatterInqireId',
                            align: 'center',
                            width: 150,
                            formatter: function(e) {
                                if (e.value) {
                                    return '<a href="javascript:void(0)" onclick="openBasicPopup(\'' + e.value + '\')" style="color: #0066cc; text-decoration: underline; cursor: pointer;">' + e.value + '</a>';
                                }
                                return '';
                            },
                            hidden: true
                        },
                        {
                            header: '차량등록원부ID',
                            name: 'carLedgerFrmbkId',
                            align: 'center',
                            width: 150,
                            formatter: function(e) {
                                if (e.value) {
                                    return '<a href="javascript:void(0)" onclick="openLedgerPopup(\'' + e.value + '\')" style="color: #0066cc; text-decoration: underline; cursor: pointer;">' + e.value + '</a>';
                                }
                                return '';
                            },
                            hidden: true
                        },

                        { header: '등록일시', name: 'regDt', align: 'center', width: 150 },
                        { header: '등록자ID', name: 'rgtr', align: 'center', width: 100, hidden: true },
                        { header: '등록자', name: 'rgtrNm', align: 'center', width: 100 },
                        { header: '삭제일시', name: 'delDt', align: 'center', width: 150, hidden: true },
                        { header: '삭제자', name: 'dltr', align: 'center', width: 100, hidden: true }
                    ];
                },

                /**
                 * 데이터 소스 생성
                 * @returns {Object} 데이터 소스 설정 객체
                 */
                createDataSource: function() {
                    return {
                        api: {
                            readData: {
                                url: '<c:url value="/carInspectionPenalty/registration/list.ajax"/>',
                                method: 'POST',
                                contentType: 'application/x-www-form-urlencoded',
                                processData: true
                            }
                        },
                        initialRequest: false,
                        serializer: function(params) {
                            setSearchCond();
                            return $.param(SEARCH_COND);
                        }
                    };
                },

                /**
                 * 그리드 인스턴스 생성
                 */
                create: function() {
                    var gridConfig = this.initConfig();
                    var Grid = tui.Grid;
                    this.instance = gridConfig.instance(Grid);

                    // 그리드 테마 설정
                    Grid.applyTheme('striped');

                    this.gridBindEvents();
                },

                /**
                 * 그리드 이벤트 바인딩
                 */
                gridBindEvents: function() {
                    var self = this;
                    
                    // 데이터 로딩 완료 이벤트
                    this.instance.on('successResponse', function(ev) {
                        var responseObj = JSON.parse(ev.xhr.response);
                        if(responseObj){
                            if( responseObj.data && responseObj.data.contents ){
                                var totalCount = responseObj.data.contents.length;
                                $("#totalCount").text('총 ' + totalCount.toLocaleString() + '건');
                            }
                        }

                        // 선택된 행 초기화
                        CarFfnlgTrgtList.selectedRow = null;
                    });

                    // 행 선택 이벤트
                    this.instance.on('check', function(ev) {
                        var rowKey = ev.rowKey;
                        CarFfnlgTrgtList.selectedRow = self.instance.getRow(rowKey);
                    });

                    // 행 선택 해제 이벤트
                    this.instance.on('uncheck', function(ev) {
                        CarFfnlgTrgtList.selectedRow = null;
                    });
                },

                /**
                 * 그리드 새로고침
                 */
                reload: function() {
                    // 그리드 조회 전 현재 검색조건을 마지막 검색조건으로 저장
                    setSearchCond();
                    LAST_GRID_SEARCH_COND = Object.assign({}, SEARCH_COND);
                    this.instance.readData(1);
                },

                /**
                 * 그리드 변경사항 취소
                 */
                cancelChanges: function() {
                    var self = this;

                    // 변경된 데이터 확인
                    var modifiedRows = this.instance.getModifiedRows();

                    // 변경된 데이터가 없으면 알림
                    if (modifiedRows.createdRows.length === 0 &&
                        modifiedRows.updatedRows.length === 0 &&
                        modifiedRows.deletedRows.length === 0) {
                        alert('취소할 변경사항이 없습니다.');
                        return;
                    }

                    // 취소 확인
                    if (confirm('모든 변경사항을 취소하시겠습니까?')) {
                        // 그리드 데이터를 다시 로드하여 모든 변경사항 취소
                        this.instance.readData(1);
                    }
                },

                /**
                 * 그리드 변경사항 저장
                 */
                saveData: function() {
                    var self = this;

                    // 변경된 데이터 확인
                    var modifiedRows = this.instance.getModifiedRows();

                    // 변경된 데이터가 없으면 저장하지 않음
                    if (modifiedRows.createdRows.length === 0 &&
                        modifiedRows.updatedRows.length === 0 &&
                        modifiedRows.deletedRows.length === 0) {
                        alert('저장할 데이터가 없습니다.');
                        return;
                    }

                    console.log(modifiedRows);
                    var confirmMsg = "변경된 내용을 저장하시겠습니까?";
                    if (modifiedRows.deletedRows.length > 0) {
                        confirmMsg += "\n삭제 포함되어 있습니다."
                    }

                    // 저장 확인
                    if (confirm(confirmMsg)) {
                        $.ajax({
                            url: '<c:url value="/carInspectionPenalty/registration/saveAll.ajax"/>',
                            type: 'POST',
                            contentType: 'application/json',
                            data: JSON.stringify(modifiedRows),
                            success: function(response) {
                                if (response.result) {
                                    alert(response.message);
                                    self.instance.readData(1);
                                } else {
                                    alert(response.message);
                                }
                            },
                            error: function(xhr, status, error) {
                                console.error("저장 실패:", error);
                            }
                        });
                    }
                }
            },

            /**
             * 초기화
             */
            init: function() {
                this.grid.create();
                this.bindEvents();
                
                // 초기 데이터 로드
                this.grid.reload();
            },

            /**
             * 이벤트 바인딩
             */
            bindEvents: function() {
                var self = this;

                // 검색 버튼 클릭
                $("#search_btn").on('click', function() {
                    self.grid.reload();
                });

                // 초기화 버튼 클릭
                $("#reset_btn").on('click', function() {
                    $("#schRcptYmdStart").val("${dateUtil:getCurrentDateAddDays('yyyy-MM-dd', -10)}");
                    $("#schRcptYmdEnd").val("${dateUtil:getCurrentDateTime('yyyy-MM-dd')}");
                    $("#schInspYmdStart").val("");
                    $("#schInspYmdEnd").val("");
                    $("#schVhclno").val("");
                    $("#schOwnrNm").val("");
                    // 체크박스 모두 해제
                    $("input[name='schTaskPrcsSttsCd']").prop('checked', false);
                    $("input[name='schReinspYn']").prop('checked', false);
                    self.grid.reload();
                });

                // 등록 버튼 클릭 - 파일 업로드 팝업 열기
                $("#registerBtn").on('click', function() {
                    self.openUploadPopup();
                });

                // 삭제 버튼 클릭
                $("#deleteBtn").on('click', function() {
                    self.deleteData();
                });

                // API 호출 버튼 클릭 (그리드 선택)
                $("#callApiBtn").on('click', function() {
                    self.callApiAndCompare();
                });

                // API 호출 버튼 클릭 (검색조건 전체)
                $("#callApiAllBtn").on('click', function() {
                    self.callApiAndCompareAll();
                });

                // 목록 다운로드 버튼 클릭
                $("#downloadBtn").on('click', function() {
                    // 검색조건 비교 및 확인
                    if (!compareSearchConditions()) {
                        return;
                    }

                    var url = buildDownloadUrl();
                    // 파일 다운로드는 단순 이동으로 처리
                    window.location.href = url;
                });

                // 엑셀 다운로드 버튼 클릭
                $("#excelDownloadBtn").on('click', function() {
                    // 검색조건 비교 및 확인
                    if (!compareSearchConditions()) {
                        return;
                    }

                    // Form 생성 및 제출
                    var $form = $('<form>', {
                        method: 'POST',
                        action: '<c:url value="/carInspectionPenalty/registration/excel.do"/>'
                    });

                    // 검색 조건 파라미터 추가
                    setSearchCond();
                    $.each(SEARCH_COND, function(key, value) {
                        if (key === 'schTaskPrcsSttsCd' || key === 'schReinspYn') {
                            // 배열인 경우 각각 추가
                            if (value && value.length > 0) {
                                value.forEach(function(val) {
                                    $form.append($('<input>', {
                                        type: 'hidden',
                                        name: key,
                                        value: val
                                    }));
                                });
                            }
                        } else if (value) {
                            $form.append($('<input>', {
                                type: 'hidden',
                                name: key,
                                value: value
                            }));
                        }
                    });

                    // Form을 body에 추가하고 제출 후 제거
                    $form.appendTo('body').submit().remove();
                });

                // 페이지당 건수 변경
                $("#perPageSelect").on('change', function() {
                    var perPage = parseInt($(this).val(), 10);
                    self.grid.instance.setPerPage(perPage);
                    self.grid.reload();
                });

                // 검색 조건 입력 필드에서 Enter 키 처리
                $(".gs_b_top input").on('keypress', function(e) {
                    if (e.which === 13) {
                        self.grid.reload();
                    }
                });

                // 취소 버튼 클릭 이벤트
                $('#btn_cancel').on('click', function() {
                    self.grid.cancelChanges();
                });

                // 저장 버튼 클릭 이벤트
                $('#btn_save').on('click', function() {
                    self.grid.saveData();
                });
            },

            /**
             * 파일 업로드 팝업 열기
             */
            openUploadPopup: function() {
                var popupUrl = '<c:url value="/carInspectionPenalty/registration/uploadPopup.do"/>';
                var popup = openPopup(popupUrl, 800, 450, 'uploadPopup');

                // 팝업이 닫힐 때 그리드 새로고침
                var checkPopupClosed = setInterval(function() {
                    if (popup && popup.closed) {
                        clearInterval(checkPopupClosed);
                        CarFfnlgTrgtList.grid.reload();
                    }
                }, 500);
            },

            /**
             * 데이터 삭제
             */
            deleteData: function() {
                var checkedRows = this.grid.instance.getCheckedRows();

                if (checkedRows.length === 0) {
                    alert("삭제할 데이터를 선택해주세요.");
                    return;
                }

                if (!confirm(checkedRows.length + "건의 데이터를 삭제하시겠습니까?")) {
                    return;
                }

                // 삭제할 ID 목록 준비
                var deleteIds = checkedRows.map(function(row) {
                    return row.carFfnlgTrgtId;
                });

                // AJAX 호출
                $.ajax({
                    url: '<c:url value="/carInspectionPenalty/registration/deleteBatch.ajax"/>',
                    type: 'POST',
                    contentType: 'application/json',
                    data: JSON.stringify(deleteIds),
                    success: function(response) {
                        if (response.success) {
                            alert("삭제가 완료되었습니다.");
                            CarFfnlgTrgtList.grid.reload();
                        } else {
                            alert("삭제 중 오류가 발생했습니다: " + response.message);
                        }
                    },
                    error: function(xhr, status, error) {
                        console.error("삭제 실패:", error);
                    }
                });
            },

            /**
             * API 호출 및 데이터 비교 (그리드 선택)
             */
            callApiAndCompare: function() {
                var checkedRows = this.grid.instance.getCheckedRows();

                if (checkedRows.length === 0) {
                    alert("API 호출할 데이터를 선택해주세요.");
                    return;
                }

                // 접수상태(01)가 아닌 행이 있는지 확인
                var nonRcptRows = checkedRows.filter(function(row) {
                    return row.taskPrcsSttsCd !== '01';
                });

                if (nonRcptRows.length > 0) {
                    alert("접수 상태(01)인 데이터만 API 호출이 가능합니다.\n접수 상태가 아닌 데이터가 " + nonRcptRows.length + "건 포함되어 있습니다.");
                    return;
                }

                if (!confirm(checkedRows.length + "건의 데이터에 대해 API를 호출하고 비교하시겠습니까?")) {
                    return;
                }

                // 선택된 행 데이터 배열 준비
                var targetList = checkedRows.map(function(row) {
                    return {
                        carFfnlgTrgtId: row.carFfnlgTrgtId,
                        vhclno: row.vhclno,
                        inspYmd: row.inspYmd,
                        ownrNm: row.ownrNm,
                        carNm: row.carNm
                    };
                });

                // 로딩 메시지 표시 (선택사항)
                var loadingMsg = "API 호출 및 비교 중입니다...\n잠시만 기다려주세요.";
                console.log(loadingMsg);

                // AJAX 호출
                $.ajax({
                    url: '<c:url value="/carInspectionPenalty/registration/compareWithApi.ajax"/>',
                    type: 'POST',
                    contentType: 'application/json',
                    data: JSON.stringify(targetList),
                    success: function(response) {
                        if (response.success) {
                            alert("API 호출 및 비교가 완료되었습니다.\n\n" + response.message);

                            // 비교 결과 상세 보기 (콘솔 출력)
                            if (response.data && response.data.compareResults) {
                                console.log("비교 결과 상세:", response.data.compareResults);
                            }

                            // 그리드 새로고침
                            CarFfnlgTrgtList.grid.reload();
                        } else {
                            alert("오류: " + response.message);
                        }
                    },
                    error: function(xhr, status, error) {
                        console.error("API 호출 실패:", error);
                    }
                });
            },

            /**
             * API 호출 및 데이터 비교 (검색조건 전체, 페이징 없이)
             */
            callApiAndCompareAll: function() {
                // 검색조건 비교 및 확인
                if (!compareSearchConditions()) {
                    return;
                }

                if (!confirm("현재 검색조건의 전체 데이터에 대해 API를 호출하고 비교하시겠습니까?")) {
                    return;
                }

                // 검색 조건 설정
                setSearchCond();

                // 페이징 없이 전체 조회를 위한 파라미터, 백엔드에서 처리해되되나 params 값을 던지기위해 다시한번 처리
                var params = Object.assign({}, SEARCH_COND, {
                    pagingYn: 'N'  // 페이징 비활성화
                });

                // 로딩 메시지 표시
                console.log("전체 데이터 API 호출 및 비교 중입니다...\n잠시만 기다려주세요.");

                // AJAX 호출
                $.ajax({
                    url: '<c:url value="/carInspectionPenalty/registration/compareWithApiAll.ajax"/>',
                    type: 'POST',
                    contentType: 'application/json',
                    data: JSON.stringify(params),
                    success: function(response) {
                        if (response.success) {
                            alert("API 호출 및 비교가 완료되었습니다.\n\n" + response.message);

                            // 비교 결과 상세 보기 (콘솔 출력)
                            if (response.data && response.data.compareResults) {
                                console.log("비교 결과 상세:", response.data.compareResults);
                            }

                            // 그리드 새로고침
                            CarFfnlgTrgtList.grid.reload();
                        } else {
                            alert("오류: " + response.message);
                        }
                    },
                    error: function(xhr, status, error) {
                        console.error("API 호출 실패:", error);
                    }
                });
            }
        };

        // 페이지 로드 시 초기화
        $(document).ready(function() {
            CarFfnlgTrgtList.init();
        });

    })(window, jQuery);

    /**
     * 차량 기본정보 팝업 열기 (전역 함수)
     */
    function openBasicPopup(carBassMatterInqireId) {
        console.log(carBassMatterInqireId);
        var popupUrl = '<c:url value="/carInspectionPenalty/history/carBassMatterInqire/popup.do"/>?carBassMatterInqireId='+encodeURIComponent(carBassMatterInqireId);
        var popup = openPopup(popupUrl, 1200, 900, 'carBassMatterInqirePopup');
    }

    /**
     * 차량 등록원부 팝업 열기 (전역 함수)
     */
    function openLedgerPopup(carLedgerFrmbkId) {
        console.log(carLedgerFrmbkId);
        var popupUrl = '<c:url value="/carInspectionPenalty/history/carLedgerFrmbk/popup.do"/>?carLedgerFrmbkId='+encodeURIComponent(carLedgerFrmbkId);
        var popup = openPopup(popupUrl, 1200, 900, 'carLedgerFrmbkPopup');
    }

    /**
     * 과태료대상ID로 조회이력 페이지 열기 (전역 함수)
     */
    function openHistoryWithCarFfnlgTrgtId(carFfnlgTrgtId) {
        console.log('Opening history with carFfnlgTrgtId:', carFfnlgTrgtId);
        var url = '<c:url value="/carInspectionPenalty/history/list.do"/>?searchCarFfnlgTrgtId=' + encodeURIComponent(carFfnlgTrgtId);
        window.open(url, '_blank');
    }

    /**
     * 비고 레이어 팝업 열기 (전역 함수)
     */
    function showRmrkPopup(rmrkText) {
        var $popup = $('#rmrkLayerPopup');
        var $content = $('#rmrkPopupContent');

        // 이스케이프된 문자 복원
        rmrkText = rmrkText.replace(/\\n/g, '\n').replace(/\\'/g, "'");

        // 내용 설정
        $content.text(rmrkText);

        // 팝업 표시 (화면 중앙) - transform 대신 계산된 위치 사용
        $popup.css({
            display: 'block',
            transform: 'none'
        });

        // 중앙 위치 계산
        var windowWidth = $(window).width();
        var windowHeight = $(window).height();
        var popupWidth = $popup.outerWidth();
        var popupHeight = $popup.outerHeight();

        $popup.css({
            left: (windowWidth - popupWidth) / 2 + 'px',
            top: (windowHeight - popupHeight) / 2 + 'px'
        });

        // 드래그 기능 초기화
        initRmrkPopupDrag();
    }

    /**
     * 비고 레이어 팝업 닫기 (전역 함수)
     */
    function closeRmrkPopup() {
        $('#rmrkLayerPopup').hide();
    }

    /**
     * 비고 레이어 팝업 드래그 기능 초기화
     */
    var rmrkPopupDragInitialized = false;
    function initRmrkPopupDrag() {
        if (rmrkPopupDragInitialized) {
            return;
        }

        var $popup = $('#rmrkLayerPopup');
        var $header = $('#rmrkPopupHeader');
        var $closeBtn = $('#rmrkPopupClose');
        var isDragging = false;
        var dragOffset = { x: 0, y: 0 };

        $header.on('mousedown', function(e) {
            // 닫기 버튼 클릭 시 드래그 시작하지 않음
            if ($(e.target).is($closeBtn) || $(e.target).closest('#rmrkPopupClose').length > 0) {
                return;
            }

            isDragging = true;
            var popupOffset = $popup.offset();
            dragOffset.x = e.pageX - popupOffset.left;
            dragOffset.y = e.pageY - popupOffset.top;
            e.preventDefault(); // 텍스트 선택 방지
        });

        $(document).on('mousemove', function(e) {
            if (isDragging) {
                $popup.css({
                    left: e.pageX - dragOffset.x + 'px',
                    top: e.pageY - dragOffset.y + 'px'
                });
            }
        });

        $(document).on('mouseup', function() {
            isDragging = false;
        });

        rmrkPopupDragInitialized = true;
    }

    // 팝업 외부 클릭 시 닫기 (선택사항)
    $(document).on('click', function(e) {
        var $popup = $('#rmrkLayerPopup');
        if ($popup.is(':visible') && !$(e.target).closest('#rmrkLayerPopup, .mdi-note-text').length) {
            closeRmrkPopup();
        }
    });

</script>
