import os
import time
import asyncio
import aiosqlite
from quart import Quart, render_template, request, send_from_directory, Response
from datetime import datetime
from babel.dates import format_datetime
<<<<<<< HEAD
from urllib.parse import quote
=======
>>>>>>> 9cc0929a09596abeb93ee7f2711527fb5da25f7a



app = Quart(__name__, template_folder='frontend', static_folder='frontend')

DB_PATH = 'maps.db'
DATA = "/data"

GAME_MODES = {
    "Classic": "Классический",
    "Deathmatch": "Бой насмерть",
    "Demolition": "Уничтожение объекта",
    "Armsrace": "Гонка вооружений",
    "Custom": "Пользовательский",
    "Training": "Обучение",
    "Co-op Strike": "Совместный налёт",
    "Wingman": "Напарники",
    "Flying Scoutsman": "Перелётные снайперы"
}

last_download_times = {}
DOWNLOAD_COOLDOWN = 10

async def get_maps(page=1, per_page=30):
    print(f"Запрос карт на странице {page}, с {per_page} картами на странице.")
    async with aiosqlite.connect(DB_PATH) as conn:
        cursor = await conn.cursor()

        offset = (page - 1) * per_page

        await cursor.execute('''
            SELECT FilePath, Title, COALESCE(Stars, 0) as Stars, Description
            FROM maps
            ORDER BY DateTime DESC
            LIMIT ? OFFSET ?
        ''', (per_page, offset))

        maps = await cursor.fetchall()

    print(f"Получено {len(maps)} карт на странице {page}.")
    return maps

def get_image_path(filepath):
<<<<<<< HEAD
    print(f"Получение пути изображения для файла: {filepath}")
    image_path = os.path.join(DATA, filepath)
    if not os.path.exists(image_path):
        print("Изображение не найдено, возвращаем дефолтное.")
=======
    image_path = os.path.join(DATA, filepath)
    if not os.path.exists(image_path):
>>>>>>> 9cc0929a09596abeb93ee7f2711527fb5da25f7a
        return "/images/image.jpg"
    return f"/images/{filepath.split('/')[0]}/{filepath.split('/')[1]}/{filepath.split('/')[1]}.jpg"

def get_star_image(stars):
    print(f"Получение изображения для {stars} звезд.")
    if stars is None or stars == 0:
        return "/stars/0-star.png"
    return f"/stars/{stars}-star.png"

@app.route('/images/<path:filename>')
async def serve_image(filename):
<<<<<<< HEAD
    print(f"Запрос изображения с именем: {filename}")
    image_path = os.path.join(DATA, filename)
    if os.path.exists(image_path):
        print(f"Изображение {filename} найдено и отправляется.")
=======
    image_path = os.path.join(DATA, filename)
    if os.path.exists(image_path):
>>>>>>> 9cc0929a09596abeb93ee7f2711527fb5da25f7a
        return await send_from_directory(DATA, filename)
    else:
        default_image_path = os.path.join(DATA, 'image.jpg')
        if os.path.exists(default_image_path):
<<<<<<< HEAD
            print("Изображение не найдено, отправляем дефолтное.")
            return await send_from_directory(DATA, 'image.jpg')
        print("Не найдено ни одного изображения.")
=======
            return await send_from_directory(DATA, 'image.jpg')
>>>>>>> 9cc0929a09596abeb93ee7f2711527fb5da25f7a
        return "Default image not found", 404

@app.route('/stars/<filename>')
async def serve_star_image(filename):
<<<<<<< HEAD
    print(f"Запрос изображения звезды: {filename}")
    stars = os.path.join(DATA, 'stars')
    star_path = os.path.join(stars, filename)
    if os.path.exists(star_path):
        print(f"Звезда {filename} найдена и отправляется.")
=======
    stars = os.path.join(DATA, 'stars')
    star_path = os.path.join(stars, filename)
    if os.path.exists(star_path):
>>>>>>> 9cc0929a09596abeb93ee7f2711527fb5da25f7a
        return await send_from_directory(stars, filename)
    else:
        print("Изображение звезды не найдено.")
        return "Star image not found", 404

