#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# app.py - основной скрипт для Apache2 с mod_wsgi

import os
import sys
import logging
import re
import json
from datetime import datetime, timedelta, timezone
from functools import wraps
from flask import Flask, request, Response, jsonify, render_template_string, session, redirect, url_for
import secrets

app = Flask(__name__)

# Секретный ключ для сессий
app.secret_key = secrets.token_hex(32)

# Настройка логирования
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('/opt/api/logs/app.log'),
        logging.StreamHandler(sys.stdout)
    ]
)
logger = logging.getLogger(__name__)

# Конфигурация
LOG_DIR = "/opt/api/apilog"
USERNAME = "admin"
PASSWORD = "админ@2026"
BOT_TOKEN = "7957630117:AAHxO2DEdpR7Y8t4d55gDPyaKuO0Fd9M7rY"
SESSION_TIMEOUT_MINUTES = 0

# Переменные для API доступа
API_USER = "event"
API_PASS = "Event2026"

# Файл для хранения статуса переданных событий
SENT_EVENTS_FILE = "/opt/api/sent_events.json"

# Убедимся, что директория для логов существует
if not os.path.exists(LOG_DIR):
    os.makedirs(LOG_DIR, mode=0o755)
    logger.info(f"Created log directory: {LOG_DIR}")

# Создаем директорию для файлов состояния если нужно
os.makedirs(os.path.dirname(SENT_EVENTS_FILE), exist_ok=True)

logger.info(f"Application started with LOG_DIR={LOG_DIR}")
logger.info(f"Configured username: {USERNAME}")
logger.info(f"Bot token: {BOT_TOKEN}")
logger.info(f"API credentials configured")

def load_sent_events():
    """Загружает список отправленных событий"""
    if os.path.exists(SENT_EVENTS_FILE):
        try:
            with open(SENT_EVENTS_FILE, 'r', encoding='utf-8') as f:
                return json.load(f)
        except:
            return []
    return []

def save_sent_events(events):
    """Сохраняет список отправленных событий"""
    try:
        with open(SENT_EVENTS_FILE, 'w', encoding='utf-8') as f:
            json.dump(events, f, ensure_ascii=False, indent=2)
        return True
    except Exception as e:
        logger.error(f"Error saving sent events: {e}")
        return False

def get_current_time():
    """Возвращает текущее время с часовым поясом UTC"""
    return datetime.now(timezone.utc)

def add_timestamp_to_event(message):
    """Добавляет временную метку к событию в формате YYYYMMDD_hhmmss"""
    now = datetime.now()
    timestamp = now.strftime("%Y%m%d_%H%M%S")
    return f"[{timestamp}]\n{message}"

def parse_events_from_file(content):
    """Парсит файл логов, извлекая события с timestamp и телом сообщения"""
    events = []
    
    # Ищем все блоки, начинающиеся с [timestamp]
    pattern = r'\[(\d{8}_\d{6})\]\n?(.*?)(?=\n\[|$)'
    matches = re.findall(pattern, content, re.DOTALL)
    
    for match in matches:
        timestamp = match[0]
        event_body = match[1].strip()
        
        # Удаляем пустые строки в начале тела сообщения
        event_body = re.sub(r'^\n+', '', event_body)
        
        if event_body:
            events.append({
                'timestamp': timestamp,
                'body': event_body
            })
    
    return events

def parse_event_from_log(event_text):
    """Извлекает timestamp и текст события из многострочного лога"""
    lines = event_text.strip().split('\n')
    if not lines:
        return None
    
    for i, line in enumerate(lines):
        line = line.strip()
        pattern = r'\[(\d{8}_\d{6})\]'
        match = re.match(pattern, line)
        if match:
            event_date = match.group(1)
            event_body = '\n'.join(lines[i+1:]).strip()
            event_body = re.sub(r'^\n+', '', event_body)
            return {
                'event_date': event_date,
                'event_text': event_body
            }
    
    return None

def format_event_for_display(event_date_str, event_text):
    """Форматирует событие для отображения на странице"""
    try:
        if '_' in event_date_str:
            date_part = event_date_str.split('_')[0]
            time_part = event_date_str.split('_')[1]
            
            year = date_part[0:4]
            month = date_part[4:6]
            day = date_part[6:8]
            
            hour = time_part[0:2]
            minute = time_part[2:4]
            second = time_part[4:6]
            
            header = f"Дата события: {day} {month} {year}  Время события: {hour} час. {minute} мин. {second} сек."
            return f"{header}\n{event_text}"
    except:
        pass
    
    return event_text

def get_events_for_date_range(start_date, end_date):
    """Получает все события за указанный диапазон дат"""
    events = []
    
    start = datetime.strptime(start_date, '%Y%m%d')
    end = datetime.strptime(end_date, '%Y%m%d')
    
    current = start
    event_counter = 1
    
    while current <= end:
        date_str = current.strftime('%Y%m%d')
        log_file = os.path.join(LOG_DIR, f'api_{date_str}.log')
        
        if os.path.exists(log_file):
            with open(log_file, 'r', encoding='utf-8') as f:
                content = f.read()
            
            parsed_events = parse_events_from_file(content)
            
            for parsed in parsed_events:
                events.append({
                    'event_id': str(event_counter),
                    'event_date': parsed['timestamp'],
                    'event_text': parsed['body']
                })
                event_counter += 1
        
        current += timedelta(days=1)
    
    return events

