from bs4 import BeautifulSoup
import re
import time
import os

# Для Selenium
from selenium import webdriver
from selenium.webdriver.firefox.service import Service  # Используем Firefox
from selenium.webdriver.firefox.options import Options   # Опции для Firefox
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, WebDriverException

# --- Функция для перевода названий месяцев (остается без изменений) ---
def translate_month(english_month):
    month_map = {
        'January': 'января', 'February': 'февраля', 'March': 'марта',
        'April': 'апреля', 'May': 'мая', 'June': 'июня',
        'July': 'июля', 'August': 'августа', 'September': 'сентября',
        'October': 'октября', 'November': 'ноября', 'December': 'декабря'
    }
    return month_map.get(english_month, english_month)

# --- Основная функция парсинга (использует драйвер Selenium) ---
def parse_bandcamp_album(driver, url):
    try:
        print(f"Открытие URL с помощью Selenium: {url}")
        driver.get(url)

        # Добавляем явные ожидания для ключевых элементов, чтобы убедиться, что страница полностью загружена
        # Ожидаем появления заголовка альбома (хороший индикатор загрузки страницы)
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CLASS_NAME, "trackTitle"))
        )
        # Небольшая дополнительная задержка для рендеринга других элементов
        time.sleep(1) # Небольшая статическая задержка после загрузки динамического контента

        # Получаем исходный код страницы после выполнения JavaScript
        page_source = driver.page_source
        soup = BeautifulSoup(page_source, 'html.parser')

        # Инициализация словаря данных
        data = {
            'artist': '',
            'album': '',
            'label': '',
            'catalog': '',
            'day': '',
            'month': '',
            'year': '',
            'duration_hh': '00',
            'duration_mm': '00',
            'duration_ss': '00',
            'link': url,
            'album_description': '',
            'album_credits': '',
            'track_list': [],
            'bandcamp_id': ''
        }

        # %album% - из элемента с классом trackTitle
        album_title_tag = soup.find('h2', class_='trackTitle')
        if album_title_tag:
            data['album'] = album_title_tag.get_text(strip=True)

        # %artist% - из тега <a> в элементе с id name-section
        artist_tag = soup.find('div', id='name-section')
        if artist_tag:
            artist_link = artist_tag.find('a')
            if artist_link:
                data['artist'] = artist_link.get_text(strip=True)

        # %day%, %month%, %year% - из элемента с классами tralbumData и tralbum-credits
        release_info_div = soup.find('div', class_='tralbumData tralbum-credits')

        if release_info_div:
            release_text = release_info_div.get_text(strip=True)
            match = re.search(r'released\s+([A-Za-z]+)\s+(\d{1,2}),\s*(\d{4})', release_text)
        if match:
            english_month = match.group(1)
            data['month'] = translate_month(english_month)
            day_int = int(match.group(2))
            data['day'] = f'{day_int:02d}'
            data['year'] = match.group(3)

        # %hh%:%mm%:%ss% - сумма всех числовых значений из элементов с классами time и secondaryText.
        total_seconds = 0
        time_elements = soup.find_all('span', class_=['time', 'secondaryText'])
        for time_elem in time_elements:
            time_str = time_elem.get_text(strip=True)
            time_str = time_str.strip('()')

            # Ensure the string contains a colon, indicating it's likely a time format
            if ':' in time_str:
                parts = time_str.split(':')

                # Check if ALL parts are composed only of digits before attempting conversion
                # This will filter out strings like '00/02' or '10:00/02' where '00/02' is not a digit string
                if all(part.isdigit() for part in parts):
                    if len(parts) == 2: # Format: mm:ss
                        minutes, seconds = int(parts[0]), int(parts[1])
                        total_seconds += minutes * 60 + seconds
                    elif len(parts) == 3: # Format: hh:mm:ss
                        hours, minutes, seconds = int(parts[0]), int(parts[1]), int(parts[2])
                        total_seconds += hours * 3600 + minutes * 60 + seconds
                    # Add an else for cases like 4 parts, though unlikely for durations
                else:
                    # Optional: You can add a print statement here to see what non-numeric strings are being skipped
                    # print(f"Warning: Skipping non-numeric time part found: '{time_str}'")
                    pass # Skip this element if its parts are not purely digits

        hours = total_seconds // 3600
        minutes = (total_seconds % 3600) // 60
        seconds = total_seconds % 60
        data['duration_hh'] = f"{hours:02d}"
        data['duration_mm'] = f"{minutes:02d}"
        data['duration_ss'] = f"{seconds:02d}"

        # %album_description% - из элемента с классами tralbumData и tralbum-about
        album_desc_div = soup.find('div', class_='tralbumData tralbum-about')
        if album_desc_div:
            data['album_description'] = '\n'.join([p.get_text(strip=True) for p in album_desc_div.find_all('p') if p.get_text(strip=True)])
            if not data['album_description']:
                data['album_description'] = album_desc_div.get_text(separator='\n', strip=True)

        # %album_credits% - из элемента с классами tralbumData и tralbum-credits
        credits_divs = soup.find_all('div', class_='tralbumData tralbum-credits')
        if credits_divs:
            credits_texts = []
            for div in credits_divs:
                text = div.get_text(separator='\n', strip=True)
                if not re.search(r'released\s+[A-Za-z]+\s+\d{1,2},\s*\d{4}', text):
                    credits_texts.append(text)
                elif re.search(r'released\s+[A-Za-z]+\s+\d{1,2},\s*\d{4}', text) and len(text.splitlines()) > 1:
                    lines = text.splitlines()
                    for line in lines:
                        if not re.search(r'released\s+[A-Za-z]+\s+\d{1,2},\s*\d{4}', line):
                            credits_texts.append(line)
            data['album_credits'] = '\n'.join(credits_texts).strip()

        # # %track_name%:
        track_elements = soup.find_all('span', class_='track-title')
        data['track_list'] = [f"# {track.get_text(strip=True)}" for track in track_elements]

        # %id% - из <meta name="bc-page-properties" ...>
        meta_tag = soup.find('meta', attrs={'name': 'bc-page-properties'})
        if meta_tag:
            content = meta_tag.get('content', '')
            match = re.search(r'"item_id":(\d+)', content)
            if match:
                data['bandcamp_id'] = match.group(1)
            else:
                path_parts = url.strip('/').split('/')
                if 'album' in path_parts:
                    album_slug_index = path_parts.index('album') + 1
                    if album_slug_index < len(path_parts):
                        data['bandcamp_id'] = path_parts[album_slug_index]

        return data

    except TimeoutException:
        print(f"Истекло время ожидания загрузки страницы для {url}")
        return None
    except WebDriverException as e:
        print(f"Ошибка WebDriver для {url}: {e}")
        # Добавьте конкретные рекомендации для ошибок WebDriver
        print("Это ошибка WebDriver. Убедитесь, что:")
        print("1. Установленный ChromeDriver соответствует версии вашего браузера Chrome.")
        print("2. Путь к ChromeDriver в скрипте указан правильно.")
        print("3. Браузер Chrome не блокируется фаерволом/антивирусом или другим ПО.")
        return None
    except Exception as e:
        print(f"Произошла непредвиденная ошибка при парсинге {url}: {e}")
        return None

