<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>Координаты дня</title>
    <style>
        :root {
            --axis-color: #333;
            --grid-color: rgba(0, 0, 0, 0.08);
            --text-color: #222;
            --bg-color: #fff;
            --btn-bg: #f5f5f5;
        }
        @media (prefers-color-scheme: dark) {
            :root {
                --axis-color: #ddd;
                --grid-color: rgba(255, 255, 255, 0.1);
                --text-color: #eee;
                --bg-color: #121212;
                --btn-bg: #1e1e1e;
            }
        }
       
        body, html { margin: 0; padding: 0; height: 100%; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: var(--bg-color); color: var(--text-color); display: flex; flex-direction: column; overflow: hidden; touch-action: pan-y; }
       
        .header { text-align: center; padding: 15px 10px 5px; position: relative; z-index: 10; background: var(--bg-color); border-bottom: 1px solid var(--grid-color); }
        .month-nav { display: flex; justify-content: space-between; align-items: center; max-width: 300px; margin: 0 auto; gap: 10px; }
        .month-label { font-size: 18px; font-weight: 600; min-width: 120px; text-align: center; }
        .nav-btn { width: 36px; height: 36px; border: 1px solid var(--grid-color); border-radius: 8px; background: var(--btn-bg); display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 20px; line-height: 1; }
        .nav-btn:active { background: var(--grid-color); }
       
        .chart-container { flex-grow: 1; position: relative; padding: 60px 40px 60px 50px; overflow: hidden; }
       
        svg { width: 100%; height: 100%; display: block; }
       
        .y-axis line, .x-axis line { stroke: var(--axis-color); stroke-width: 1; shape-rendering: crispEdges; }
        .grid line { stroke: var(--grid-color); stroke-width: 1; }
       
        .tick-text { fill: var(--text-color); font-size: 12px; dominant-baseline: middle; pointer-events: none; user-select: none; }
        .y-tick { text-anchor: end; dx: -8px; }
        .x-tick { text-anchor: middle; dy: 20px; opacity: 0.7; }
       
        .point { cursor: pointer; transition: r 0.1s ease; }
        .point:hover { r: 10 !important; }
       
        /* Цвета точек */
        .p-0 { fill: #D32F2F; }      /* Красный */
        .p-6 { fill: #9E9E9E; }      /* Серый */
        .p-7 { fill: #FFEB3B; }      /* Желтый */
        .p-8 { fill: #FFA000; }      /* Оранжевый */
        .p-9 { fill: #64DD17; }      /* Салатовый */
        .p-10 { fill: #00C853; }     /* Изумрудный */
       
        .empty-day { fill: transparent; stroke: var(--grid-color); stroke-width: 1; rx: 5; cursor: pointer; }
        .empty-day:hover { fill: rgba(0,0,0,0.02); }
       
        .modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: center; visibility: hidden; opacity: 0; transition: opacity 0.2s ease; z-index: 100; }
        .modal.active { visibility: visible; opacity: 1; }
        .modal-content { background: var(--bg-color); padding: 25px; border-radius: 16px; width: 90%; max-width: 400px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); transform: scale(0.9); transition: transform 0.2s ease; }
        .modal.active .modal-content { transform: scale(1); }
        .modal-header { font-size: 18px; font-weight: 600; margin-bottom: 10px; }
        .score-display { font-size: 48px; font-weight: bold; text-align: center; margin: 15px 0; line-height: 1; }
        .note-input { width: 100%; padding: 12px; border: 1px solid var(--grid-color); border-radius: 8px; font-size: 16px; margin-top: 15px; box-sizing: border-box; background: inherit; color: inherit; }
        .modal-actions { display: flex; gap: 10px; margin-top: 20px; }
        .btn { flex: 1; padding: 12px; border: none; border-radius: 8px; font-size: 16px; cursor: pointer; text-align: center; }
        .btn-cancel { background: var(--btn-bg); color: var(--text-color); }
        .btn-save { background: #007AFF; color: white; }
       
        .toast { position: fixed; top: 100px; left: 50%; transform: translateX(-50%); background: rgba(0,0,0,0.8); color: white; padding: 12px 20px; border-radius: 25px; font-size: 14px; opacity: 0; pointer-events: none; transition: opacity 0.3s; z-index: 200; }
        .toast.show { opacity: 1; }
       
        .legend { position: absolute; top: 15px; right: 15px; font-size: 12px; background: rgba(255,255,255,0.9); backdrop-filter: blur(10px); padding: 8px 12px; border-radius: 20px; border: 1px solid var(--grid-color); display: none; }
        @media (min-width: 500px) { .legend { display: block; } }
        .legend-item { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
        .legend-dot { width: 10px; height: 10px; border-radius: 50%; border: 1px solid var(--grid-color); }
    </style>
</head>
<body>

<div class="header">
    <div class="month-nav">
        <div class="nav-btn" id="prevMonth">&#8249;</div>
        <div class="month-label" id="monthLabel"></div>
        <div class="nav-btn" id="nextMonth">&#8250;</div>
    </div>
</div>

<div class="chart-container" id="chartArea">
    <!-- SVG График будет здесь -->
</div>

<!-- Модальное окно подтверждения -->
<div class="modal" id="confirmModal">
    <div class="modal-content">
        <div class="modal-header">Оценка за день</div>
        <div class="day-indicator" id="modalDay"></div>
        <div class="score-display" id="modalScore"></div>
        <input type="text" class="note-input" id="noteInput" placeholder="Заметка (необязательно)">
        <div class="modal-actions">
            <button class="btn btn-cancel" id="cancelBtn">Отмена</button>
            <button class="btn btn-save" id="saveBtn">Сохранить</button>
        </div>
    </div>
</div>

<div class="toast" id="toast">Записано</div>

<script>
// --- ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ---
let currentDate = new Date();
let dataStore = {};
const efficiencyMap = [
    {val: 0, label: 'Нулевая активность', colorClass: 'p-0'},
    {val: 6, label: 'Еле встал / Апатия', colorClass: 'p-6'},
    {val: 7, label: 'Базовое выживание', colorClass: 'p-7'},
    {val: 8, label: 'Главное дело сделано', colorClass: 'p-8'},
    {val: 9, label: 'Продуктивный день', colorClass: 'p-9'},
    {val: 10, label: 'Прорыв', colorClass: 'p-10'}
];

// --- ЭЛЕМЕНТЫ DOM ---
const chartArea = document.getElementById('chartArea');
const monthLabel = document.getElementById('monthLabel');
const prevMonthBtn = document.getElementById('prevMonth');
const nextMonthBtn = document.getElementById('nextMonth');
const confirmModal = document.getElementById('confirmModal');
const modalDay = document.getElementById('modalDay');
const modalScore = document.getElementById('modalScore');
const noteInput = document.getElementById('noteInput');
const saveBtn = document.getElementById('saveBtn');
const cancelBtn = document.getElementById('cancelBtn');
const toast = document.getElementById('toast');

// --- УТИЛИТЫ ---
function formatKey(date) {
    return date.toISOString().slice(0, 7);
}
function getDaysInMonth(year, month) {
    return new Date(year, month + 1, 0).getDate();
}
function loadData() {
    const raw = localStorage.getItem('day_coordinates_data');
    if (raw) {
        try {
            dataStore = JSON.parse(raw);
        } catch(e) {
            console.error("Ошибка парсинга данных", e);
            dataStore = {};
        }
    }
}
function saveData() {
    localStorage.setItem('day_coordinates_data', JSON.stringify(dataStore));
}

// --- ЛОГИКА РИСОВАНИЯ ---
function renderChart() {
    const key = formatKey(currentDate);
    const year = currentDate.getFullYear();
    const month = currentDate.getMonth();
   
    const options = { month: 'long' };
    monthLabel.textContent = currentDate.toLocaleDateString('ru-RU', options) + ' ' + year;
   
    const daysInCurrentMonth = getDaysInMonth(year, month);
    const monthData = dataStore[key] || [];
   
    const containerRect = chartArea.getBoundingClientRect();
    const w = containerRect.width;
    const h = containerRect.height;
    const paddingLeft = 50;
    const paddingBottom = 60;
    const plotW = w - paddingLeft;
    const plotH = h - paddingBottom;
   
    const xScale = (i) => paddingLeft + (i * plotW / 31);
    const yScale = (score) => {
        const levels = [0, 6, 7, 8, 9, 10];
        const step = plotH / (levels.length - 1);
        const index = levels.indexOf(score);
        return h - paddingBottom - (index * step);
    };

    chartArea.innerHTML = '';
   
    const svgNS = "http://www.w3.org/2000/svg";
    const svg = document.createElementNS(svgNS, 'svg');
    svg.setAttribute('width', w);
    svg.setAttribute('height', h);
    chartArea.appendChild(svg);

    const gridGroup = document.createElementNS(svgNS, 'g');
    const axisGroup = document.createElementNS(svgNS, 'g');
    svg.appendChild(gridGroup);
    svg.appendChild(axisGroup);

    const yLevels = [0, 6, 7, 8, 9, 10];
    yLevels.forEach((lvl, idx) => {
        const y = yScale(lvl);
        const line = document.createElementNS(svgNS, 'line');
        line.setAttribute('x1', paddingLeft);
        line.setAttribute('x2', w);
        line.setAttribute('y1', y);
        line.setAttribute('y2', y);
        line.classList.add('grid');
        gridGroup.appendChild(line);
       
        const text = document.createElementNS(svgNS, 'text');
        text.setAttribute('x', paddingLeft - 15);
        text.setAttribute('y', y + 4);
        text.classList.add('tick-text', 'y-tick');
        text.textContent = lvl === 0 ? '0' : lvl.toString();
        axisGroup.appendChild(text);
    });

    for(let i = 1; i <= daysInCurrentMonth; i++) {
        const x = xScale(i - 1);
        const vLine = document.createElementNS(svgNS, 'line');
        vLine.setAttribute('x1', x);
        vLine.setAttribute('x2', x);
        vLine.setAttribute('y1', 0);
        vLine.setAttribute('y2', h - paddingBottom);
        vLine.classList.add('grid');
        gridGroup.appendChild(vLine);
       
        const xText = document.createElementNS(svgNS, 'text');
        xText.setAttribute('x', x);
        xText.setAttribute('y', h - paddingBottom + 20);
        xText.classList.add('tick-text', 'x-tick');
        xText.textContent = i;
        axisGroup.appendChild(xText);
    }

    const pointsGroup = document.createElementNS(svgNS, 'g');
    svg.appendChild(pointsGroup);

    monthData.forEach(item => {
        const day = item.dayOfMonth;
        const score = item.efficiencyScore;
        if(day > daysInCurrentMonth) return;
       
        const cx = xScale(day - 1);
        const cy = yScale(score);
       
        const circle = document.createElementNS(svgNS, 'circle');
        circle.setAttribute('cx', cx);
        circle.setAttribute('cy', cy);
        circle.setAttribute('r', 8);
        circle.classList.add('point', item.colorClass);
        circle.dataset.day = day;
        circle.dataset.score = score;
        circle.dataset.note = item.note || '';
        pointsGroup.appendChild(circle);
    });

    for(let d = 1; d <= daysInCurrentMonth; d++) {
        const exists = monthData.find(it => it.dayOfMonth === d);
        if(exists) continue;
       
        const rect = document.createElementNS(svgNS, 'rect');
        const size = 20;
        const rx = xScale(d - 1) - size/2;
        const ry = yScale(6) - size/2;
       
        rect.setAttribute('x', rx);
        rect.setAttribute('y', ry);
        rect.setAttribute('width', size);
        rect.setAttribute('height', size);
        rect.classList.add('empty-day');
        rect.dataset.day = d;
        pointsGroup.appendChild(rect);
    }

    pointsGroup.addEventListener('click', function(e) {
        let target = e.target;
        if(target.tagName !== 'circle' && target.tagName !== 'rect') return;
       
        const day = parseInt(target.dataset.day);
        const today = new Date();
        const isPastOrToday = (
            currentDate.getMonth() === today.getMonth() &&
            currentDate.getFullYear() === today.getFullYear() &&
            day <= today.getDate()
        ) || currentDate < today;
       
        if(!isPastOrToday) return;

        const existingScore = parseInt(target.dataset.score);
       
        openModal(day, existingScore);
    });
}

// --- МОДАЛЬНОЕ ОКНО ---
function openModal(day, presetScore = null) {
    modalDay.textContent = `День ${day}`;
    if(presetScore !== null){
        modalScore.textContent = presetScore;
        modalScore.className = `score-display ${findColorClass(presetScore)}`;
        noteInput.value = findNoteFor(day, presetScore);
    } else {
        modalScore.textContent = '?';
        modalScore.className = 'score-display';
        noteInput.value = '';
    }
    confirmModal.classList.add('active');
   
    const allPoints = document.querySelectorAll('.point');
    allPoints.forEach(pt => pt.style.outline = '');
   
    const handler = function(e) {
        const clickedScore = parseInt(e.target.dataset.score);
        modalScore.textContent = clickedScore;
        modalScore.className = `score-display ${e.target.classList.contains('point') ? e.target.classList[1] : ''}`;
       
        allPoints.forEach(pt => pt.removeEventListener('click', handler));
    };
   
    if(presetScore === null){
        setTimeout(() => {
            allPoints.forEach(pt => pt.addEventListener('click', handler));
        }, 300);
    }
}

function closeModal(save = false) {
    confirmModal.classList.remove('active');
    if(save){
        const day = parseInt(modalDay.textContent.replace('День ', ''));
        const score = parseInt(modalScore.textContent);
        const note = noteInput.value.trim();
       
        upsertPoint({date: currentDate, dayOfMonth: day, efficiencyScore: score, note: note});
        showToast('Записано');
        renderChart();
    }
}

// --- РАБОТА С ДАННЫМИ ---
function upsertPoint(pointObj) {
    const key = formatKey(pointObj.date);
    if (!dataStore[key]) dataStore[key] = [];
   
    dataStore[key] = dataStore[key].filter(item => item.dayOfMonth !== pointObj.dayOfMonth);
   
    const colorCls = findColorClass(pointObj.efficiencyScore);
    dataStore[key].push({
        ...pointObj,
        colorClass: colorCls
    });
   
    dataStore[key].sort((a,b) => a.dayOfMonth - b.dayOfMonth);
    saveData();
}

function findColorClass(score) {
    const found = efficiencyMap.find(el => el.val === score);
    return found ? found.colorClass : 'p-6';
}

function findNoteFor(day, score) {
    const key = formatKey(currentDate);
    const item = (dataStore[key] || []).find(it => it.dayOfMonth === day && it.efficiencyScore === score);
    return item ? item.note : '';
}

function showToast(msg) {
    toast.textContent = msg;
    toast.classList.add('show');
    setTimeout(() => toast.classList.remove('show'), 1500);
}

// --- НАВИГАЦИЯ ---
prevMonthBtn.addEventListener('click', () => {
    currentDate.setMonth(currentDate.getMonth() - 1);
    renderChart();
});
nextMonthBtn.addEventListener('click', () => {
    currentDate.setMonth(currentDate.getMonth() + 1);
    renderChart();
});

saveBtn.addEventListener('click', () => closeModal(true));
cancelBtn.addEventListener('click', () => closeModal(false));
window.addEventListener('keydown', (e) => {
    if(e.key === 'Escape' && confirmModal.classList.contains('active')) closeModal(false);
});

// --- ЗАПУСК ---
loadData();
renderChart();
</script>

</body>
</html>