def get_events_for_date(date_str):
    """Получает все события за конкретную дату"""
    events = []
    
    log_file = os.path.join(LOG_DIR, f'api_{date_str}.log')
    
    if os.path.exists(log_file):
        with open(log_file, 'r', encoding='utf-8') as f:
            content = f.read()
        
        parsed_events = parse_events_from_file(content)
        
        for idx, parsed in enumerate(parsed_events, 1):
            events.append({
                'event_id': str(idx),
                'event_date': parsed['timestamp'],
                'event_text': parsed['body']
            })
    
    return events

def get_all_events():
    """Получает все события из всех лог-файлов"""
    events = []
    
    for filename in sorted(os.listdir(LOG_DIR)):
        if filename.startswith('api_') and filename.endswith('.log'):
            log_file = os.path.join(LOG_DIR, filename)
            with open(log_file, 'r', encoding='utf-8') as f:
                content = f.read()
            
            parsed_events = parse_events_from_file(content)
            
            for parsed in parsed_events:
                events.append({
                    'event_id': f"{filename}_{parsed['timestamp']}",
                    'event_date': parsed['timestamp'],
                    'event_text': parsed['body']
                })
    
    return events

def get_new_events():
    """Получает новые события, которые еще не были отправлены"""
    all_events = get_all_events()
    sent_events = load_sent_events()
    
    sent_ids = [event['event_id'] for event in sent_events]
    new_events = [event for event in all_events if event['event_id'] not in sent_ids]
    
    return new_events

def mark_events_as_sent(events):
    """Отмечает события как отправленные"""
    sent_events = load_sent_events()
    sent_ids = [event['event_id'] for event in sent_events]
    
    for event in events:
        if event['event_id'] not in sent_ids:
            sent_events.append(event)
    
    save_sent_events(sent_events)

# Декоратор для проверки API ключей (для мобильного приложения)
def api_auth_required(f):
    """Декоратор для проверки API аутентификации через параметры user/pass"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        user = request.args.get('user') or request.headers.get('X-API-User')
        password = request.args.get('pass') or request.headers.get('X-API-Key')
        
        if user == API_USER and password == API_PASS:
            return f(*args, **kwargs)
        else:
            logger.warning(f"API auth failed - User: {user}")
            return jsonify({'error': 'Unauthorized', 'message': 'Invalid API credentials'}), 401
    return decorated_function

# Декоратор для проверки веб-аутентификации (для браузера)
def login_required(f):
    """Декоратор для проверки авторизации в веб-интерфейсе"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        # Проверяем, что запрос хочет JSON (мобильное приложение)
        if request.headers.get('Accept') == 'application/json' or \
           request.headers.get('User-Agent', '').startswith('AlexEventsList'):
            # Для мобильного приложения используем API аутентификацию
            user = request.args.get('user') or request.headers.get('X-API-User')
            password = request.args.get('pass') or request.headers.get('X-API-Key')
            
            if user == API_USER and password == API_PASS:
                return f(*args, **kwargs)
            else:
                return jsonify({'error': 'Unauthorized', 'message': 'Invalid API credentials'}), 401
        
        # Для браузера используем сессионную аутентификацию
        if 'user_id' not in session:
            logger.info("User not authenticated, redirecting to login")
            return redirect(url_for('login'))
        
        if SESSION_TIMEOUT_MINUTES:
            login_time = session.get('login_time')
            if login_time:
                elapsed = (get_current_time() - login_time).total_seconds() / 60
                if elapsed > SESSION_TIMEOUT_MINUTES:
                    logger.info(f"Session expired for user {session.get('username')}")
                    session.clear()
                    return redirect(url_for('login', message='Сессия истекла. Пожалуйста, войдите снова.'))
        
        return f(*args, **kwargs)
    return decorated_function