# --- Функция для форматирования вывода (остается без изменений) ---
def format_output(data):
    if not data:
        return "Failed to parse album data."

    duration_str = f"{data['duration_hh']}:{data['duration_mm']}:{data['duration_ss']}"
    if data['duration_hh'] == '00' and data['duration_mm'] == '00' and data['duration_ss'] == '00':
        duration_str = ''

    template = f"""{{{{Альбом
|Обложка = {data['artist']} - {data['album']}.jpg
|Исполнитель = {data['artist']}
|Название = {data['album']}
|Лейбл = {data['label']}
|Каталог = {data['catalog']}
|День и месяц релиза = {data['day']} {data['month']}
|Год релиза = {data['year']}
|Продолжительность = {duration_str}
|Формат = 
}}}}
==Ссылки==
* {data['link']}

==Об альбоме==
{data['album_description']}

==Трек-лист==
"""
    template += "\n".join(data['track_list'])

    if data['bandcamp_id']:
        template += f"""

==Дополнительная информация==
{data['album_credits']}

==Плеер==
{{{{bandcamp|album|{data['bandcamp_id']}}}}}"""
    else:
        template += """

==Плеер==
(ID Bandcamp не найден)"""

    return template

# --- Основной блок выполнения скрипта ---
if __name__ == "__main__":
    links_file = "links.txt"
    output_dir = "bandcamp_output"

    os.makedirs(output_dir, exist_ok=True)

 # --- Настройка Selenium для Firefox ---
    #geckodriver_path = '/usr/local/bin/geckodriver'  # Путь к geckodriver
    # Для локального запуска можно использовать:
    geckodriver_path = 'geckodriver'

    firefox_options = Options()
    # Раскомментируйте для безголового режима
    firefox_options.add_argument("--headless")
    firefox_options.add_argument("--no-sandbox")
    firefox_options.add_argument("--disable-dev-shm-usage")
    firefox_options.add_argument("--window-size=1920,1080")
    # Добавляем User-Agent (Firefox по умолчанию)
    #firefox_options.set_preference("general.useragent.override", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Firefox/123.0")

    driver = None
    try:
        service = Service(geckodriver_path)
        driver = webdriver.Firefox(service=service, options=firefox_options)

        try:
            with open(links_file, 'r', encoding='utf-8') as f:
                links = [line.strip() for line in f if line.strip()]
        except FileNotFoundError:
            print(f"Ошибка: Файл '{links_file}' не найден. Пожалуйста, создайте его и добавьте ссылки.")
            links = []

        for link in links:
            print(f"\nОбработка ссылки: {link}")
            album_data = parse_bandcamp_album(driver, link) # Передаем объект драйвера в функцию парсинга

            if album_data:
                output_content = format_output(album_data)
                filename_base = f"{album_data['artist']} - {album_data['album']}"
                sanitized_filename = re.sub(r'[\\/:*?"<>|]', '', filename_base)
                output_filename = os.path.join(output_dir, f"{sanitized_filename}.txt")

                try:
                    with open(output_filename, 'w', encoding='utf-8') as outfile:
                        outfile.write(output_content)
                    print(f"Сохранено в: {output_filename}")
                except Exception as e:
                    print(f"Ошибка при сохранении файла {output_filename}: {e}")
            else:
                print(f"Не удалось получить данные для ссылки: {link}")
            print("-" * 50)

    except WebDriverException as e:
        print(f"\nКРИТИЧЕСКАЯ ОШИБКА: Проблема с WebDriver или браузером. Убедитесь, что:")
        print(f"1. Установлен Firefox")
        print(f"2. Скачан geckodriver")
        print(f"3. Версия geckodriver соответствует версии браузера.")
        print(f"4. Путь '{geckodriver_path}' в скрипте указан верно или geckodriver находится в PATH.")
        print(f"Подробности ошибки: {e}")
    finally:
        if driver:
            driver.quit() # Убедитесь, что браузер закрыт даже в случае ошибки
