import React, { useState, useEffect, useCallback } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import SbItem from './SbItem'
import Loading from '../../components/Loading'
import BookmarkModal from './BookmarkModal';
import {SbContainer} from './Sb.style'
import {VwDiv, VwPtag} from './Vw.style'
import Form from 'react-bootstrap/Form'
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Modal from 'react-bootstrap/Modal';
import * as EgovNet from 'api/egovFetch';
import {getLocalItem} from "../../utils/storage";
import CODE from "../../constants/code";
import {parseJwt} from "../../utils/parseJwt";

function CodeViewer(props) {
    const [treeLoading, setTreeLoading] = useState(true);
    const [docLoading, setDocLoading] = useState(true);
    const {linkedDocCode} = useParams();
    const [docCode, setDocCode] = useState(linkedDocCode !== undefined?linkedDocCode.split(':')[0]:props.docCode);
    const [ymd, setYmd] = useState(linkedDocCode !== undefined?linkedDocCode.split(':')[1]:props.ymd);
    const [docInfo, setDocInfo] = useState();
    const [codeTree, setCodeTree] = useState();
    const [docSummary, setDocSummary] = useState();
    const [docDetail, setDocDetail] = useState();
    const [errorSelector, setErrorSelector] = useState();

    const [show, setShow] = useState(false);
    const [bookMarkModal, setBookMarkModal] = useState();


    const sessionUser = parseJwt(getLocalItem('accessToken'));
    const sessionUserSe = sessionUser?.userSe;

    const handleClose = () => setShow(false);
    const handleShow = () => setShow(true);

    console.group("viewer");
    console.log("[Start] viewer ------------------------------");
    console.log("viewer [props] : ", props);
    const location = useLocation();
    console.log("viewer [location] : ", location);
    console.log("viewer [docCode] : ", docCode);

    const updateDocCode = (docCode)=>{
        setDocSummary([<div></div>])
        setDocDetail([<div>불러오는중</div>])
        setDocInfo([])
        setDocCode(docCode);
        getCodeInfo(docCode);
        getCodeDetailInfo(docCode);
    }

    const getCodeTree = ()=>{
        EgovNet.requestFetch(
            '/standardCode/getCodeTree.do',
            {
                method: "POST",
                headers: {
                    'Content-type': 'application/json'
                },
                body: JSON.stringify({})
            },
            (resp) => {
                const menuData = resp.result.codeTree;
                // 코드 목록 트리 구성
                // https://garve32.tistory.com/52 참고
                const nest = (menuData, parent_seq = null, link = 'parent_seq') =>
                    menuData.filter(item => item[link] === parent_seq)
                        .map(item => ({ ...item, childrens: nest(menuData, item.seq) }));
                const tree = nest(menuData);
                let treeTag = [];
                if(tree.length>0){
                    treeTag.push(
                        <SbContainer>
                            {tree.map((subItem) =>
                                <SbItem item={subItem} openDocCode={docCode} updateDocCode={updateDocCode} />
                            )}
                        </SbContainer>
                    )
                }else{
                    treeTag.push(<div>검색된 결과가 없습니다.</div>); // 코드 목록 초기값
                }
                setCodeTree(treeTag);
                setTreeLoading(false);
            },
            function (resp) {
                console.log("err response : ", resp);
            }
        );
    }

    const getCodeInfo = useCallback((docCode) => {
        console.groupCollapsed("EgovMain.getCodeInfo()");
        EgovNet.requestFetch(
            '/standardCode/getCodeInfo.do',
            {
                method: "POST",
                headers: {
                    'Content-type': 'application/json'
                },
                body: JSON.stringify({
                    docCode: docCode
                })
            },
            (resp) => {
                const docInfo = resp.result.docInfo;
                // 헤더 연도 선택지 구성
                let headTag = [];
                if(docInfo.length>0){
                    let optionTag = [];
                    let activeIndex = 0;
                    let docTitle = "";
                    if(ymd===undefined){
                        activeIndex = docInfo.length-1
                        docTitle = docInfo[docInfo.length-1].doc_nm
                    }else{
                        docInfo.forEach(function (item, index){
                            if(new Date(item.rvsn_ymd) <= new Date(ymd)){
                                activeIndex = index;
                                docTitle = item.doc_nm
                            }
                        })
                    }
                    docInfo.forEach(function (item, index){
                        let buttonClass = "btn btn-sm docInfoBtn "
                        let pClass = "yearInfo ";
                        if(item.doc_er === 'E'){
                            buttonClass += "btn-success "
                        }else{
                            buttonClass += "btn-primary "
                        }
                        if(index === activeIndex){
                            buttonClass += "docInfoActive"
                            pClass += "yearInfoActive"
                        }
                        optionTag.push(
                            <Col>
                                <input type="button"
                                       className={buttonClass}
                                       value={item.doc_er==='E'?'제':'개'}
                                       onClick={docInfoSelectorChange}
                                       data-ymd={item.rvsn_ymd}
                                       data-doccode={item.kcsc_cd}
                                       data-docinfoseq={item.doc_info_seq}/>
                                <br/>
                                <p className={pClass}>{item.doc_yr}</p>
                            </Col>)
                    })
                    headTag.push(<Row className="docInfoRow"><Col className="docInfoTitle">{docCode} {docTitle}</Col>{optionTag}</Row>)
                }else{
                    headTag.push(<div>검색된 결과가 없습니다.</div>); // 코드 목록 초기값
                }
                setDocInfo(headTag);
            }
        )
    })

    const getCodeDetailInfo = useCallback((docCode, ymd) => {
        setErrorSelector([]);
        console.groupCollapsed("EgovMain.getCodeDetailInfo()");
        EgovNet.requestFetch(
            '/standardCode/getCodeDetailInfo.do',
            {
                method: "POST",
                headers: {
                    'Content-type': 'application/json'
                },
                body: JSON.stringify({
                    docCode: docCode,
                    ymd: ymd
                })
            },
            (resp) => {
                // 목차 구성
                let summaryTag = [];
                // 문서 전문 구성
                let detailTag = [];
                // 문서 오류 선택 구성
                let errorTag = [];
                let optionTag = [];
                //const activeYmd = document.querySelector(".docInfoActive").dataset.ymd;
                if(resp.result.document.length>0){
                    const docLinkReg = /([A-Z]{3,5}(\s[0-9]{2}){3,4})/g
                    const docPartReg = /\((?:표|그림|부록)?\s*([A-Z]\.)?(?!\d\))\d+(\.\d+)*(\s?\(\d\))?(-\d+)?(?:\s*[A-Z])?\)/g // /(\((?:표|그림|부록)?\s*([A-Z]\.)?\d+(\.\d+)*(\s?\(\d\))?(-\d+)?(?:\s*[A-Z])?\))/g
                    let parentContCd = "";
                    let lastLevel = 0;
                    resp.result.document.forEach(function (item, index){
                        const isTitle = item.full_content.includes(item.group_title);
                        if(isTitle){
                            summaryTag.push(
                                <VwDiv depth={item.cont_level} isTitle={isTitle}>
                                    <VwPtag href="#" isTitle={isTitle} onClick={() => {
                                        document.location.hash="#"+item.cont_type_cd;
                                    }} dangerouslySetInnerHTML={ {__html: item.group_title} }>
                                    </VwPtag>
                                </VwDiv>
                            )
                            if(lastLevel < item.cont_level){
                                parentContCd = parentContCd+" "+item.cont_type_cd;
                            }else{
                                const contCdAry = parentContCd.split(" ");
                                parentContCd = "";
                                contCdAry.forEach(function (contCd, index){
                                    if(index+1<item.cont_level){
                                        parentContCd = parentContCd+" "+contCd
                                    }
                                })
                                parentContCd = parentContCd+" "+item.cont_type_cd;
                            }
                            lastLevel = item.cont_level;
                            parentContCd = parentContCd.trim();
                            item.full_content = "<input type='checkbox' " +
                                "class='titleCheckBox "+parentContCd+"' " +
                                "id='"+item.cont_type_cd+"chk' " +
                                ">"+item.full_content;
                            if(index!==0 && item.cont_level===1 && item.cont_order !== 1){
                                item.full_content = "<br>"+item.full_content;
                            }
                        }
                        if(!item.full_content.includes("<table")){
                            if(docLinkReg.test(item.full_content)){
                                const docCodeAry = item.full_content.match(docLinkReg);
                                const docCodeMap = new Map();
                                for(let i=0; i<docCodeAry.length; i++) {
                                    const docCode = docCodeAry[i];
                                    //docCodeMap.set(docCode, '<a class="docLink" href="/standardCode/viewer/' + docCode + '" target="_blank">' + docCode + '</a>')
                                    docCodeMap.set(docCode, '<a class="docLink" href="#" data-doccode="'+docCode+'">' + docCode + '</a>')
                                }
                                docCodeMap.forEach((docCodeLink, docCode)=>{
                                    item.full_content = item.full_content.replaceAll(docCode, docCodeLink);
                                })
                                if(docPartReg.test(item.full_content)){
                                    const docPartAry = item.full_content.match(docPartReg);
                                    const docPartMap = new Map();
                                    for(let i=0; i<docPartAry.length; i++) {
                                        const docPart = docPartAry[i];
                                        const docCodeMatch = item.full_content.substring(item.full_content.indexOf(docPart)-30).match(docLinkReg);
                                        let docCode = null;
                                        if (docCodeMatch){
                                            docCode = docCodeMatch[0];
                                        }
                                        //const docCode = item.full_content.substring(item.full_content.indexOf(docPart)-30).match(docLinkReg)[0];
                                        docPartMap.set(docPart, docPart +
                                            '<key class="bookmark" data-doccode="'+docCode+'" data-docpart="'+docPart.replace('(', '').replace(')', '')+'">'+
                                            '<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M2 4a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v11.5a.5.5 0 0 1-.777.416L7 13.101l-4.223 2.815A.5.5 0 0 1 2 15.5V4z"></path><path d="M4.268 1A2 2 0 0 1 6 0h6a2 2 0 0 1 2 2v11.5a.5.5 0 0 1-.777.416L13 13.768V2a1 1 0 0 0-1-1H4.268z"></path></svg>'+
                                            '</key>');
                                    }
                                    docPartMap.forEach((docPartLink, docPart)=>{
                                        item.full_content = item.full_content.replaceAll(docPart, docPartLink);
                                    })
                                }
                            }
                        }
                        if(item.full_content.includes("<table")){
                            item.full_content = item.full_content.replace('<table ', '<table class="table table-bordered "')
                        }
                        if(item.error_cd !== null){
                            if(sessionUserSe === "ACC_TP01"){
                                item.full_content = "<p class='errorText' id='error"+item.doc_cont_seq+"'>"+item.error_cd+"</p><br>"+
                                    "<div class='input-group w-25 d-none errorEditDiv'>" +
                                    "<input type='hidden' class='docContSeq' value='"+item.doc_cont_seq+"' />"+
                                    "<input type='text' class='form-control form-control-sm errorCd' value='"+item.error_cd+"'/>"+
                                    "<button class='btn btn-sm btn-primary errorEditSaveBtn'>저장</button>"+
                                    "<button class='btn btn-sm btn-secondary errorEditCancelBtn'>취소</button>"+
                                    "</div>"+
                                    item.full_content;
                            }else{
                                item.full_content = "<p class='errorText' id='error"+item.doc_cont_seq+"'>"+item.error_cd+"</p><br>"+item.full_content;
                            }
                            optionTag.push(<option value={item.doc_cont_seq}>{item.error_cd}</option>)
                        }
                        item.full_content = item.full_content+"<hr>"
                        detailTag.push(
                            <VwDiv depth={item.cont_level} isTitle={isTitle} id={item.cont_type_cd} dangerouslySetInnerHTML={ {__html: item.full_content} }></VwDiv>
                        )
                    })
                }else{
                    summaryTag.push(<li key="0">검색된 결과가 없습니다.</li>);
                }
                setDocSummary(summaryTag);
                setDocDetail(detailTag);
                if(optionTag.length>0){
                    errorTag.push(<Form.Select size="sm" onChange={errorSelectorChange}><option value="">선택</option>{optionTag}</Form.Select>)
                    setErrorSelector(errorTag);
                }
                setDocLoading(false);
                document.querySelector(".detailInfoDiv").scrollTop = 0
            },
            function (resp) {
                console.log("err response : ", resp);
            }
        );
        console.groupEnd("EgovMain.getCodeDetailInfo()");
    },[]);

    const docInfoSelectorChange = useCallback((el) => {
        setDocSummary([<div></div>])
        setDocDetail([<div>불러오는중</div>])
        const activeBtn = document.querySelector(".docInfoActive")
        activeBtn.className = activeBtn.className.replace('docInfoActive', '').trim();
        const activeP = document.querySelector(".yearInfoActive")
        activeP.className = activeP.className.replace('yearInfoActive', '').trim();
        const clickBtn = el.target;
        clickBtn.className += " docInfoActive";
        clickBtn.parentElement.querySelector("p").className += " yearInfoActive"
        getCodeDetailInfo(clickBtn.dataset.doccode, clickBtn.dataset.ymd);
    })
    const actionAppend = (el) => {
        if(!el) return;
        if(el.childNodes.length===0){
            return
        }else{
            docLinkActionAppend(el)
            bookmarkBtnActionAppend(el)
            checkboxActionAppend(el)
            if(sessionUserSe === "ACC_TP01"){
                errorTextActionAppend(el)
                errorEditSaveBtnActionAppend(el)
                errorEditCancelBtnActionAppend(el)
            }
        }
    }

    const docLinkActionAppend = (el) => {
        const docLinkList = el.getElementsByClassName("docLink")
        for(let docLink of docLinkList){
            docLink.onclick = (e) => {
                const ymd = document.querySelector(".docInfoActive").dataset.ymd;
                window.open("/standardCode/viewer/"+e.target.dataset.doccode+":"+ymd);
            }

        }
    }
    const bookmarkBtnActionAppend = (el) => {
        const bookmarkList = el.getElementsByClassName("bookmark")
        for(let bookmark of bookmarkList){
            bookmark.onclick = (e) => {
                handleShow();
                const params = e.currentTarget.dataset
                setBookMarkModal(<BookmarkModal docCode={params.doccode} docPart={params.docpart} ymd={document.querySelector(".docInfoActive").dataset.ymd}/>)
            }
        }
    }
    const checkboxActionAppend = (el) => {
        const checkboxList = el.getElementsByClassName("titleCheckBox")
        for(let checkbox of checkboxList){
            checkbox.onclick = (e) => {
                const flag = e.target.checked;
                const childCheckboxList = document.querySelectorAll('.'+e.target.id.replace('chk', ''))
                childCheckboxList.forEach((child)=> {
                    child.checked = flag
                })
            }
        }
    }
    const errorTextActionAppend = (el) => {
        const errorTextList = el.getElementsByClassName("errorText")
        for(let errorText of errorTextList){
            errorText.onclick = (e) => {
                e.target.parentElement.querySelector(".errorText").className = "errorText d-none"
                e.target.parentElement.querySelector(".errorEditDiv").className = "input-group w-25 errorEditDiv"
            }
        }
    }
    const errorEditSaveBtnActionAppend = (el) => {
        const saveBtnList = el.getElementsByClassName("errorEditSaveBtn")
        for(let saveBtn of saveBtnList){
            saveBtn.onclick = (e) => {
                const errorEditDiv = e.target.parentElement;
                const content = {
                    docContSeq: errorEditDiv.querySelector(".docContSeq").value,
                    errorCd: errorEditDiv.querySelector(".errorCd").value
                }
                saveErrorCd(content, errorEditDiv)
                hideErrorEditDiv(e)
            }
        }
    }
    const errorEditCancelBtnActionAppend = (el) => {
        const cancelBtnList = el.getElementsByClassName("errorEditCancelBtn")
        for(let cancelBtn of cancelBtnList){
            cancelBtn.onclick = (e) => {
                hideErrorEditDiv(e)
            }
        }
    }

    function hideErrorEditDiv(e){
        const contentDiv = e.target.parentElement.parentElement;
        contentDiv.querySelector(".errorText").className = "errorText"
        contentDiv.querySelector(".errorEditDiv").className = "input-group w-25 errorEditDiv d-none"
        contentDiv.querySelector(".errorCd").value = contentDiv.querySelector(".errorText").innerText;
    }

    function errorSelectorChange(e){
        window.location.href = window.location.origin+window.location.pathname+"#error"+e.target.value
    }

    function saveErrorCd(content, errorEditDiv){
        EgovNet.requestFetch(
            '/standardCode/auth/saveErrorCd.do',
            {
                method: "POST",
                headers: {
                    'Content-type': 'application/json'
                },
                body: JSON.stringify(content)
            },
            (resp) => {
                if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
                    alert("저장되었습니다.")
                    errorEditDiv.parentElement.querySelector(".errorText").innerText = content.errorCd
                }else if(Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)){
                    console.log("토큰 갱신중.")
                }else{
                    alert("저장에 실패하였습니다.")
                }
            }
        )
    }

    useEffect(() => {
        getCodeTree();
        getCodeInfo(docCode);
        getCodeDetailInfo(docCode);
    }, []);

    console.log("------------------------------viewer [End]");
    console.groupEnd("viewer");
    return (
        <>
            {treeLoading || docLoading? (<Loading/>):(
                <Row className="mx-0">
                    <Col xs={12} className="border-bottom">
                        <Row>
                            <Col xs={3}></Col>
                            <Col xs={9}>
                                <Row className="justify-content-between">
                                    <Col xs={"auto"}>
                                        <Row>
                                            <Col xs={"auto"}>{docInfo}</Col>
                                            <Col>
                                                <input type="button" className="btn btn-sm btn-primary optionBtn" value="연혁"/>
                                                <input type="button" className="btn btn-sm btn-primary optionBtn" value="비교"/>
                                            </Col>
                                        </Row>
                                    </Col>
                                    <Col xs={"auto"}>{errorSelector}</Col>
                                </Row>
                            </Col>
                        </Row>
                    </Col>
                    <Col xs={3} className="border-end viewerDiv">
                        {codeTree}
                    </Col>
                    <Col xs={2} className="border-end viewerDiv">
                        {docSummary}
                    </Col>
                    <Col xs={7} className="viewerDiv detailInfoDiv" ref={actionAppend}>
                        {docDetail}
                    </Col>
                </Row>
                )}
            <Modal show={show} onHide={handleClose} size="xl" keyboard={false} scrollable>
                {bookMarkModal}
            </Modal>
        </>
    );
}

CodeViewer.defaultProps = {
    docCode: 'KCS 24 31 10',
    docName: '용접(한계상태설계법)'
}

export default CodeViewer;