# HTML шаблон страницы логина
LOGIN_TEMPLATE = '''
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Вход в систему</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .login-container {
            background: white;
            border-radius: 10px;
            box-shadow: 0 10px 40px rgba(0,0,0,0.1);
            width: 100%;
            max-width: 400px;
            padding: 40px;
        }
        
        .login-header {
            text-align: center;
            margin-bottom: 30px;
        }
        
        .login-header h1 {
            color: #333;
            font-size: 24px;
            margin-bottom: 10px;
        }
        
        .login-header p {
            color: #666;
            font-size: 14px;
        }
        
        .form-group {
            margin-bottom: 20px;
        }
        
        .form-group label {
            display: block;
            margin-bottom: 8px;
            color: #333;
            font-weight: 500;
        }
        
        .form-group input {
            width: 100%;
            padding: 12px;
            border: 1px solid #ddd;
            border-radius: 5px;
            font-size: 14px;
            transition: border-color 0.3s;
        }
        
        .form-group input:focus {
            outline: none;
            border-color: #667eea;
        }
        
        .btn-login {
            width: 100%;
            padding: 12px;
            background: #667eea;
            color: white;
            border: none;
            border-radius: 5px;
            font-size: 16px;
            font-weight: 500;
            cursor: pointer;
            transition: background 0.3s;
        }
        
        .btn-login:hover {
            background: #5a67d8;
        }
        
        .error-message {
            background: #fed7d7;
            color: #c53030;
            padding: 10px;
            border-radius: 5px;
            margin-bottom: 20px;
            text-align: center;
            font-size: 14px;
        }
        
        .info-message {
            background: #e6fffa;
            color: #2c7a7b;
            padding: 10px;
            border-radius: 5px;
            margin-bottom: 20px;
            text-align: center;
            font-size: 14px;
        }
    </style>
</head>
<body>
    <div class="login-container">
        <div class="login-header">
            <h1>🔐 Вход в систему</h1>
        </div>
        
        {% if error %}
        <div class="error-message">
            {{ error }}
        </div>
        {% endif %}
        
        {% if message %}
        <div class="info-message">
            {{ message }}
        </div>
        {% endif %}
        
        <form method="POST" action="{{ url_for('login') }}">
            <div class="form-group">
                <label for="username">Имя пользователя</label>
                <input type="text" id="username" name="username" required autofocus>
            </div>
            
            <div class="form-group">
                <label for="password">Пароль</label>
                <input type="password" id="password" name="password" required>
            </div>
            
            <button type="submit" class="btn-login">Войти</button>
        </form>
    </div>
</body>
</html>
'''