@app.route('/download_bsp')
async def download_bsp():
    user_ip = request.remote_addr
    print(f"Запрос на скачивание от IP: {user_ip}")

    current_time = time.time()
    last_time = last_download_times.get(user_ip, 0)

    if current_time - last_time < DOWNLOAD_COOLDOWN:
        wait_time = DOWNLOAD_COOLDOWN - (current_time - last_time)
        print(f"Пользователь должен подождать {int(wait_time)} секунд до следующего скачивания.")
        return f"Please wait {int(wait_time)} seconds before downloading again.", 429

    last_download_times[user_ip] = current_time
    print("Тайм-аут скачивания обновлен.")

    image_path = request.args.get('image_path')
    if not image_path:
        print("Не указан путь к изображению.")
        return "No image path provided", 400

    image_folder = os.path.dirname(image_path.replace("/images/", ""))
    bsp_filename = None

    for file in os.listdir(os.path.join(DATA, image_folder)):
        if file.endswith('.bsp'):
            bsp_filename = file
            break

    if not bsp_filename:
        print("Не найден .bsp файл в той же директории.")
        return "No .bsp file found in the same directory", 404

    file_path = os.path.join(DATA, image_folder, bsp_filename)
<<<<<<< HEAD
    print(f"Найден файл для скачивания: {file_path}")
=======
>>>>>>> 9cc0929a09596abeb93ee7f2711527fb5da25f7a

    SPEED_LIMIT = 60 * 1024 * 1024 // 8

    async def file_stream():
        print("Начало передачи файла по частям.")
        with open(file_path, 'rb') as f:
            while chunk := f.read(SPEED_LIMIT):
                yield chunk
                await asyncio.sleep(1)

    headers = {
        "Content-Disposition": f"attachment; filename={bsp_filename}"
    }
    return Response(file_stream(), headers=headers, content_type='application/octet-stream')

@app.route('/main')
async def main_page():
    print("Запрос страницы карты с параметрами:", request.args)
    image_url = request.args.get('image_url', 'default_image.jpg')
    map_title = request.args.get('map_title', 'Default Map Title')

    async with aiosqlite.connect(DB_PATH) as conn:
        cursor = await conn.cursor()
        await cursor.execute('''
            SELECT GameMode, Tags, FilePath, DateTime, YoutubeLink, Description
            FROM maps
            WHERE Title = ?
        ''', (map_title,))
        row = await cursor.fetchone()

    game_mode = row[0] if row else None
    tags = row[1] if row else None
    file_path = row[2] if row else None
    date_time = row[3] if row else None
    youtube_link = row[4] if row else None
    description = row[5] if row else "Нет описания"

    if date_time:
        dt = datetime.fromisoformat(date_time)
        added_time = format_datetime(dt, format='d MMM y г., HH:mm', locale='ru_RU')
    else:
        added_time = 'Не найдено'

    if game_mode:
        game_modes = game_mode.split(', ')
        game_modes = [GAME_MODES.get(mode, mode) for mode in game_modes]
        game_mode = ', '.join(game_modes)
    else:
        game_mode = 'Не найден'

    if tags:
        tags_list = tags.split(', ')
        tags_list = [GAME_MODES.get(tag, tag) for tag in tags_list]
        tags = ', '.join(tags_list)
    else:
        tags = 'Не найдено'

    if file_path:
        file_size = os.path.getsize(os.path.join(DATA, file_path))
        file_size_mb = file_size / (1024 * 1024)
        file_size_display = f"{file_size_mb:.2f} MB"
    else:
        file_size_display = 'Не найден'

    print(f"Отправка страницы карты {map_title} с данными:")
    print(f"Игра: {game_mode}, Теги: {tags}, Размер файла: {file_size_display}, Время добавления: {added_time}")

    return await render_template(
        'main.html',
        image_url=image_url,
        map_title=map_title,
        game_mode=game_mode,
        tags=tags,
        file_size=file_size_display,
        added_time=added_time,
        youtube_link=youtube_link,
        description=description
    )


