<!DOCTYPE html>
<html lang="th">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Omniscience GoJS</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gojs/2.3.11/go.js"></script>
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Thai:wght@400;500&display=swap');
        body { 
            font-family: 'Noto Sans Thai', sans-serif; 
        }
        #myDiagramDiv { 
            height: calc(100vh - 64px); 
            overflow: auto; 
        }
    </style>
</head>
<body class="bg-gray-50">
    <div id="secretKeyModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
        <div class="bg-white p-6 rounded-lg shadow-xl max-w-md w-full">
            <h2 class="text-xl font-semibold mb-4">X-Secret</h2>
            <input 
                type="text" 
                id="secretKeyInput"
                placeholder="Secret Key" 
                class="w-full p-2 border rounded mb-4"
            >
            <button 
                onclick="handleSecretKeySubmit()" 
                class="w-full bg-blue-500 text-white py-2 rounded hover:bg-blue-600"
            >
                ยืนยัน
            </button>
        </div>
    </div>

    <div class="p-4 bg-white shadow flex items-center">
        <input 
            type="text" 
            id="pidInput" 
            placeholder="เลขบัตรประชาชน" 
            class="border p-2 rounded flex-grow mr-2"
        >
        <button 
            onclick="generateTree()" 
            id="generateBtn"
            class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors"
        >
            ค้นหา
        </button>
        <div class="ml-4">
            <button onclick="handleToggleLog()" class="px-3 py-2 bg-gray-200 rounded flex items-center">
                📜 Log <span id="logCount" class="ml-2 bg-blue-500 text-white rounded-full px-2 text-xs">0</span>
            </button>
        </div>
    </div>

    <div id="errorMsg" class="text-red-500 text-center mb-4 hidden"></div>
    <div id="myDiagramDiv" class="bg-white"></div>

    <div id="logContainer" class="fixed bottom-4 right-4 w-96 bg-white rounded-lg shadow-lg max-h-96 overflow-hidden transition-all duration-300 ease-in-out" style="height:0">
        <div class="p-2 bg-gray-100 flex justify-between items-center">
            <span class="font-semibold">Log</span>
            <button onclick="handleClearLog()" class="text-sm bg-red-500 text-white px-2 py-1 rounded">Clear</button>
        </div>
        <div id="log" class="p-2 overflow-y-auto" style="max-height:300px"></div>
    </div>

    <script>
        let myDiagram;
        let accessToken = '';
        let secretKey = '';

        function handleSecretKeySubmit() {
            const key = document.getElementById('secretKeyInput').value.trim();
            if (!key) {
                alert('กรุณาใส่ Secret Key');
                return;
            }
            secretKey = key;
            document.getElementById('secretKeyModal').style.display = 'none';
            init();
        }

        function log(msg, emoji = '📝') {
            const logDiv = document.getElementById('log');
            const div = document.createElement('div');
            div.innerHTML = `
                <div class="flex items-center mb-1 p-1 bg-gray-50 rounded">
                    <span class="mr-2">${emoji}</span>
                    <span class="text-sm">${new Date().toLocaleTimeString()} ${msg}</span>
                </div>
            `;
            logDiv.insertBefore(div, logDiv.firstChild);
            document.getElementById('logCount').textContent = 
                parseInt(document.getElementById('logCount').textContent) + 1;
        }

        function handleToggleLog() {
            const container = document.getElementById('logContainer');
            container.style.height = 
                container.style.height === '0px' || container.style.height === '' ? '400px' : '0';
        }

        function handleClearLog() {
            document.getElementById('log').innerHTML = '';
            document.getElementById('logCount').textContent = '0';
        }

        async function getToken() {
            try {
                log('Getting token', '🔑');
                const response = await fetch('https://omniscience.wenhe.bar/token', {
                    method: 'POST',
                    headers: {
                        'x-secret': secretKey
                    }
                });
                const data = await response.json();
                accessToken = data.access_token;
                log('Token received', '✅');
            } catch (error) {
                log('Failed to get token: ' + error.message, '❌');
                showError('Failed to get access token');
            }
        }

        async function fetchProfile(pid) {
            try {
                log(`Getting profile for ${pid}`, '👤');
                const response = await fetch('https://omniscience.wenhe.bar/v1/nhso/get_profile', {
                    method: 'POST',
                    headers: {
                        'authorization': `Bearer ${accessToken}`,
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({ pid })
                });
                const data = await response.json();
                if (data.status === 'SUCCESS') {
                    log(`Profile found for ${pid}`, '✅');
                }
                return data;
            } catch (error) {
                log(`Error getting profile: ${error.message}`, '❌');
                return null;
            }
        }

        async function fetchChildren(pid, isFemale) {
            try {
                log(`Getting children for ${pid}`, '👶');
                const endpoint = isFemale ? 'pop_mother' : 'pop_father';
                const response = await fetch(`https://omniscience.wenhe.bar/v1/isoc/${endpoint}`, {
                    method: 'POST',
                    headers: {
                        'authorization': `Bearer ${accessToken}`,
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({ pid })
                });
                const data = await response.json();
                const children = data.status === 'SUCCESS' && Array.isArray(data.data) ? data.data : [];
                log(`Found ${children.length} children`, '✅');
                return children;
            } catch (error) {
                log(`Error getting children: ${error.message}`, '❌');
                return [];
            }
        }

        async function fetchImage(pid) {
            if (!pid) return null;
            try {
                const response = await fetch('https://omniscience.wenhe.bar/v1/isoc/pop_image', {
                    method: 'POST',
                    headers: {
                        'authorization': `Bearer ${accessToken}`,
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({ pid })
                });
                const data = await response.json();
                return data.status === 'SUCCESS' ? data.data.image : null;
            } catch {
                return null;
            }
        }

        function showError(message) {
            const errorDiv = document.getElementById('errorMsg');
            errorDiv.textContent = message;
            errorDiv.classList.remove('hidden');
            log(message, '❌');
        }

        function initializeDiagram() {
            const $ = go.GraphObject.make;
            
            myDiagram = $(go.Diagram, "myDiagramDiv", {
                initialContentAlignment: go.Spot.Center,
                "animationManager.isEnabled": false,
                "undoManager.isEnabled": true,
                allowMove: true,
                allowDragOut: true,
                "draggingTool.isGridSnapEnabled": false,
                "draggingTool.isCopyEnabled": false,
                layout: $(go.Layout)
            });

            myDiagram.nodeTemplate =
                $(go.Node, "Vertical",
                    new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
                    {
                        selectionAdorned: false,
                        cursor: "move",
                        mouseDrop: (e, node) => { },
                        mouseEnter: (e, obj) => obj.findObject("SHAPE").scale = 1.1,
                        mouseLeave: (e, obj) => obj.findObject("SHAPE").scale = 1.0
                    },
                    $(go.Panel, "Auto",
                        $(go.Shape, "RoundedRectangle",
                            {
                                name: "SHAPE",
                                fill: "white",
                                stroke: "#ccc",
                                strokeWidth: 2,
                                width: 200,
                                height: 80
                            },
                            new go.Binding("stroke", "gender", gender => 
                                gender === "2" ? "#EC4899" : "#3B82F6"
                            )
                        ),
                        $(go.Panel, "Horizontal",
                            { margin: 8 },
                            $(go.Picture,
                                {
                                    width: 48,
                                    height: 48,
                                    background: "#F3F4F6",
                                    margin: new go.Margin(0, 8, 0, 0)
                                },
                                new go.Binding("source", "image")
                            ),
                            $(go.Panel, "Vertical",
                                { alignment: go.Spot.Left },
                                $(go.TextBlock,
                                    { 
                                        font: "500 14px Noto Sans Thai",
                                        maxLines: 1,
                                        overflow: go.TextBlock.OverflowEllipsis
                                    },
                                    new go.Binding("text", "name")
                                ),
                                $(go.TextBlock,
                                    { 
                                        font: "12px Noto Sans Thai",
                                        stroke: "#6B7280"
                                    },
                                    new go.Binding("text", "pid")
                                ),
                                $(go.TextBlock,
                                    { 
                                        font: "12px Noto Sans Thai",
                                        stroke: "#4B5563"
                                    },
                                    new go.Binding("text", "age", age => `${age} ปี`)
                                )
                            )
                        )
                    )
                );

            myDiagram.linkTemplate =
                $(go.Link,
                    {
                        routing: go.Link.AvoidsNodes,
                        curve: go.Link.JumpOver,
                        corner: 10,
                        reshapable: true,
                        relinkableFrom: true,
                        relinkableTo: true
                    },
                    $(go.Shape,
                        {
                            strokeWidth: 2,
                            stroke: "#CBD5E1"
                        }
                    )
                );
        }

        async function init() {
            try {
                await getToken();
                if (!accessToken) {
                    showError('Failed to initialize: Could not get access token');
                    return;
                }
                log('Successfully initialized', '✅');
                initializeDiagram();
            } catch (error) {
                showError('Failed to initialize application');
                log('Initialization error: ' + error.message, '❌');
            }
        }

        async function generateTree() {
            const pid = document.getElementById('pidInput').value.trim();
            if (pid.length !== 13) {
                showError('กรุณากรอกเลขประจำตัวประชาชน 13 หลัก');
                return;
            }

            const generateBtn = document.getElementById('generateBtn');
            generateBtn.disabled = true;
            generateBtn.textContent = 'กำลังค้นหา...';

            try {
                if (!accessToken) {
                    await getToken();
                    if (!accessToken) {
                        throw new Error('Could not get access token');
                    }
                }

                const nodeDataArray = new Map();
                const linkDataArray = new Map();

                function createLinkKey(from, to) {
                    return `${from}-${to}`;
                }

                async function collectData(pid, visited = new Set()) {
                    if (visited.has(pid)) return;
                    visited.add(pid);

                    const profile = await fetchProfile(pid);
                    if (!profile.data) return;

                    const person = profile.data.personData;
                    const isFemale = person.sex === '2';
                    
                    let image = null;
                    let hasImage = false;
                    if (person.age.years >= 10) {
                        image = await fetchImage(pid);
                        if (image) {
                            image = `data:image/png;base64,${image}`;
                            hasImage = true;
                        }
                    }

                    const randomX = Math.random() * 500;
                    const randomY = Math.random() * 500;

                    nodeDataArray.set(pid, {
                        key: pid,
                        name: `${person.fname} ${person.lname}`,
                        gender: person.sex,
                        age: person.age.years,
                        image: image,
                        hasImage: hasImage,
                        pid: pid,
                        loc: `${randomX} ${randomY}`
                    });

                    if (person.fatherId) {
                        const linkKey = createLinkKey(person.fatherId, pid);
                        linkDataArray.set(linkKey, { from: person.fatherId, to: pid });
                        await collectData(person.fatherId, visited);
                    }
                    if (person.motherId) {
                        const linkKey = createLinkKey(person.motherId, pid);
                        linkDataArray.set(linkKey, { from: person.motherId, to: pid });
                        await collectData(person.motherId, visited);
                    }

                    const children = await fetchChildren(pid, isFemale);
                    if (Array.isArray(children)) {
                        for (const child of children) {
                            const linkKey = createLinkKey(pid, child.pid);
                            linkDataArray.set(linkKey, { from: pid, to: child.pid });
                            await collectData(child.pid, visited);
                        }
                    }
                }

                await collectData(pid);
                const nodeArray = Array.from(nodeDataArray.values());
                const linkArray = Array.from(linkDataArray.values());

                myDiagram.model = new go.GraphLinksModel(nodeArray, linkArray);
                myDiagram.zoomToFit();
                log('Family tree generation complete', '🌳');
            } catch (error) {
                showError('Failed to generate family tree');
                log('Error: ' + error.message, '❌');
            } finally {
                generateBtn.disabled = false;
                generateBtn.textContent = 'ค้นหา';
            }
        }

        document.getElementById('secretKeyInput').addEventListener('keypress', function(e) {
            if (e.key === 'Enter') {
                handleSecretKeySubmit();
            }
        });

        document.getElementById('pidInput').addEventListener('keypress', function(e) {
            if (e.key === 'Enter') {
                generateTree();
            }
        });
    </script>
</body>
</html>