# HTML шаблон для страницы просмотра логов с календарем
HTML_TEMPLATE = '''
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API Logs Viewer</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
    <script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
    <script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/l10n/ru.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: #1e1e1e;
            color: #d4d4d4;
            line-height: 1.6;
            padding: 20px;
        }
        
        .container {
            max-width: 1400px;
            margin: 0 auto;
        }
        
        .header {
            background: #2d2d2d;
            padding: 15px;
            border-radius: 5px;
            margin-bottom: 20px;
            border-left: 4px solid #4caf50;
            position: sticky;
            top: 0;
            z-index: 10;
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-wrap: wrap;
            gap: 10px;
        }
        
        .header h1 {
            color: #4caf50;
            font-size: 1.5em;
        }
        
        .user-info {
            display: flex;
            align-items: center;
            gap: 15px;
        }
        
        .user-info span {
            color: #888;
            font-size: 0.9em;
        }
        
        .logout-btn {
            background: #dc3545;
            color: white;
            border: none;
            padding: 5px 15px;
            border-radius: 3px;
            cursor: pointer;
            font-size: 0.9em;
            transition: background 0.2s;
        }
        
        .logout-btn:hover {
            background: #c82333;
        }
        
        .controls {
            background: #252526;
            padding: 15px;
            border-radius: 5px;
            margin-bottom: 20px;
            display: flex;
            gap: 15px;
            align-items: center;
            flex-wrap: wrap;
        }
        
        .date-controls {
            display: flex;
            gap: 10px;
            align-items: center;
            flex-wrap: wrap;
        }
        
        .date-btn {
            background: #3e3e3e;
            color: #d4d4d4;
            border: 1px solid #4caf50;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            transition: all 0.2s;
            font-size: 14px;
        }
        
        .date-btn:hover {
            background: #4caf50;
            color: white;
        }
        
        .date-btn.active {
            background: #4caf50;
            color: white;
        }
        
        .date-input {
            background: #3e3e3e;
            color: #d4d4d4;
            border: 1px solid #4caf50;
            padding: 8px 12px;
            border-radius: 4px;
            font-size: 14px;
            cursor: pointer;
        }
        
        .date-input:hover {
            background: #4caf50;
            color: white;
        }
        
        .range-info {
            background: #3e3e3e;
            padding: 8px 12px;
            border-radius: 4px;
            font-size: 14px;
            color: #4caf50;
        }
        
        .auto-refresh-info {
            background: #3e3e3e;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            transition: background 0.2s;
            font-size: 14px;
        }
        
        .auto-refresh-info:hover {
            background: #4caf50;
        }
        
        .auto-refresh-info.active {
            background: #4caf50;
        }
        
        .logs-container {
            background: #252526;
            border-radius: 5px;
            overflow: hidden;
            min-height: 500px;
        }
        
        .message-block {
            background: #2d2d2d;
            margin: 10px;
            padding: 15px;
            border-radius: 5px;
            border-left: 3px solid #4caf50;
            white-space: pre-wrap;
            word-break: break-word;
            font-family: 'Courier New', monospace;
            font-size: 0.9em;
            line-height: 1.5;
        }
        
        .message-header {
            color: #4caf50;
            font-weight: bold;
            margin-bottom: 10px;
            padding-bottom: 5px;
            border-bottom: 1px solid #3e3e3e;
        }
        
        .message-body {
            color: #d4d4d4;
        }
        
        .message-block.new {
            animation: highlight 1s ease-out;
            border-left-color: #ff9800;
        }
        
        @keyframes highlight {
            0% {
                background: #4caf50;
                border-left-color: #ff9800;
            }
            100% {
                background: #2d2d2d;
                border-left-color: #4caf50;
            }
        }
        
        .message-block:hover {
            background: #3d3d3d;
        }
        
        .loading {
            text-align: center;
            padding: 20px;
            color: #888;
        }
        
        .no-more {
            text-align: center;
            padding: 20px;
            color: #888;
            font-style: italic;
        }
        
        .scroll-to-bottom {
            position: fixed;
            bottom: 30px;
            right: 30px;
            width: 50px;
            height: 50px;
            background: #4caf50;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            box-shadow: 0 2px 10px rgba(0,0,0,0.3);
            transition: transform 0.2s, background 0.2s;
            z-index: 1000;
        }
        
        .scroll-to-bottom:hover {
            background: #45a049;
            transform: scale(1.1);
        }
        
        .scroll-to-bottom:active {
            transform: scale(0.95);
        }
        
        .scroll-to-bottom svg {
            width: 24px;
            height: 24px;
            fill: white;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .spinner {
            display: inline-block;
            width: 16px;
            height: 16px;
            border: 2px solid #4caf50;
            border-top-color: transparent;
            border-radius: 50%;
            animation: spin 0.6s linear infinite;
            margin-left: 10px;
        }
        
        .error-message {
            background: #5a1e1e;
            color: #ff6b6b;
            padding: 10px;
            border-radius: 5px;
            margin: 10px;
            text-align: center;
        }
        
        .notification {
            position: fixed;
            bottom: 100px;
            right: 30px;
            background: #4caf50;
            color: white;
            padding: 10px 20px;
            border-radius: 5px;
            font-size: 0.9em;
            z-index: 1000;
            animation: slideIn 0.3s ease-out;
        }
        
        @keyframes slideIn {
            from {
                transform: translateX(100%);
                opacity: 0;
            }
            to {
                transform: translateX(0);
                opacity: 1;
            }
        }
        
        @media (max-width: 768px) {
            .controls {
                flex-direction: column;
                align-items: stretch;
            }
            
            .date-controls {
                flex-direction: column;
            }
            
            .header {
                flex-direction: column;
                text-align: center;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>📋 API Logs Viewer</h1>
            <div class="user-info">
                <span>👤 {{ username }}</span>
                <form method="POST" action="{{ url_for('logout') }}" style="margin: 0;">
                    <button type="submit" class="logout-btn">Выйти</button>
                </form>
            </div>
        </div>
        
        <div class="controls">
            <div class="date-controls">
                <button class="date-btn" id="today-btn">📅 Сегодня</button>
                <button class="date-btn" id="yesterday-btn">📆 Вчера</button>
                <input type="text" id="date-picker" class="date-input" placeholder="Выберите дату">
                <button class="date-btn" id="range-btn">📅📅 Выбрать интервал</button>
                <button class="date-btn" id="clear-range-btn" style="display:none;">❌ Очистить интервал</button>
            </div>
            <div class="auto-refresh-info active" id="auto-refresh-toggle">🔄 Автообновление: ВКЛ</div>
            <div class="range-info" id="range-info" style="display:none;"></div>
        </div>
        
        <div class="logs-container" id="logs-container">
            <div class="loading">Загрузка логов...</div>
        </div>
    </div>
    
    <div class="scroll-to-bottom" id="scroll-to-bottom" title="Вниз">
        <svg viewBox="0 0 24 24">
            <path d="M7.41,8.59L12,13.17L16.59,8.59L18,10L12,16L6,10L7.41,8.59Z"/>
        </svg>
    </div>
    
    <div id="notification" style="display: none;"></div>
    
    <script>
        let currentView = 'today';
        let currentDate = null;
        let currentRange = null;
        let loading = false;
        let container = document.getElementById('logs-container');
        let autoRefresh = true;
        let refreshInterval = null;
        let isAtBottom = true;
        let lastMessageCount = 0;
        
        const datePicker = flatpickr("#date-picker", {
            locale: "ru",
            dateFormat: "Y-m-d",
            onChange: function(selectedDates, dateStr, instance) {
                if (selectedDates.length === 1) {
                    loadEventsForDate(dateStr);
                }
            }
        });
        
        let rangePicker = null;
        
        function showNotification(message, isError = false) {
            const notification = document.getElementById('notification');
            notification.textContent = message;
            notification.style.display = 'block';
            notification.style.background = isError ? '#dc3545' : '#4caf50';
            notification.classList.add('notification');
            setTimeout(() => {
                notification.style.display = 'none';
                notification.style.background = '#4caf50';
            }, 3000);
        }
        
        function scrollToBottom() {
            window.scrollTo({
                top: document.documentElement.scrollHeight,
                behavior: 'smooth'
            });
            isAtBottom = true;
        }
        
        function checkIfAtBottom() {
            const scrollPosition = window.scrollY + window.innerHeight;
            const pageHeight = document.documentElement.scrollHeight;
            isAtBottom = Math.abs(scrollPosition - pageHeight) < 100;
        }
        
        function createMessageBlock(event) {
            const messageBlock = document.createElement('div');
            messageBlock.className = 'message-block';
            
            const firstNewLine = event.event_text.indexOf('\\n');
            let header, body;
            
            if (firstNewLine !== -1) {
                header = event.event_text.substring(0, firstNewLine);
                body = event.event_text.substring(firstNewLine + 1);
            } else {
                header = event.event_text;
                body = '';
            }
            
            const headerDiv = document.createElement('div');
            headerDiv.className = 'message-header';
            headerDiv.textContent = header;
            
            const bodyDiv = document.createElement('div');
            bodyDiv.className = 'message-body';
            bodyDiv.textContent = body;
            
            messageBlock.appendChild(headerDiv);
            if (body) {
                messageBlock.appendChild(bodyDiv);
            }
            
            return messageBlock;
        }
        
        async function loadEventsForDate(dateStr) {
            if (loading) return;
            loading = true;
            currentView = 'date';
            currentDate = dateStr;
            currentRange = null;
            
            document.getElementById('range-info').style.display = 'none';
            document.getElementById('clear-range-btn').style.display = 'none';
            
            container.innerHTML = '<div class="loading">Загрузка событий...<span class="spinner"></span></div>';
            
            try {
                const response = await fetch(`/api/events/date/${dateStr}`);
                const data = await response.json();
                
                if (data.error) {
                    container.innerHTML = `<div class="error-message">Ошибка: ${data.error}</div>`;
                    return;
                }
                
                if (data.events && data.events.length > 0) {
                    container.innerHTML = '';
                    data.events.forEach((event) => {
                        const messageBlock = createMessageBlock(event);
                        container.appendChild(messageBlock);
                    });
                    lastMessageCount = data.events.length;
                    setTimeout(() => scrollToBottom(), 100);
                } else {
                    container.innerHTML = '<div class="no-more">📭 Нет событий за выбранную дату</div>';
                    lastMessageCount = 0;
                }
            } catch (error) {
                console.error('Error loading events:', error);
                container.innerHTML = '<div class="error-message">Ошибка загрузки событий</div>';
            } finally {
                loading = false;
            }
        }
        
        async function loadEventsForRange(startDate, endDate) {
            if (loading) return;
            loading = true;
            currentView = 'range';
            currentRange = { start: startDate, end: endDate };
            currentDate = null;
            
            document.getElementById('range-info').style.display = 'block';
            document.getElementById('range-info').innerHTML = `📅 Диапазон: ${startDate} - ${endDate}`;
            document.getElementById('clear-range-btn').style.display = 'inline-block';
            
            container.innerHTML = '<div class="loading">Загрузка событий...<span class="spinner"></span></div>';
            
            try {
                const response = await fetch(`/api/events/range/${startDate}/${endDate}`);
                const data = await response.json();
                
                if (data.error) {
                    container.innerHTML = `<div class="error-message">Ошибка: ${data.error}</div>`;
                    return;
                }
                
                if (data.events && data.events.length > 0) {
                    container.innerHTML = '';
                    data.events.forEach((event) => {
                        const messageBlock = createMessageBlock(event);
                        container.appendChild(messageBlock);
                    });
                    lastMessageCount = data.events.length;
                    setTimeout(() => scrollToBottom(), 100);
                } else {
                    container.innerHTML = '<div class="no-more">📭 Нет событий за выбранный период</div>';
                    lastMessageCount = 0;
                }
            } catch (error) {
                console.error('Error loading events:', error);
                container.innerHTML = '<div class="error-message">Ошибка загрузки событий</div>';
            } finally {
                loading = false;
            }
        }
        
        async function loadTodayEvents() {
            if (loading) return;
            loading = true;
            currentView = 'today';
            currentDate = null;
            currentRange = null;
            
            document.getElementById('range-info').style.display = 'none';
            document.getElementById('clear-range-btn').style.display = 'none';
            datePicker.clear();
            
            container.innerHTML = '<div class="loading">Загрузка событий...<span class="spinner"></span></div>';
            
            try {
                const response = await fetch('/api/events/today');
                const data = await response.json();
                
                if (data.error) {
                    container.innerHTML = `<div class="error-message">Ошибка: ${data.error}</div>`;
                    return;
                }
                
                if (data.events && data.events.length > 0) {
                    container.innerHTML = '';
                    data.events.forEach((event) => {
                        const messageBlock = createMessageBlock(event);
                        container.appendChild(messageBlock);
                    });
                    lastMessageCount = data.events.length;
                    setTimeout(() => scrollToBottom(), 100);
                } else {
                    container.innerHTML = '<div class="no-more">📭 Нет событий за сегодня</div>';
                    lastMessageCount = 0;
                }
            } catch (error) {
                console.error('Error loading events:', error);
                container.innerHTML = '<div class="error-message">Ошибка загрузки событий</div>';
            } finally {
                loading = false;
            }
        }
        
        async function checkForNewMessages() {
            if (!autoRefresh || loading || currentView !== 'today') return;
            
            try {
                const response = await fetch('/api/events/today/count');
                const data = await response.json();
                
                if (data.count > lastMessageCount && lastMessageCount > 0) {
                    const newMessagesCount = data.count - lastMessageCount;
                    showNotification(`📨 Получено ${newMessagesCount} новое событие`);
                    await loadTodayEvents();
                    
                    if (isAtBottom) {
                        setTimeout(() => scrollToBottom(), 100);
                    }
                }
                
                lastMessageCount = data.count;
            } catch (error) {
                console.error('Error checking for new messages:', error);
            }
        }
        
        function startAutoRefresh() {
            if (refreshInterval) {
                clearInterval(refreshInterval);
            }
            refreshInterval = setInterval(checkForNewMessages, 5000);
        }
        
        function toggleAutoRefresh() {
            autoRefresh = !autoRefresh;
            const toggleBtn = document.getElementById('auto-refresh-toggle');
            
            if (autoRefresh) {
                toggleBtn.textContent = '🔄 Автообновление: ВКЛ';
                toggleBtn.classList.add('active');
                startAutoRefresh();
                showNotification('Автообновление включено');
            } else {
                toggleBtn.textContent = '⏸️ Автообновление: ВЫКЛ';
                toggleBtn.classList.remove('active');
                if (refreshInterval) {
                    clearInterval(refreshInterval);
                    refreshInterval = null;
                }
                showNotification('Автообновление выключено');
            }
        }
        
        function selectRange() {
            if (rangePicker) {
                rangePicker.destroy();
            }
            
            rangePicker = flatpickr("#date-picker", {
                locale: "ru",
                mode: "range",
                dateFormat: "Y-m-d",
                onChange: function(selectedDates, dateStr, instance) {
                    if (selectedDates.length === 2) {
                        const startDate = formatDate(selectedDates[0]);
                        const endDate = formatDate(selectedDates[1]);
                        loadEventsForRange(startDate, endDate);
                        instance.close();
                    }
                }
            });
            
            rangePicker.open();
        }
        
        function formatDate(date) {
            const year = date.getFullYear();
            const month = String(date.getMonth() + 1).padStart(2, '0');
            const day = String(date.getDate()).padStart(2, '0');
            return `${year}-${month}-${day}`;
        }
        
        function clearRange() {
            currentRange = null;
            currentView = 'today';
            document.getElementById('range-info').style.display = 'none';
            document.getElementById('clear-range-btn').style.display = 'none';
            datePicker.clear();
            datePicker.set('mode', 'single');
            if (rangePicker) {
                rangePicker.destroy();
                rangePicker = null;
            }
            loadTodayEvents();
        }
        
        document.getElementById('today-btn').addEventListener('click', loadTodayEvents);
        document.getElementById('yesterday-btn').addEventListener('click', () => {
            const yesterday = new Date();
            yesterday.setDate(yesterday.getDate() - 1);
            const dateStr = formatDate(yesterday);
            loadEventsForDate(dateStr);
            datePicker.setDate(dateStr);
        });
        document.getElementById('range-btn').addEventListener('click', selectRange);
        document.getElementById('clear-range-btn').addEventListener('click', clearRange);
        document.getElementById('auto-refresh-toggle').addEventListener('click', toggleAutoRefresh);
        document.getElementById('scroll-to-bottom').addEventListener('click', scrollToBottom);
        window.addEventListener('scroll', checkIfAtBottom);
        window.addEventListener('resize', checkIfAtBottom);
        
        loadTodayEvents();
        startAutoRefresh();
        checkIfAtBottom();
    </script>
</body>
</html>
'''

