<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!-- 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="btn_add_row" class="newbtn bg1">행 추가</button>
                <button type="button" id="btn_delete" class="newbtn bg2">삭제</button>
                <button type="button" id="btn_cancel" class="newbtn bg1">취소</button>
                <button type="button" id="btn_save" class="newbtn bg4">저장</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="searchKeyword" name="searchKeyword" class="input"/></li>
                <li class="th">사용여부</li>
                <li>
                    <select id="searchUseYn" name="searchUseYn" class="input">
                        <option value="">전체</option>
                        <option value="Y">사용</option>
                        <option value="N">미사용</option>
                    </select>
                </li>
                <li>
                    <button type="button" id="search_btn" class="newbtnss bg1">검색</button>
                </li>
            </ul>
            <ul class="rig2">
                <li>
                    <select id="perPageSelect" class="input">
                        <option value="10">페이지당 10</option>
                        <option value="20">페이지당 20</option>
                        <option value="30">페이지당 30</option>
                    </select>
                    <span class="page_number"><span id="currentPage"></span><span class="bar">/</span><sapn id="totalPages"></sapn> Pages</span>
                </li>
            </ul>
        </div>
        <div class="gs_booking">
            <div class="row">
                <div class="col-sm-12">
                    <div class="box_column">
                        <div class="containers">
                            <div id="grid"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<!-- /Main body -->

<script type="text/javascript">
/**
 * 역할 목록 관리 모듈
 * 역할 목록을 조회하고 관리하는 기능을 제공합니다.
 */
