with open('app/modules/sag/templates/detail.html', 'r', encoding='utf-8') as f:
    text = f.read()

start_marker = "        function renderTimeV1Timeline(entries) {"
end_marker = "        async function loadTimeTrackingTab() {"

start_idx = text.index(start_marker)
end_idx = text.index(end_marker)

print(f"Replacing lines {text[:start_idx].count(chr(10))+1} to {text[:end_idx].count(chr(10))+1}")

new_func = r"""        function renderTimeV1Timeline(entries) {
            const timeline = document.getElementById('timeTimelineColumns');
            if (!timeline) return;

            if (!entries || entries.length === 0) {
                timeline.innerHTML = '<div class="text-muted text-center p-4">Ingen tidsregistreringer endnu</div>';
                return;
            }

            const START_HOUR = 7;
            const TOTAL_HOURS = 10;
            const HOUR_HEIGHT = 60;

            const PALETTE = [
                { border: '#0f4c75', bg: 'rgba(15,76,117,0.09)',  header: 'rgba(15,76,117,0.08)'  },
                { border: '#ef4444', bg: 'rgba(239,68,68,0.09)',   header: 'rgba(239,68,68,0.08)'  },
                { border: '#10b981', bg: 'rgba(16,185,129,0.09)',  header: 'rgba(16,185,129,0.08)' },
                { border: '#f59e0b', bg: 'rgba(245,158,11,0.09)',  header: 'rgba(245,158,11,0.08)' },
                { border: '#8b5cf6', bg: 'rgba(139,92,246,0.09)', header: 'rgba(139,92,246,0.08)' },
                { border: '#ec4899', bg: 'rgba(236,72,153,0.09)', header: 'rgba(236,72,153,0.08)' },
                { border: '#06b6d4', bg: 'rgba(6,182,212,0.09)',   header: 'rgba(6,182,212,0.08)'  },
                { border: '#f97316', bg: 'rgba(249,115,22,0.09)',  header: 'rgba(249,115,22,0.08)' },
            ];

            const allUsers = [...new Set(entries.map(e => e.bruger_navn || e.user_name || 'Ukendt'))].sort();
            const userColor = {};
            allUsers.forEach((u, i) => { userColor[u] = PALETTE[i % PALETTE.length]; });

            const groupedByDate = {};
            entries.forEach(entry => {
                let dateKey;
                if (entry.start_tid)        dateKey = entry.start_tid.substring(0, 10);
                else if (entry.worked_date) dateKey = entry.worked_date.substring(0, 10);
                else if (entry.created_at)  dateKey = entry.created_at.substring(0, 10);
                else                        dateKey = 'Ukendt dato';
                if (!groupedByDate[dateKey]) groupedByDate[dateKey] = [];
                groupedByDate[dateKey].push(entry);
            });

            const sortedDates = Object.keys(groupedByDate).sort((a, b) => new Date(b) - new Date(a));
            let html = '';

            sortedDates.forEach(dateStr => {
                const dayEntries = groupedByDate[dateStr];
                let dateLab = dateStr;
                try {
                    const d = new Date(dateStr);
                    if (!isNaN(d.getTime())) {
                        dateLab = d.toLocaleDateString('da-DK', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });
                        dateLab = dateLab.charAt(0).toUpperCase() + dateLab.slice(1);
                    }
                } catch(e) {}

                const techPlaced = {};
                const unplaced = [];
                const userTotals = {};

                dayEntries.forEach(entry => {
                    const tech = entry.bruger_navn || entry.user_name || 'Ukendt';
                    const mins = entry.faktisk_tid_min
                        ? parseInt(entry.faktisk_tid_min)
                        : Math.round(parseFloat(entry.original_hours || entry.timer || 0) * 60);
                    userTotals[tech] = (userTotals[tech] || 0) + mins;
                    if (entry.start_tid) {
                        if (!techPlaced[tech]) techPlaced[tech] = [];
                        techPlaced[tech].push(entry);
                    } else {
                        unplaced.push(entry);
                    }
                });

                const techNames = Object.keys(techPlaced).sort();

                html += `<div class="time-v1-calendar-container">
                    <div class="time-v1-calendar-header">
                        <i class="bi bi-calendar3 text-primary"></i> ${dateLab}
                    </div>
                    <div class="time-v1-calendar-grid">
                        <div class="time-v1-time-axis">`;

                for (let i = 0; i <= TOTAL_HOURS; i++) {
                    const h = START_HOUR + i;
                    html += `<div class="time-v1-hour-marker" style="top:${i * HOUR_HEIGHT}px">${String(h).padStart(2,'0')}:00</div>`;
                }
                html += `</div>`;

                techNames.forEach(tech => {
                    const c   = userColor[tech] || PALETTE[0];
                    const tot = userTotals[tech] || 0;
                    const totS = tot >= 60
                        ? `${Math.floor(tot/60)}t${tot%60 ? ' '+tot%60+'m' : ''}`
                        : `${tot}m`;

                    html += `<div class="time-v1-tech-col" style="border-top:3px solid ${c.border};">
                        <div class="time-v1-tech-header" style="background:${c.header};">
                            <i class="bi bi-person-fill" style="color:${c.border};"></i>
                            <span style="color:${c.border};font-weight:600;">${escapeHtml(tech)}</span>
                            <span class="ms-auto badge" style="background:${c.border};color:#fff;font-size:0.7rem;">${totS}</span>
                        </div>
                        <div class="time-v1-tech-body">`;

                    const posEntries = [];
                    techPlaced[tech].forEach(entry => {
                        const desc = escapeHtml(entry.beskrivelse || entry.description || 'Ingen beskrivelse');
                        const startObj = new Date(entry.start_tid);
                        let durMin = 30;
                        if (entry.faktisk_tid_min)                    durMin = parseInt(entry.faktisk_tid_min);
                        else if (entry.original_hours || entry.timer) durMin = Math.round(parseFloat(entry.original_hours || entry.timer) * 60);

                        let sH = startObj.getHours(), sM = startObj.getMinutes();
                        if (sH < START_HOUR) { durMin -= (START_HOUR * 60 - sH * 60 - sM); sH = START_HOUR; sM = 0; }

                        let topPx    = ((sH - START_HOUR) + sM / 60) * HOUR_HEIGHT;
                        let heightPx = (durMin / 60) * HOUR_HEIGHT;
                        if (topPx < 0) topPx = 0;
                        if (topPx + heightPx > TOTAL_HOURS * HOUR_HEIGHT) heightPx = TOTAL_HOURS * HOUR_HEIGHT - topPx;

                        if (heightPx > 5 && topPx < TOTAL_HOURS * HOUR_HEIGHT) {
                            const endObj  = new Date(startObj.getTime() + durMin * 60000);
                            const timeStr = `${String(startObj.getHours()).padStart(2,'0')}:${String(startObj.getMinutes()).padStart(2,'0')} \u2013 ${String(endObj.getHours()).padStart(2,'0')}:${String(endObj.getMinutes()).padStart(2,'0')}`;
                            posEntries.push({ topPx, heightPx, desc, timeStr, startMin: topPx, endMin: topPx + heightPx });
                        }
                    });

                    posEntries.sort((a, b) => a.startMin - b.startMin);
                    const lanes = [];
                    posEntries.forEach(e => {
                        let placed = false;
                        for (let li = 0; li < lanes.length; li++) {
                            if (lanes[li] <= e.startMin) { e.lane = li; lanes[li] = e.endMin; placed = true; break; }
                        }
                        if (!placed) { e.lane = lanes.length; lanes.push(e.endMin); }
                    });
                    const numLanes = lanes.length || 1;

                    posEntries.forEach(e => {
                        e.laneSpan = 1;
                        for (let li = e.lane + 1; li < numLanes; li++) {
                            if (!posEntries.some(o => o !== e && o.lane === li && o.startMin < e.endMin && o.endMin > e.startMin)) e.laneSpan++;
                            else break;
                        }
                        const lW = 100 / numLanes;
                        html += `<div class="time-v1-entry-block"
                             style="top:${e.topPx}px;height:${e.heightPx}px;left:${(e.lane*lW).toFixed(1)}%;width:calc(${(e.laneSpan*lW).toFixed(1)}% - 3px);border-left-color:${c.border};background:${c.bg};"
                             title="${e.desc}">
                            <div class="time-v1-entry-time">${e.timeStr}</div>
                            <div class="time-v1-entry-desc">${e.desc}</div>
                        </div>`;
                    });

                    html += `</div></div>`;
                });

                html += `</div>`;

                if (unplaced.length > 0) {
                    html += `<div class="time-v1-unplaced-container">
                        <span class="text-muted small fw-semibold me-2"><i class="bi bi-clock-history"></i> Uden tidsrum:</span>`;
                    unplaced.forEach(u => {
                        const tech = u.bruger_navn || u.user_name || 'Ukendt';
                        const c    = userColor[tech] || PALETTE[0];
                        const mins = u.faktisk_tid_min ? parseInt(u.faktisk_tid_min) : Math.round(parseFloat(u.original_hours || u.timer || 0) * 60);
                        const hStr = mins >= 60 ? `${Math.floor(mins/60)}t${mins%60?' '+mins%60+'m':''}` : `${mins}m`;
                        const desc = escapeHtml(u.beskrivelse || u.description || '');
                        html += `<div class="time-v1-unplaced-item" style="border-color:${c.border};color:${c.border};">
                            <i class="bi bi-person-fill"></i> ${escapeHtml(tech)} &bull; ${hStr}${desc ? ' &middot; <em style="opacity:.7;font-size:.72rem">'+desc+'</em>' : ''}
                        </div>`;
                    });
                    html += `</div>`;
                }

                html += `</div>`;
            });

            timeline.innerHTML = html;
        }

"""

text = text[:start_idx] + new_func + text[end_idx:]

with open('app/modules/sag/templates/detail.html', 'w', encoding='utf-8') as f:
    f.write(text)
print("Done - renderTimeV1Timeline replaced with user-color version")