@app.route('/login', methods=['GET', 'POST'])
def login():
    """Страница входа"""
    if 'user_id' in session:
        if SESSION_TIMEOUT_MINUTES:
            login_time = session.get('login_time')
            if login_time:
                elapsed = (get_current_time() - login_time).total_seconds() / 60
                if elapsed <= SESSION_TIMEOUT_MINUTES:
                    return redirect(url_for('index'))
        
    error = None
    message = request.args.get('message')
    
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        
        logger.info(f"Login attempt for user: {username}")
        
        if username == USERNAME and password == PASSWORD:
            logger.info(f"Successful login for user: {username}")
            session['user_id'] = username
            session['username'] = username
            session['login_time'] = get_current_time()
            session.permanent = True
            
            if SESSION_TIMEOUT_MINUTES:
                app.permanent_session_lifetime = timedelta(minutes=SESSION_TIMEOUT_MINUTES)
            
            return redirect(url_for('index'))
        else:
            logger.warning(f"Failed login attempt for user: {username}")
            error = 'Неверное имя пользователя или пароль'
    
    return render_template_string(LOGIN_TEMPLATE, error=error, message=message)

@app.route('/logout', methods=['POST'])
def logout():
    """Выход из системы"""
    logger.info(f"User {session.get('username')} logged out")
    session.clear()
    return redirect(url_for('login', message='Вы успешно вышли из системы'))

