{% extends "base.html" %}

{% block title %}Interactive Family Tree - KJV Study{% endblock %}
{% block description %}Explore biblical genealogies interactively from Adam to Jesus Christ.{% endblock %}

{% block head %}
<style>
.tree-header {
    max-width: 55%;
    margin: 2rem 0;
    padding-bottom: 1rem;
    border-bottom: 2px solid #111;
}

.tree-title {
    font-size: 2.5rem;
    font-weight: 400;
    margin: 0 0 0.5rem 0;
    line-height: 1.2;
}

.tree-subtitle {
    font-size: 1.2rem;
    color: #666;
    font-style: italic;
}

.intro-text {
    max-width: 55%;
    font-size: 1.1rem;
    line-height: 1.8;
    margin: 1.5rem 0;
}

/* Controls */
.tree-controls {
    max-width: 55%;
    display: flex;
    align-items: center;
    gap: 1.5rem;
    margin: 1.5rem 0;
    padding: 1rem 0;
    border-bottom: 1px solid #ccc;
    flex-wrap: wrap;
}

.control-group {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.control-group label {
    font-size: 0.95rem;
    color: #555;
}

.control-group select {
    font-family: inherit;
    font-size: 0.95rem;
    padding: 0.4rem 0.6rem;
    border: 1px solid #ccc;
    border-radius: 3px;
    background: white;
}

.control-group input[type="text"] {
    font-family: inherit;
    font-size: 0.95rem;
    padding: 0.4rem 0.6rem;
    border: 1px solid #ccc;
    border-radius: 3px;
    width: 180px;
}

.btn {
    font-family: inherit;
    font-size: 0.9rem;
    padding: 0.4rem 0.8rem;
    border: 1px solid #4a7c59;
    border-radius: 3px;
    background: #4a7c59;
    color: white;
    cursor: pointer;
}

.btn:hover {
    background: #3d6a4b;
}

.btn-secondary {
    background: white;
    color: #4a7c59;
}

.btn-secondary:hover {
    background: #f5f5f5;
}

/* Tree container */
.tree-container {
    max-width: 80%;
    margin: 2rem 0;
}

/* Tree nodes */
.tree-node {
    margin: 0.5rem 0 0.5rem 1rem;
    border-left: 2px solid #ccc;
    padding-left: 0.75rem;
}

.tree-node-root {
    margin-left: 0;
    border-left: none;
    padding-left: 0;
}

.tree-node.selected {
    background: rgba(74, 124, 89, 0.08);
    outline: 2px solid #4a7c59;
    outline-offset: 4px;
}

.tree-node.kekule {
    border-left-color: #d4af37;
}

.tree-node.kekule.selected {
    background: rgba(212, 175, 55, 0.08);
    outline-color: #d4af37;
}

.person-name {
    font-size: 1.1rem;
    font-weight: 600;
    margin-bottom: 0.25rem;
}

.person-name a {
    color: var(--link-color);
    text-decoration: none;
}

.person-name a:hover {
    text-decoration: underline;
}

.person-name .expand-toggle {
    font-family: monospace;
    font-size: 0.9rem;
    color: #888;
    cursor: pointer;
    user-select: none;
    margin-left: 0.5rem;
}

.person-name .expand-toggle:hover {
    color: #4a7c59;
}

.person-meta {
    font-size: 0.95rem;
    color: #666;
    margin-bottom: 0.25rem;
}

.person-details {
    font-size: 0.9rem;
    color: #888;
}

.person-details a {
    color: #888;
    text-decoration: none;
}

.person-details a:hover {
    text-decoration: underline;
}

.person-verse a {
    color: var(--link-color);
}

.children-container {
    display: block;
}

.children-container.collapsed {
    display: none;
}

/* Stats */
.tree-stats {
    font-size: 0.9rem;
    color: #666;
    margin: 1rem 0;
}

/* Navigation */
.navigation-links {
    max-width: 55%;
    margin: 2rem 0;
    padding-top: 1rem;
    border-top: 1px solid #ccc;
}

.navigation-links a {
    margin-right: 1.5rem;
}

/* Keyboard hint */
.keyboard-hint {
    max-width: 55%;
    font-size: 0.85rem;
    color: #888;
    margin: 1rem 0;
}

.keyboard-hint kbd {
    font-family: monospace;
    background: #f5f5f5;
    border: 1px solid #ddd;
    border-radius: 3px;
    padding: 0.1rem 0.4rem;
}

/* Dark mode */
[data-theme="dark"] .tree-header {
    border-bottom-color: #444;
}

[data-theme="dark"] .tree-subtitle,
[data-theme="dark"] .person-meta,
[data-theme="dark"] .person-spouse {
    color: #888;
}

[data-theme="dark"] .control-group label {
    color: #aaa;
}

[data-theme="dark"] .control-group select,
[data-theme="dark"] .control-group input[type="text"] {
    background: #1a1a1a;
    border-color: #444;
    color: #e0e0e0;
}

[data-theme="dark"] .tree-node {
    border-left-color: #444;
}

[data-theme="dark"] .tree-node.selected {
    background: rgba(74, 124, 89, 0.2);
}

[data-theme="dark"] .tree-node.kekule.selected {
    background: rgba(212, 175, 55, 0.15);
}

[data-theme="dark"] .expand-toggle {
    color: #888;
}

[data-theme="dark"] .expand-toggle:hover {
    color: #6b9b7a;
}

[data-theme="dark"] .tree-controls {
    border-bottom-color: #444;
}

[data-theme="dark"] .navigation-links {
    border-top-color: #444;
}

[data-theme="dark"] .keyboard-hint {
    color: #666;
}

[data-theme="dark"] .keyboard-hint kbd {
    background: #2a2a2a;
    border-color: #444;
}

/* Mobile full width */
@media (max-width: 768px) {
    .tree-header,
    .intro-text,
    .tree-controls,
    .navigation-links,
    .keyboard-hint {
        max-width: 100%;
    }
    .tree-container {
        max-width: 100%;
    }
}
</style>
{% endblock %}

{% block content %}
<div class="tree-header">
    <h1 class="tree-title">Interactive Family Tree</h1>
    <p class="tree-subtitle">From Adam to Jesus Christ</p>
</div>

<div class="intro-text">
    <p><span class="newthought">Explore the biblical genealogy</span> from creation to Christ. Click the arrows to expand or collapse branches, or use keyboard navigation. Names highlighted in gold are direct ancestors of Jesus Christ.</p>
</div>

<div class="tree-controls">
    <div class="control-group">
        <label for="root-select">Start from:</label>
        <select id="root-select">
            <option value="adam">Adam</option>
            <option value="noah">Noah</option>
            <option value="abraham">Abraham</option>
            <option value="jacob">Jacob (Israel)</option>
            <option value="david">David</option>
            <option value="jesus">Jesus (ancestors)</option>
        </select>
    </div>
    <div class="control-group">
        <label for="search-input">Search:</label>
        <input type="text" id="search-input" placeholder="Find a person...">
    </div>
    <button class="btn btn-secondary" id="expand-all">Expand All</button>
    <button class="btn btn-secondary" id="collapse-all">Collapse All</button>
</div>

<div class="tree-stats" id="tree-stats"></div>

<div class="tree-container" id="tree-container">
    <div class="tree-loading">Loading family tree...</div>
</div>

<div class="keyboard-hint">
    <kbd>↑</kbd><kbd>↓</kbd> navigate · <kbd>←</kbd><kbd>→</kbd> collapse/expand · <kbd>Enter</kbd> view person · <kbd>e</kbd> expand all · <kbd>c</kbd> collapse all
</div>

<div class="navigation-links">
    <a href="/family-tree">← Family Tree</a>
    <a href="/family-tree/lineage">Messianic Lineage</a>
</div>

<script>
const familyTreeData = {{ family_tree_data | tojson }};

let currentRoot = 'adam';
let collapsedNodes = new Set();
let expandedNodes = new Set(); // Manually expanded nodes (override depth limit)
let selectedIndex = -1;
let visibleNodes = [];
let defaultDepth = 2; // Show 2 levels by default

// Find person ID by name
function findPersonId(name) {
    const nameLower = name.toLowerCase();
    for (const [id, person] of Object.entries(familyTreeData)) {
        if (person.name.toLowerCase() === nameLower ||
            person.name.toLowerCase().includes(nameLower)) {
            return id;
        }
    }
    return null;
}

// Get root mappings
const rootMappings = {
    'adam': 'Adam',
    'noah': 'Noah',
    'abraham': 'Abraham',
    'jacob': 'Jacob',
    'david': 'David',
    'jesus': 'Jesus'
};

// Build tree HTML recursively
function buildTreeHTML(personId, depth = 0, visited = new Set(), isRoot = false) {
    if (visited.has(personId) || depth > 50) return '';
    visited.add(personId);

    const person = familyTreeData[personId];
    if (!person) return '';

    const children = person.children || [];
    const hasChildren = children.length > 0;
    // Auto-collapse nodes beyond default depth on initial render
    const isCollapsed = collapsedNodes.has(personId) || (depth >= defaultDepth && hasChildren && !expandedNodes.has(personId));
    const hasKekule = person.kekule_number !== null && person.kekule_number !== undefined;

    let html = `<div class="tree-node${isRoot ? ' tree-node-root' : ''}${hasKekule ? ' kekule' : ''}" data-id="${personId}">`;

    // Name line with expand toggle showing child count
    html += '<div class="person-name">';
    html += `<a href="/family-tree/person/${personId}">${person.name}</a>`;
    if (hasChildren) {
        html += `<span class="expand-toggle" data-id="${personId}">${isCollapsed ? '+' : '−'}</span>`;
    }
    html += '</div>';

    // Generation line
    if (person.generation) {
        html += `<div class="person-meta">Generation ${person.generation} from Adam</div>`;
    }

    // Details line (lifespan, children, spouse, verse)
    let details = [];

    // Extract lifespan from death_year if it contains "Lived X years"
    const lifespanMatch = person.death_year && person.death_year.match(/Lived (\d+) years/);
    if (lifespanMatch) {
        details.push(`Lived ${lifespanMatch[1]} years`);
    }

    // Number of children
    if (children.length > 0) {
        details.push(`${children.length} ${children.length > 1 ? 'children' : 'child'}`);
    }

    // Spouse
    if (person.spouse) {
        const spouseId = findPersonId(person.spouse);
        if (spouseId) {
            details.push(`∞ <a href="/family-tree/person/${spouseId}">${person.spouse}</a>`);
        } else {
            details.push(`∞ ${person.spouse}`);
        }
    }

    // Scripture reference
    if (person.verses && person.verses.length > 0) {
        const verse = person.verses[0];
        const refMatch = verse.reference.match(/^(\d?\s*[A-Za-z]+)\s+(\d+):(\d+)/);
        if (refMatch) {
            const book = refMatch[1].trim();
            const chapter = refMatch[2];
            const verseNum = refMatch[3];
            const verseUrl = `/book/${encodeURIComponent(book)}/chapter/${chapter}#verse-${verseNum}`;
            details.push(`<span class="person-verse"><a href="${verseUrl}">${verse.reference}</a></span>`);
        }
    }

    if (details.length > 0) {
        html += `<div class="person-details">${details.join(' · ')}</div>`;
    }

    // Children
    if (hasChildren) {
        html += `<div class="children-container${isCollapsed ? ' collapsed' : ''}" data-parent="${personId}">`;
        for (const childId of children) {
            html += buildTreeHTML(childId, depth + 1, visited);
        }
        html += '</div>';
    }

    html += '</div>';
    return html;
}

// Build ancestors tree (for Jesus view)
function buildAncestorsHTML(personId, depth = 0, visited = new Set(), isRoot = false) {
    if (visited.has(personId) || depth > 50) return '';
    visited.add(personId);

    const person = familyTreeData[personId];
    if (!person) return '';

    const parents = person.parents || [];
    const hasParents = parents.length > 0;
    // Auto-collapse nodes beyond default depth on initial render
    const isCollapsed = collapsedNodes.has(personId) || (depth >= defaultDepth && hasParents && !expandedNodes.has(personId));
    const hasKekule = person.kekule_number !== null && person.kekule_number !== undefined;

    let html = `<div class="tree-node${isRoot ? ' tree-node-root' : ''}${hasKekule ? ' kekule' : ''}" data-id="${personId}">`;

    // Name line with expand toggle showing parent count
    html += '<div class="person-name">';
    html += `<a href="/family-tree/person/${personId}">${person.name}</a>`;
    if (hasParents) {
        html += `<span class="expand-toggle" data-id="${personId}">${isCollapsed ? '+' : '−'}</span>`;
    }
    html += '</div>';

    // Generation line
    if (person.generation) {
        html += `<div class="person-meta">Generation ${person.generation} from Adam</div>`;
    }

    // Details line (lifespan, children count, spouse, verse)
    let details = [];

    // Extract lifespan from death_year if it contains "Lived X years"
    const lifespanMatch = person.death_year && person.death_year.match(/Lived (\d+) years/);
    if (lifespanMatch) {
        details.push(`Lived ${lifespanMatch[1]} years`);
    }

    // Number of children
    const children = person.children || [];
    if (children.length > 0) {
        details.push(`${children.length} ${children.length > 1 ? 'children' : 'child'}`);
    }

    // Spouse
    if (person.spouse) {
        const spouseId = findPersonId(person.spouse);
        if (spouseId) {
            details.push(`∞ <a href="/family-tree/person/${spouseId}">${person.spouse}</a>`);
        } else {
            details.push(`∞ ${person.spouse}`);
        }
    }

    // Scripture reference
    if (person.verses && person.verses.length > 0) {
        const verse = person.verses[0];
        const refMatch = verse.reference.match(/^(\d?\s*[A-Za-z]+)\s+(\d+):(\d+)/);
        if (refMatch) {
            const book = refMatch[1].trim();
            const chapter = refMatch[2];
            const verseNum = refMatch[3];
            const verseUrl = `/book/${encodeURIComponent(book)}/chapter/${chapter}#verse-${verseNum}`;
            details.push(`<span class="person-verse"><a href="${verseUrl}">${verse.reference}</a></span>`);
        }
    }

    if (details.length > 0) {
        html += `<div class="person-details">${details.join(' · ')}</div>`;
    }

    if (hasParents) {
        html += `<div class="children-container${isCollapsed ? ' collapsed' : ''}" data-parent="${personId}">`;
        for (const parentId of parents) {
            html += buildAncestorsHTML(parentId, depth + 1, visited);
        }
        html += '</div>';
    }

    html += '</div>';
    return html;
}

// Render tree
function renderTree() {
    const container = document.getElementById('tree-container');
    const rootName = rootMappings[currentRoot];
    let rootId;

    if (currentRoot === 'jesus') {
        rootId = findPersonId('Jesus') || findPersonId('Jesus Christ');
    } else if (currentRoot === 'jacob') {
        // Find Jacob/Israel specifically
        for (const [id, person] of Object.entries(familyTreeData)) {
            if (person.name === 'Jacob' && person.generation) {
                rootId = id;
                break;
            }
        }
        if (!rootId) rootId = findPersonId('Jacob');
    } else {
        rootId = findPersonId(rootName);
    }

    if (!rootId) {
        container.innerHTML = '<p>Person not found.</p>';
        return;
    }

    let html;
    if (currentRoot === 'jesus') {
        html = buildAncestorsHTML(rootId, 0, new Set(), true);
    } else {
        html = buildTreeHTML(rootId, 0, new Set(), true);
    }

    container.innerHTML = html;

    // Update stats
    const nodeCount = container.querySelectorAll('.tree-node').length;
    document.getElementById('tree-stats').textContent = `Showing ${nodeCount} people`;

    // Update visible nodes for keyboard nav
    updateVisibleNodes();

    // Add click handlers for expand toggles
    container.querySelectorAll('.expand-toggle:not(.empty)').forEach(toggle => {
        toggle.addEventListener('click', (e) => {
            e.stopPropagation();
            const id = toggle.dataset.id;
            toggleNode(id);
        });
    });
}

// Toggle node expand/collapse
function toggleNode(personId) {
    const toggle = document.querySelector(`.expand-toggle[data-id="${personId}"]`);
    const children = document.querySelector(`.children-container[data-parent="${personId}"]`);
    const isCurrentlyCollapsed = children && children.classList.contains('collapsed');

    if (isCurrentlyCollapsed) {
        // Expanding
        collapsedNodes.delete(personId);
        expandedNodes.add(personId);
    } else {
        // Collapsing
        collapsedNodes.add(personId);
        expandedNodes.delete(personId);
    }

    // Update the UI
    if (toggle && children) {
        const shouldCollapse = !isCurrentlyCollapsed;
        toggle.textContent = shouldCollapse ? '+' : '−';
        children.classList.toggle('collapsed', shouldCollapse);
    }

    updateVisibleNodes();
}

// Update list of visible nodes for keyboard navigation
function updateVisibleNodes() {
    visibleNodes = Array.from(document.querySelectorAll('.tree-node')).filter(node => {
        // Check if any ancestor is collapsed
        let parent = node.parentElement;
        while (parent) {
            if (parent.classList.contains('collapsed')) {
                return false;
            }
            parent = parent.parentElement;
        }
        return true;
    });
}

// Select node by index
function selectNode(index) {
    // Deselect previous
    if (selectedIndex >= 0 && selectedIndex < visibleNodes.length) {
        visibleNodes[selectedIndex].classList.remove('selected');
    }

    selectedIndex = Math.max(0, Math.min(index, visibleNodes.length - 1));

    if (selectedIndex >= 0 && selectedIndex < visibleNodes.length) {
        visibleNodes[selectedIndex].classList.add('selected');
        visibleNodes[selectedIndex].scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
}

// Expand all nodes
function expandAll() {
    collapsedNodes.clear();
    // Mark all as manually expanded to override depth limit
    for (const id of Object.keys(familyTreeData)) {
        expandedNodes.add(id);
    }
    renderTree();
}

// Collapse all nodes
function collapseAll() {
    expandedNodes.clear();
    collapsedNodes.clear();
    // Just re-render - depth limit will collapse everything beyond defaultDepth
    renderTree();
}

// Search functionality
let searchTimeout;
document.getElementById('search-input').addEventListener('input', (e) => {
    clearTimeout(searchTimeout);
    const query = e.target.value.trim().toLowerCase();

    if (!query) return;

    searchTimeout = setTimeout(() => {
        // Find matching person
        const personId = findPersonId(query);
        if (personId) {
            // Expand path to this person
            expandPathTo(personId);

            // Find and select the node
            updateVisibleNodes();
            const nodeIndex = visibleNodes.findIndex(n => n.dataset.id === personId);
            if (nodeIndex >= 0) {
                selectNode(nodeIndex);
            }
        }
    }, 300);
});

// Expand path from root to a specific person
function expandPathTo(targetId) {
    const person = familyTreeData[targetId];
    if (!person) return;

    // For descendants view, expand all ancestors of the target (walk up to root)
    if (currentRoot !== 'jesus') {
        const parents = person.parents || [];
        for (const parentId of parents) {
            expandedNodes.add(parentId);
            collapsedNodes.delete(parentId);
            expandPathTo(parentId);
        }
    } else {
        // For ancestors view, expand children path (walk down to root)
        const children = person.children || [];
        for (const childId of children) {
            expandedNodes.add(childId);
            collapsedNodes.delete(childId);
            expandPathTo(childId);
        }
    }

    expandedNodes.add(targetId);
    collapsedNodes.delete(targetId);
    renderTree();
}

// Root selector
document.getElementById('root-select').addEventListener('change', (e) => {
    currentRoot = e.target.value;
    collapsedNodes.clear();
    expandedNodes.clear();
    selectedIndex = -1;
    renderTree();
});

// Expand/collapse all buttons
document.getElementById('expand-all').addEventListener('click', expandAll);
document.getElementById('collapse-all').addEventListener('click', collapseAll);

// Keyboard navigation
document.addEventListener('keydown', (e) => {
    if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') {
        return;
    }
    // Don't handle if sidebar navigation is active
    if (KJVNav.sidebarActive) return;

    switch (e.key) {
        case 'ArrowDown':
        case 'j':
            e.preventDefault();
            selectNode(selectedIndex < 0 ? 0 : selectedIndex + 1);
            break;

        case 'ArrowUp':
        case 'k':
            e.preventDefault();
            selectNode(selectedIndex <= 0 ? 0 : selectedIndex - 1);
            break;

        case 'ArrowRight':
        case 'l':
            e.preventDefault();
            if (selectedIndex >= 0 && selectedIndex < visibleNodes.length) {
                const id = visibleNodes[selectedIndex].dataset.id;
                const childContainer = document.querySelector(`.children-container[data-parent="${id}"]`);
                // Expand if currently collapsed
                if (childContainer && childContainer.classList.contains('collapsed')) {
                    toggleNode(id);
                }
            }
            break;

        case 'ArrowLeft':
        case 'h':
            e.preventDefault();
            if (selectedIndex >= 0 && selectedIndex < visibleNodes.length) {
                const id = visibleNodes[selectedIndex].dataset.id;
                const childContainer = document.querySelector(`.children-container[data-parent="${id}"]`);
                // Collapse if currently expanded
                if (childContainer && !childContainer.classList.contains('collapsed')) {
                    toggleNode(id);
                }
            }
            break;

        case 'Enter':
            e.preventDefault();
            if (selectedIndex >= 0 && selectedIndex < visibleNodes.length) {
                const link = visibleNodes[selectedIndex].querySelector('.person-name a');
                if (link) window.location.href = link.href;
            }
            break;

        case 'e':
            e.preventDefault();
            expandAll();
            break;

        case 'c':
            e.preventDefault();
            collapseAll();
            break;

        case 'Escape':
            e.preventDefault();
            if (selectedIndex >= 0 && selectedIndex < visibleNodes.length) {
                visibleNodes[selectedIndex].classList.remove('selected');
            }
            selectedIndex = -1;
            break;
    }
});

// Find best root for a given person (nearest "save point" ancestor)
function findBestRoot(personId) {
    const rootOrder = ['david', 'jacob', 'abraham', 'noah', 'adam'];
    const rootIds = {};

    // Find IDs for each root
    for (const rootName of rootOrder) {
        const id = findPersonId(rootMappings[rootName] || rootName);
        if (id) rootIds[rootName] = id;
    }

    // Check if person is a descendant of each root (starting from most specific)
    for (const rootName of rootOrder) {
        const rootId = rootIds[rootName];
        if (!rootId) continue;

        // Check if personId is a descendant of rootId
        if (isDescendantOf(personId, rootId)) {
            return rootName;
        }
    }

    return 'adam'; // Default fallback
}

// Check if personId is a descendant of ancestorId
function isDescendantOf(personId, ancestorId, visited = new Set()) {
    if (personId === ancestorId) return true;
    if (visited.has(personId)) return false;
    visited.add(personId);

    const person = familyTreeData[personId];
    if (!person || !person.parents) return false;

    for (const parentId of person.parents) {
        if (isDescendantOf(parentId, ancestorId, visited)) {
            return true;
        }
    }
    return false;
}

// Handle URL parameters (e.g., ?person=i77)
function handleUrlParams() {
    const params = new URLSearchParams(window.location.search);
    const personId = params.get('person');

    if (personId && familyTreeData[personId]) {
        // Find best root for this person
        const bestRoot = findBestRoot(personId);
        if (bestRoot !== currentRoot) {
            currentRoot = bestRoot;
            document.getElementById('root-select').value = bestRoot;
            renderTree();
        }

        // Expand path to this person and select them
        expandPathTo(personId);
        updateVisibleNodes();
        const nodeIndex = visibleNodes.findIndex(n => n.dataset.id === personId);
        if (nodeIndex >= 0) {
            selectNode(nodeIndex);
        }
    }
}

// Initial render
renderTree();
handleUrlParams();
</script>
{% endblock %}