(function(window, $) {
    'use strict';

    var SEARCH_COND = {};

    // 검색정보 셋팅
    var setSearchCond = function() {
        var searchKeyword = $.trim(nvl($("#searchKeyword").val(), ""));
        var searchUseYn = $.trim(nvl($("#searchUseYn").val(), ""));

        SEARCH_COND.searchKeyword = searchKeyword;
        SEARCH_COND.searchUseYn = searchUseYn;
    };

    /**
     * 역할 목록 관리 네임스페이스
     */
    var RoleList = {
        /**
         * 그리드 관련 객체
         */
        grid: {
            /**
             * 그리드 인스턴스
             */
            instance: null,

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

                // 현재 선택된 perPage 값 가져오기
                var perPage = parseInt($('#perPageSelect').val() || 10, 10);

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

                // 기본 설정
                gridConfig.setOptDataSource(dataSource);            // 데이터소스 연결
                gridConfig.setOptGridId('grid');                    // 그리드를 출력할 Element ID
                gridConfig.setOptGridHeight(390);                   // 그리드 높이(단위: px)
                gridConfig.setOptRowHeight(30);                     // 그리드 행 높이(단위: px)
                gridConfig.setOptRowHeaderType('checkbox');         // 행 첫번째 셀 타입(rowNum: 순번, checkbox: 체크박스, '': 출력 안함)

                // 페이징 옵션 설정
                gridConfig.setOptPageOptions({
                    useClient: false,                               // 클라이언트 페이징 여부(false: 서버 페이징)
                    perPage: perPage                                // 페이지당 표시 건수
                });
                gridConfig.setOptUseClientSort(false);              // 서버사이드 정렬 false

                gridConfig.setOptColumns(this.getGridColumns());

                return gridConfig;
            },

            getGridColumns: function() {
                return [
                            {
                                header: '역할 ID',
                                name: 'roleId',
                                width: 250,
                                sortable: true,
                                align: 'left',
                                editor: 'text'
                            },
                        {
                            header: '역할명',
                                name: 'roleNm',
                            width: 250,
                            sortable: true,
                            align: 'left',
                            editor: 'text'
                        },
                        {
                            header: '역할 설명',
                                name: 'roleDc',
                            sortable: false,
                            align: 'left',
                            editor: 'text'
                        },
                        {
                            header: '정렬 순서',
                                name: 'sortOrdr',
                            width: 120,
                            sortable: true,
                            align: 'center',
                            editor: {
                            type: 'text',
                                options: {
                                maxLength: 3
                            }
                        }
                        },
                        {
                            header: '사용여부',
                                name: 'useYn',
                            width: 120,
                            align: 'center',
                            editor: {
                            type: 'select',
                                options: {
                                listItems: [
                                    {text: '사용', value: 'Y'},
                                    {text: '미사용', value: 'N'}
                                    ]
                                }
                            },
                            formatter: function(props) {
                                return props.value === 'Y' ? '사용' : '미사용';
                            }
                        },
                        {
                            header: '등록일시',
                                name: 'regDttm',
                            width: 150,
                            align: 'center'
                        },
                        {
                            header: '등록자',
                                name: 'rgtr',
                            width: 150,
                            align: 'center'
                        }
                    ];
            },


            /**
             * 데이터 소스 생성
             * @returns {Object} 데이터 소스 객체
             */
            createDataSource: function() {
                return {
                    api: {
                        readData: {
                            url: '<c:url value="/system/role/list.ajax"/>',
                            method: 'POST',
                            contentType: 'application/x-www-form-urlencoded',
                            processData: true
                        }
                    },
                    initialRequest: true,                           // 초기 데이터 요청 여부
                    serializer: function(params) {
                        // 기본 파라미터 (페이지 정보 등)
                        var defaultParams = $.param(params);
                        // 검색 폼 데이터, 목록, 엑셀 다운로드
                        setSearchCond();
                        var searchParams = $.param(SEARCH_COND);
                        // 모든 파라미터 조합
                        return defaultParams + '&' + searchParams;
                    }
                };
            },

            /**
             * 새 행 추가
             */
            addRow: function() {
                // 새 행 추가
                this.instance.appendRow({
                    roleId: 'ROLE_',       // 빈 값으로 시작
                    roleNm: '',
                    roleDc: '',
                    sortOrdr: '0',    // 기본값 설정
                    useYn: 'Y',       // 기본값 설정
                    regDttm: null,
                    rgtr: '신규 등록자'
                }, {
                    focus: true       // 새 행에 포커스 설정
                });
                // 첫 번째 셀(roleId)로 에디터 포커스 이동
                var rowKey = this.instance.getRowCount() - 1;
                this.instance.startEditing(rowKey, 'roleId');
            },

            /**
             * 그리드 변경사항 취소
             */
            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('모든 변경사항을 취소하시겠습니까?')) {
                    // 현재 페이지 저장
                    var currentPage = this.instance.getPagination().getCurrentPage();

                    // 그리드 데이터를 다시 로드하여 모든 변경사항 취소
                    this.instance.readData(currentPage);

                    //alert('변경사항이 취소되었습니다.');
                }
            },

            /**
             * 그리드 변경사항 저장
             */
            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;
                }

                // RoleVO 기반 유효성 검증
                var validationResult = this.validateRoleData(modifiedRows);
                if (!validationResult.isValid) {
                    alert(validationResult.message);
                    return;
                }

                var confirmMsg = "변경된 내용을 저장하시겠습니까?";
                if( modifiedRows.deletedRows.length > 0 ){
                    confirmMsg += "\n삭제 Role 포함되어 있습니다."
                }
                // 저장 확인
                if (confirm(confirmMsg)) {
                    $.ajax({
                        url: '<c:url value="/system/role/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);
                            }
                        }
                    });
                }
            },

            /**
             * RoleVO 기반 유효성 검증
             * @param {Object} modifiedRows 변경된 행 데이터
             * @returns {Object} 검증 결과 객체 {isValid: boolean, message: string}
             */
            validateRoleData: function(modifiedRows) {
                var self = this;

                var result = {
                    isValid: true,
                    message: ''
                };

                // 정규식 패턴 정의
                var patterns = {
                    // roleId: 영문, 숫자, 언더스코어만 허용, 'ROLE_'로 시작
                    roleId: /^ROLE_[A-Za-z0-9_]*$/,
                    // roleNm: 한글, 영문, 숫자, 일부 특수문자 허용
                    roleNm: /^[가-힣A-Za-z0-9\s\(\)\[\]\-\_\.\,]*$/,
                    // roleDc: 한글, 영문, 숫자, 일부 특수문자 허용
                    roleDc: /^[가-힣A-Za-z0-9\s\(\)\[\]\-\_\.\,\;\:\!]*$/,
                    // sortOrdr: 숫자만 허용
                    sortOrdr: /^\d+$/,
                    // useYn: 'Y' 또는 'N'만 허용
                    useYn: /^[YN]$/
                };

                // 최대 길이 제한
                var maxLengths = {
                    roleId: 20,
                    roleNm: 100,
                    roleDc: 200,
                    sortOrdr: 3
                };

                // 필수 입력 필드
                var requiredFields = ['roleId', 'roleNm', 'useYn'];
                var validatRows = [].concat(modifiedRows.createdRows || [], modifiedRows.updatedRows || []);
                // 생성된 행 검증
                for (var i = 0; i < validatRows.length; i++) {
                    var row = validatRows[i];
                    // 필수 입력 검증
                    for (var j = 0; j < requiredFields.length; j++) {
                        var field = requiredFields[j];
                        if (!row[field]) {
                            result.isValid = false;
                            result.message = self.getGridColumns().find(col => col.name === field).header + '은(는) 필수 입력 항목입니다.';
                            return result;
                        }
                    }

                    // 최대 길이 검증
                    for (var field in maxLengths) {
                        if (row[field] && row[field].toString().length > maxLengths[field]) {
                            result.isValid = false;
                            result.message = self.getGridColumns().find(col => col.name === field).header + '은(는) 최대 ' + maxLengths[field] + '자까지 입력 가능합니다.';
                            return result;
                        }
                    }

                    // 패턴 검증
                    for (var field in patterns) {
                        if (row[field] && !patterns[field].test(row[field])) {
                            var errorMsg = '';
                            switch (field) {
                                case 'roleId':
                                    errorMsg = '역할 ID는 \'ROLE_\'로 시작하고 영문, 숫자, 언더스코어(_)만 사용 가능합니다.';
                                    break;
                                case 'roleNm':
                                    errorMsg = '역할명은 한글, 영문, 숫자, 일부 특수문자만 사용 가능합니다.';
                                    break;
                                case 'roleDc':
                                    errorMsg = '역할 설명은 한글, 영문, 숫자, 일부 특수문자만 사용 가능합니다.';
                                    break;
                                case 'sortOrdr':
                                    errorMsg = '정렬 순서는 숫자만 입력 가능합니다.';
                                    break;
                                case 'useYn':
                                    errorMsg = '사용 여부는 Y 또는 N만 입력 가능합니다.';
                                    break;
                            }
                            result.isValid = false;
                            result.message = errorMsg;
                            return result;
                        }
                    }
                }

                return result;
            },


            /**
             * 그리드 인스턴스 생성
             */
            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);
                    $("#currentPage").text(responseObj.data.pagination.page);
                    $("#totalPages").text(responseObj.data.pagination.totalPages);
                });

                // 셀 편집 시작 전 이벤트
                this.instance.on('editingStart', function(ev) {
                    var { rowKey, columnName } = ev;
                    // 행 데이터 가져오기
                    var rowData = self.instance.getRow(rowKey);
                    // 기존 행인지 확인 (regDt가 있으면 기존 행)
                    console.log(rowData.roleId.indexOf("ROLE_"));
                    if (columnName === "roleId" && rowData.regDttm) {
                        // 기존 행의 roleId는 편집 불가
                        alert('기존 역할의 ID는 수정할 수 없습니다.');
                        ev.stop(); // 편집 취소
                    }
                    // 신규 행은 roleId 편집 가능 (별도 처리 필요 없음)
                });

                // 셀 편집 시작 전 이벤트
                this.instance.on('editingFinish', function(ev) {
                    var { rowKey, columnName } = ev;
                    // 행 데이터 가져오기
                    var rowData = self.instance.getRow(rowKey);
                    // 기존 행인지 확인 (regDt가 있으면 기존 행)
                    if(columnName === "roleId" && rowData.roleId.indexOf("ROLE_") !== 0){
                        alert('역할 ID 값은 \'ROLE_\' 로 시작해야 합니다.');
                        // roleId 값을 'ROLE_'로 시작하도록 복원
                        self.instance.setValue(rowKey, 'roleId', 'ROLE_' + (rowData.roleId || ''));
                    }
                });

            }
        },

        /**
         * 이벤트 핸들러 설정
         */
        eventBindEvents: function() {
            var self = this;

            // 검색 버튼 클릭 이벤트
            $('#search_btn').on('click', function() {
                // 페이지를 1로 리셋
                $("#page").val(1);
                // 그리드 데이터 리로드
                self.grid.instance.readData(1);
            });

            // 검색어 입력 필드에서 엔터키 이벤트 처리
            $('#searchKeyword').on('keypress', function(e) {
                if (e.which === 13) { // 엔터키 코드는 13
                    e.preventDefault(); // 기본 이벤트 방지
                    $('#search_btn').trigger('click'); // 검색 버튼 클릭 이벤트 트리거
                }
            });

            // perPage 변경 이벤트 추가
            $('#perPageSelect').on('change', function() {
                var perPage = parseInt($(this).val(), 10);
                // Grid의 perPage 설정 변경 및 데이터 리로드
                self.grid.instance.setPerPage(perPage);
            });

            // 행 추가 버튼 클릭 이벤트
            $('#btn_add_row').on('click', function() {
                self.grid.addRow();
            });

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

            // 삭제 버튼 클릭 이벤트
            $('#btn_delete').on('click', function() {
                var checkedRows = self.grid.instance.getCheckedRows();
                if (checkedRows.length === 0) {
                    alert('삭제할 역할을 선택해주세요.');
                    return;
                }

                // 선택된 행의 rowKey 배열 생성
                var rowKeys = checkedRows.map(function(row) {
                    return row.rowKey;
                });

                // 그리드에서 선택된 행 제거
                //self.grid.instance.removeRows(rowKeys); // 해당버전 지원안됨....
                // 여러 행 삭제 (rowKey 배열을 이용)
                rowKeys.forEach(function(rowKey) {
                    self.grid.instance.removeRow(rowKey);
                });

                // 삭제 완료 메시지 표시
                alert('[저장] 후 실제 삭제가 진행됩니다.');

            });

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

        /**
         * 모듈 초기화
         */
        init: function() {
            // 그리드 생성
            this.grid.create();

            // 이벤트 핸들러 설정
            this.eventBindEvents();
        }
    };

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

    // 전역 네임스페이스에 모듈 노출
    window.RoleList = RoleList;

})(window, jQuery);
</script>