@app.route('/')
@login_required
def index():
    """Главная страница"""
    username = session.get('username', 'User')
    return render_template_string(HTML_TEMPLATE, username=username)

# API endpoints для веб-интерфейса (с поддержкой мобильного приложения)
@app.route('/api/events/today', methods=['GET'])
@login_required
def get_today_events():
    """Получение событий за сегодня"""
    today = datetime.now().strftime('%Y%m%d')
    events = get_events_for_date(today)
    formatted_events = []
    for event in events:
        formatted_text = format_event_for_display(event['event_date'], event['event_text'])
        formatted_events.append({
            'event_id': event['event_id'],
            'event_date': event['event_date'],
            'event_text': formatted_text
        })
    return jsonify({'events': formatted_events})

@app.route('/api/events/today/count', methods=['GET'])
@login_required
def get_today_events_count():
    """Получение количества событий за сегодня"""
    today = datetime.now().strftime('%Y%m%d')
    events = get_events_for_date(today)
    return jsonify({'count': len(events)})

@app.route('/api/events/date/<date_str>', methods=['GET'])
@login_required
def get_events_by_date(date_str):
    """Получение событий за конкретную дату"""
    date_clean = date_str.replace('-', '')
    events = get_events_for_date(date_clean)
    formatted_events = []
    for event in events:
        formatted_text = format_event_for_display(event['event_date'], event['event_text'])
        formatted_events.append({
            'event_id': event['event_id'],
            'event_date': event['event_date'],
            'event_text': formatted_text
        })
    return jsonify({'events': formatted_events})