@app.route('/')
async def index():
    print("Запрос главной страницы с параметрами фильтрации:", request.args)
    page = int(request.args.get('page', 1))
    selected_game_modes = request.args.getlist('game_modes')
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')
    search_title = request.args.get('search_title')
    selected_stars = request.args.get('stars')

    maps_data = await get_maps_filtered(page, selected_game_modes, start_date, end_date, search_title, selected_stars)

    async with aiosqlite.connect(DB_PATH) as conn:
        cursor = await conn.cursor()

        query = 'SELECT COUNT(*) FROM maps WHERE 1=1'
        params = []

        if selected_game_modes:
            placeholders = ', '.join('?' for _ in selected_game_modes)
            query += f' AND GameMode IN ({placeholders})'
            params.extend(selected_game_modes)

        if start_date:
            query += ' AND DateTime >= ?'
            params.append(start_date)
        if end_date:
            query += ' AND DateTime <= ?'
            params.append(end_date)

        if search_title:
            query += ' AND Title LIKE ?'
            params.append(f'%{search_title}%')

        if selected_stars:
            query += ' AND Stars = ?'
            params.append(selected_stars)

        await cursor.execute(query, params)
        total_maps = await cursor.fetchone()

    total_maps = total_maps[0]
    per_page = 30
    total_pages = (total_maps + per_page - 1) // per_page

    filters = '&'.join(
        [f'game_modes={mode}' for mode in selected_game_modes] +
        ([f'start_date={start_date}'] if start_date else []) +
        ([f'end_date={end_date}'] if end_date else []) +
        ([f'search_title={search_title}'] if search_title else []) +
        ([f'stars={selected_stars}'] if selected_stars else [])
    )

    print(f"Общее количество карт: {total_maps}, Страниц: {total_pages}")
    return await render_template(
        'workshop.html',
        maps_data=maps_data,
        page=page,
        total_pages=total_pages,
        get_image_path=get_image_path,
        get_star_image=get_star_image,
        selected_game_modes=selected_game_modes,
        filters=filters,
        selected_stars=selected_stars
    )

async def get_maps_filtered(page=1, selected_game_modes=None, start_date=None, end_date=None, search_title=None, selected_stars=None):
    print(f"Фильтрация карт с параметрами: {locals()}")
    async with aiosqlite.connect(DB_PATH) as conn:
        cursor = await conn.cursor()

        offset = (page - 1) * 30
        query = '''
            SELECT FilePath, Title, COALESCE(Stars, 0) as Stars, Description
            FROM maps
            WHERE 1=1
        '''
        params = []

        if selected_stars:
            query += ' AND Stars = ?'
            params.append(selected_stars)

        if search_title:
            query += ' AND Title LIKE ?'
            params.append(f'%{search_title}%')

        if selected_game_modes:
            query += ' AND GameMode IN ({})'.format(','.join('?' for _ in selected_game_modes))
            params.extend(selected_game_modes)

        if start_date:
            query += ' AND DateTime >= ?'
            params.append(start_date)
        if end_date:
            query += ' AND DateTime <= ?'
            params.append(end_date)

        query += ' ORDER BY DateTime DESC LIMIT ? OFFSET ?'
        params.extend([30, offset])

        await cursor.execute(query, params)
        maps = await cursor.fetchall()

    print(f"Найдено {len(maps)} карт после фильтрации.")
    return maps
    
    
@app.route('/favicon.ico')
async def favicon():
    return await send_from_directory(os.getcwd(), 'favicon.ico')


@app.route('/sitemap.xml')
async def sitemap():
    domain = "https://csgoworkshop.ru"
    async with aiosqlite.connect(DB_PATH) as conn:
        cursor = await conn.cursor()

        # Получаем список всех карт
        await cursor.execute('SELECT Title FROM maps')
        maps = await cursor.fetchall()

    # Создаем базовые URL для sitemap
    urls = [
        f"{domain}/",
        f"{domain}/main",
    ]

    # Добавляем URL-адреса для всех карт
    for map_title, in maps:
        encoded_title = quote(map_title)
        urls.append(f"{domain}/main?map_title={encoded_title}")

    # Генерируем XML
    sitemap_xml = '<?xml version="1.0" encoding="UTF-8"?>\n'
    sitemap_xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'

    for url in urls:
        sitemap_xml += "  <url>\n"
        sitemap_xml += f"    <loc>{url}</loc>\n"
        sitemap_xml += f"    <lastmod>{datetime.utcnow().strftime('%Y-%m-%d')}</lastmod>\n"
        sitemap_xml += "    <changefreq>weekly</changefreq>\n"
        sitemap_xml += "    <priority>0.8</priority>\n"
        sitemap_xml += "  </url>\n"

    sitemap_xml += '</urlset>'

    return Response(sitemap_xml, content_type='application/xml')



@app.route('/robots.txt')
async def robots_txt():
    content = """
    User-agent: *
    Disallow:
    """
    return Response(content, content_type='text/plain')


if __name__ == '__main__':
<<<<<<< HEAD
    print("Запуск приложения...")
    import hypercorn.asyncio
    from hypercorn.config import Config

    config = Config()
    config.bind = ["0.0.0.0:5000"]
    hypercorn.asyncio.run(app, config)
=======
    import hypercorn.asyncio
    from hypercorn.config import Config
    config = Config()
    config.bind = ["0.0.0.0:5000"]
    hypercorn.asyncio.run(app, config)
>>>>>>> 9cc0929a09596abeb93ee7f2711527fb5da25f7a
