#!/usr/bin/env python3
"""Скрипт для сдвига дат в CSV файле MQL5 на указанное количество недель"""

import os
import sys
import glob
from datetime import datetime, timedelta

# Определяем входной файл
if len(sys.argv) > 1:
    input_file = sys.argv[1]
else:
    # Ищем CSV файлы в текущей директории (исключая уже обработанные)
    csv_files = [f for f in glob.glob("*.csv") if not f.endswith("_shifted.csv")]
    if len(csv_files) == 0:
        print("Ошибка: CSV файлы не найдены в текущей директории")
        sys.exit(1)
    elif len(csv_files) == 1:
        input_file = csv_files[0]
        print(f"Найден файл: {input_file}")
    else:
        print("Найдено несколько CSV файлов. Выберите файл:")
        for i, f in enumerate(csv_files, 1):
            print(f"  [{i}] {f}")
        while True:
            try:
                selection = input(f"Введите номер (1-{len(csv_files)}): ")
                selected_index = int(selection) - 1
                if 0 <= selected_index < len(csv_files):
                    input_file = csv_files[selected_index]
                    print(f"Выбран: {input_file}")
                    break
                else:
                    print(f"Неверный выбор. Введите число от 1 до {len(csv_files)}")
            except ValueError:
                print("Пожалуйста, введите число")
            except KeyboardInterrupt:
                print("\nОтменено пользователем")
                sys.exit(1)

# Проверяем существование файла
if not os.path.exists(input_file):
    print(f"Ошибка: Файл '{input_file}' не найден")
    sys.exit(1)

# Запрашиваем количество недель для сдвига
default_weeks = 52  # Примерно год
print(f"\nНа сколько недель сдвинуть даты? (по умолчанию: {default_weeks})")
print("Можно указать отрицательное значение для сдвига назад (например: -52)")
while True:
    try:
        weeks_input = input(f"Введите количество недель [{default_weeks}]: ").strip()
        if not weeks_input:
            weeks_shift = default_weeks
        else:
            weeks_shift = int(weeks_input)
            if weeks_shift == 0:
                print("Количество недель не может быть нулем")
                continue
        break
    except ValueError:
        print("Пожалуйста, введите целое число")
    except KeyboardInterrupt:
        print("\nОтменено пользователем")
        sys.exit(1)

direction = "вперед" if weeks_shift > 0 else "назад"
print(f"Будет выполнено сдвиг {direction} на {abs(weeks_shift)} недель ({abs(weeks_shift) * 7} дней)")

# Формируем имя выходного файла
base_name = os.path.splitext(input_file)[0]
output_file = f"{base_name}_shifted.csv"

# Получаем размер файла для прогресса
file_size = os.path.getsize(input_file)
file_size_mb = file_size / (1024 * 1024)

print(f"Входной файл: {input_file}")
print(f"Размер файла: {file_size_mb:.2f} MB")
print(f"Выходной файл: {output_file}")
print("Обработка...")

# Используем буферизацию для больших файлов
BUFFER_SIZE = 1024 * 1024  # 1MB буфер

with open(input_file, 'r', encoding='utf-8', buffering=BUFFER_SIZE) as f_in, \
     open(output_file, 'w', encoding='utf-8', buffering=BUFFER_SIZE) as f_out:
    
    # Заголовок
    header = f_in.readline()
    f_out.write(header)
    
    # Определяем тип файла по заголовку
    header_upper = header.upper()
    if '<OPEN>' in header_upper and '<HIGH>' in header_upper:
        file_type = "Bars (свечи)"
    elif '<BID>' in header_upper and '<ASK>' in header_upper:
        file_type = "Ticks (тики)"
    else:
        file_type = "Unknown (неизвестный)"
    
    print(f"Тип файла: {file_type}")
    
    processed = 0
    bytes_read = len(header.encode('utf-8'))
    
    # Обработка данных
    for line in f_in:
        # Сохраняем оригинальное окончание строки
        line_ending = ''
        if line.endswith('\r\n'):
            line_ending = '\r\n'
            line = line[:-2]
        elif line.endswith('\n'):
            line_ending = '\n'
            line = line[:-1]
        elif line.endswith('\r'):
            line_ending = '\r'
            line = line[:-1]
        
        # Быстрая проверка и обработка даты
        # Формат даты одинаковый для обоих типов: YYYY.MM.DD
        if line and len(line) > 0 and line[0].isdigit():
            # Находим позицию первого табулятора (разделитель между датой и временем)
            tab_pos = line.find('\t')
            if tab_pos >= 10:  # Минимум YYYY.MM.DD (10 символов)
                try:
                    # Парсим дату
                    date_str = line[:tab_pos]
                    dt = datetime.strptime(date_str, "%Y.%m.%d")
                    # Добавляем недели
                    dt_new = dt + timedelta(weeks=weeks_shift)
                    # Формируем новую строку с обновленной датой
                    new_date_str = dt_new.strftime("%Y.%m.%d")
                    line = new_date_str + line[tab_pos:]
                except ValueError:
                    # Если не удалось распарсить дату, пропускаем строку без изменений
                    pass
        
        # Записываем строку с оригинальным окончанием
        f_out.write(line + line_ending)
        
        processed += 1
        bytes_read += len((line + line_ending).encode('utf-8'))
        
        # Обновляем прогресс каждые 10000 строк
        if processed % 10000 == 0:
            percent = min(100, int(bytes_read / file_size * 100))
            bar_length = 50
            filled = int(bar_length * bytes_read / file_size)
            bar = '█' * filled + '░' * (bar_length - filled)
            mb_processed = bytes_read / (1024 * 1024)
            sys.stdout.write(f'\r[{bar}] {percent}% ({mb_processed:.1f}/{file_size_mb:.1f} MB, {processed:,} строк)')
            sys.stdout.flush()

# Финальный прогресс
percent = 100
bar = '█' * 50
mb_processed = file_size / (1024 * 1024)
sys.stdout.write(f'\r[{bar}] {percent}% ({mb_processed:.1f}/{file_size_mb:.1f} MB, {processed:,} строк)')
sys.stdout.flush()

print(f"\nГотово! Результат сохранен в {output_file}")
print(f"Обработано строк: {processed:,}")