@app.route('/api/events/range/<start_date>/<end_date>', methods=['GET'])
@login_required
def get_events_by_range(start_date, end_date):
    """Получение событий за диапазон дат"""
    start_clean = start_date.replace('-', '')
    end_clean = end_date.replace('-', '')
    events = get_events_for_date_range(start_clean, end_clean)
    formatted_events = []
    for event in events:
        formatted_text = format_event_for_display(event['event_date'], event['event_text'])
        formatted_events.append({
            'event_id': event['event_id'],
            'event_date': event['event_date'],
            'event_text': formatted_text
        })
    return jsonify({'events': formatted_events})

# API endpoint для мобильного приложения (без сессий, только API ключи)
@app.route('/getdata/', methods=['GET'])
@api_auth_required
def get_data():
    """API для получения событий с аутентификацией через API ключи"""
    logger.info(f"API request from mobile app - Headers: {dict(request.headers)}")
    
    # Проверяем параметр status=ok для подтверждения отправки
    if request.args.get('status') == 'ok':
        sent_events = load_sent_events()
        logger.info(f"Confirmed {len(sent_events)} events as sent successfully")
        return jsonify({'status': 'ok', 'message': 'Events confirmed'}), 200
    
    # Проверяем параметр date
    date_param = request.args.get('date')
    if date_param:
        if len(date_param) == 8 and date_param.isdigit():
            events = get_events_for_date(date_param)
            if events:
                logger.info(f"Returning {len(events)} events for date {date_param}")
                return jsonify({'events_list_items': events})
            else:
                logger.info(f"No events found for date {date_param}")
                return jsonify({'events_list_items': 'empty'})
        else:
            return jsonify({'error': 'Invalid date format. Use YYYYMMDD'}), 400
    
    # Проверяем параметры date_start и date_end
    date_start = request.args.get('date_start')
    date_end = request.args.get('date_end')
    
    if date_start and date_end:
        if (len(date_start) == 8 and date_start.isdigit() and 
            len(date_end) == 8 and date_end.isdigit()):
            
            events = get_events_for_date_range(date_start, date_end)
            if events:
                logger.info(f"Returning {len(events)} events from {date_start} to {date_end}")
                return jsonify({'events_list_items': events})
            else:
                logger.info(f"No events found from {date_start} to {date_end}")
                return jsonify({'events_list_items': 'empty'})
        else:
            return jsonify({'error': 'Invalid date format. Use YYYYMMDD'}), 400
    
    # Если нет параметров даты, возвращаем новые события
    new_events = get_new_events()
    
    if new_events:
        mark_events_as_sent(new_events)
        logger.info(f"Returning {len(new_events)} new events")
        return jsonify({'events_list_items': new_events})
    else:
        logger.info("No new events available")
        return jsonify({'events_list_items': 'empty'})

# Альтернативный endpoint для мобильного приложения (без count и success)
@app.route('/api/v1/events', methods=['GET'])
@api_auth_required
def get_events_api_v1():
    """API v1 для получения событий (без полей count и success)"""
    logger.info(f"API v1 request from mobile app - Params: {request.args}")
    
    # Получаем параметры
    date_param = request.args.get('date')
    date_start = request.args.get('date_start')
    date_end = request.args.get('date_end')
    status = request.args.get('status')
    
    # Подтверждение отправки
    if status == 'ok':
        sent_events = load_sent_events()
        logger.info(f"Confirmed {len(sent_events)} events")
        return jsonify({'status': 'ok', 'message': 'Events confirmed'}), 200
    
    # Поиск по конкретной дате
    if date_param:
        if len(date_param) == 8 and date_param.isdigit():
            events = get_events_for_date(date_param)
            if events:
                return jsonify({'events_list_items': events})
            else:
                return jsonify({'events_list_items': 'empty'})
        else:
            return jsonify({'error': 'Invalid date format. Use YYYYMMDD'}), 400
    
    # Поиск по диапазону дат
    if date_start and date_end:
        if (len(date_start) == 8 and date_start.isdigit() and 
            len(date_end) == 8 and date_end.isdigit()):
            events = get_events_for_date_range(date_start, date_end)
            if events:
                return jsonify({'events_list_items': events})
            else:
                return jsonify({'events_list_items': 'empty'})
        else:
            return jsonify({'error': 'Invalid date format. Use YYYYMMDD'}), 400
    
    # Возвращаем новые события
    new_events = get_new_events()
    if new_events:
        mark_events_as_sent(new_events)
        return jsonify({'events_list_items': new_events})
    else:
        return jsonify({'events_list_items': 'empty'})

@app.route('/bot<token>/sendMessage', methods=['POST', 'GET'])
def telegram_send_message(token):
    """Эмуляция Telegram API: /bot<TOKEN>/sendMessage"""
    
    if token != BOT_TOKEN:
        logger.warning(f"Invalid bot token attempt: {token}")
        return jsonify({
            'ok': False,
            'error_code': 401,
            'description': 'Unauthorized'
        }), 401
    
    if request.method == 'POST':
        message = request.form.get('text') or request.args.get('text')
        if not message and request.is_json:
            data = request.get_json()
            message = data.get('text') if data else None
    else:
        message = request.args.get('text')
    
    chat_id = request.form.get('chat_id') or request.args.get('chat_id')
    
    logger.info(f"Telegram API request - Token: {token[:10]}..., Chat ID: {chat_id}, Message length: {len(message) if message else 0}")
    
    if not message:
        logger.warning("Telegram API: No message provided")
        return jsonify({
            'ok': False,
            'error_code': 400,
            'description': 'Bad Request: message text is empty'
        }), 400
    
    message_with_timestamp = add_timestamp_to_event(message)
    
    if write_log(message_with_timestamp):
        logger.info("Telegram API: Message successfully logged with timestamp")
        
        response = {
            'ok': True,
            'result': {
                'message_id': int(datetime.now().timestamp()),
                'from': {
                    'id': 123456789,
                    'is_bot': True,
                    'first_name': 'API Logs Bot',
                    'username': 'api_logs_bot'
                },
                'chat': {
                    'id': int(chat_id) if chat_id and chat_id.isdigit() else 123456789,
                    'type': 'private',
                    'first_name': 'User',
                    'username': 'user'
                },
                'date': int(datetime.now().timestamp()),
                'text': message
            }
        }
        return jsonify(response), 200
    else:
        logger.error("Telegram API: Failed to write log")
        return jsonify({
            'ok': False,
            'error_code': 500,
            'description': 'Internal Server Error'
        }), 500

@app.route('/send', methods=['POST'])
def send_alert():
    """Эндпоинт для получения сообщений от send.sh (без авторизации)"""
    message = request.form.get('text') or request.args.get('text')
    
    if not message:
        logger.warning("Send request without message")
        return jsonify({'error': 'No message provided'}), 400
    
    logger.info(f"Received message via /send: {message[:100]}...")
    
    message_with_timestamp = add_timestamp_to_event(message)
    
    if write_log(message_with_timestamp):
        logger.info("Message successfully logged with timestamp")
        return jsonify({'status': 'success', 'message': 'Message logged'}), 200
    else:
        logger.error("Failed to write log")
        return jsonify({'error': 'Failed to write log'}), 500

@app.route('/health', methods=['GET'])
def health_check():
    """Эндпоинт для проверки работоспособности"""
    return jsonify({'status': 'ok', 'timestamp': datetime.now().isoformat()})

def write_log(message):
    """Запись сообщения в лог-файл"""
    today = datetime.now().strftime('%Y%m%d')
    log_file = os.path.join(LOG_DIR, f'api_{today}.log')
    
    try:
        with open(log_file, 'a', encoding='utf-8') as f:
            f.write(message + '\n\n')
        return True
    except Exception as e:
        logger.error(f"Error writing log: {e}")
        return False

# Для WSGI
application = app
