import requests
from bs4 import BeautifulSoup
from pprint import pprint
import re


def parse_html(url=str):
    """
    Фунция принимает строку URL, выполняет запрос.
    Создает и возращает объект BeautifulSoup(HTML).
    """
    # Запрос страницы
    response = requests.get(url)
    # Проверка статуса в ответе на запрос
    if not(200 <= response.status_code <= 299):
        # Повторный запрос 
        response = requests.get(url)
        print("Ошибка при запросе: ", response.status_code)
        return response.status_code
    # Создание обьекта BeautifulSoup(HTML страница)
    soup = BeautifulSoup(response.text, 'html.parser')
    return soup

def parse_date_report(url=str):
    """
    Функия ожидает list из URL ввида:
        url = https://formats.saby.ru/report/fns/128513
    Заходит по URL, запоминает дату.
    Возвращает две строки ввида:
        'date =  01.07.22'
        'id_date = 5.01' 
    """
    # HTML report
    soup = parse_html(url)
    # Если не удалось отправить запрос, ворзвращаем URL и код ошибки.
    # Они будут занесы в файл.
    if soup == int:
        return url, soup
    # Поиск в HTML строки ввида: 'Действующий формат (с 10.01.23) 5.01'
    div_element = soup.find('div', class_='controls-Dropdown__text')
    # Извлекаем текст из элемента
    text = div_element.get_text()
    # Парсим нужные данные
    # Уловия ловит: text = 'Действующий формат 02-04-2025 _2025_001'
    if '_' in text:
        regex = r'\w+\s\w+\s(\S+) (\S+)'
        date, id_date = re.search(regex, text).groups()
        return date, id_date
    # Все остальные
    else:
        regex = r'(\d{2}\D\d{2}\D\d{2})(?:(?:.+)?\))? #?(\d+(?:\D\d+)?)'
        date, id_date = re.search(regex, text).groups()
        return date, id_date

def parse_reports(soup=BeautifulSoup, 
                  report_title = str, 
                  url_formats = str, 
                  name_title = str):
    """       
    Достаются все необходимые данные, возвращаются в ввиде словаря:
        {106538: ('fns', 'НД по косвенным налогам', '01.08.23', '5.04')}
    """

    result_dict_data = {}
    # Перебарает все URL, ищутся по тегу 'a'
    for link in soup.find_all('a'):
        # Ищет по тегу: href 
        href = link.get('href')
        if f'{report_title}/' in href:
            # id report
            id = href.rstrip('/').split('/')[-1]
            #URL report 
            url_report = f'{url_formats}{href}'
            link = soup.find('a', href=href)
            # Name report
            span = link.find('span', class_="ProxySbisRu__registry-BrowserItem_typeName")
            # Данные получены из url после парсинга
            date, id_date = parse_date_report(url_report)
            # Добавление всех данных в итоговый словарь            
            result_dict_data.update({id: (name_title, span.text, date, id_date)})

    return result_dict_data

def write_report_data(filename, dict_name = dict, name_title = str):
    """
    Сохраняем запись, каждая запись с новой строки:
    'ключ: значение'
    'ключ: значение'
    ...
    """
    #Блок для красивого форлмения файла

    # Вычисляем количество подчёркиваний слева и справа
    def center_text():
        """
        Функия парсит сколько нужно подчеркивания,
        что бы центролизовать текст в строке с этими подчеркиваниями
        Возвращает две строки одна для начало блока записей тайтал, вторая конца блока.
        """
        start_str = f'START_{name_title}'
        end_str = f'END_{name_title}'
        dash = 100
        list_result = []
        # сначал вернеться dash_start, потом end_start.
        for text in start_str, end_str:
            remaining_space = dash - len(text)
            left = remaining_space // 2
            right = remaining_space - left  # Чтобы учесть нечётную разницу
            list_result.append('_' * left + text + '_' * right)
        return list_result[:2]   
    dash_start, dash_end = center_text()

    #Конец блока
    #Запись в файл с красивым офрмление в виде нижнего подчеркивания 
    with open(filename, 'a', encoding='utf-8') as f:
        f.write(f'\n{dash_start}\n')
        for key, value in dict_name.items():
            str_k_v = f'{key}: {value}\n'
            f.write(str_k_v)
        f.write(f'{dash_end}\n')

def search_title():
    """
    Функция ищет все тайтлы,
    возвращает лист сотоящий из:
        ['/report/fns', ...]
    """
    # url по которому в котором будет происходить поиск,
    # Используется только в этой функции
    url_format_report = 'https://formats.saby.ru/report'
    # Объект HTML
    html = parse_html(url_format_report)
    # Если придет int(он же respons.status_code))
    if html == int:
        error_message = f'Ошибка при запросе {url_format_report}: {html}'
        raise Exception(error_message)
    # Лист в который будут заноситься тайтлы
    list_reports = []
    # Перебераем все URL
    # Ищем все тэги 'a'
    for link in html.find_all('a'):
        # Ищем по тегу: href 
        href = link.get('href')
        #Проверям что href содержит: /report/{title}
        if re.search(r'\/report\/(\w+)$', href):
                list_reports.append(href)
    return list_reports

# Имя файла в который будет записан результат кода
filename_save = 'ReportData.txt'
# Удаляем старые записи, что бы записать актульные 
with open(filename_save, 'w') as f:
    # Файл перезаписывается и становится пустым
    f.write('')
# Лист имеет вид: ['/report/fns', '/report/sfr'...]
list_title = search_title()
# Используется два раза, создал отдельную переменную 
URL_FORMATS = 'https://formats.saby.ru'
"""
Цикл про бегается по каждому тайтлу. 
Для всех записей(reports) выполняется запрос HTML страницы, 
которая парситься в объект BeautifulSoup(HTML страница).
Из это обьекта достаются не боходимые данные,
которые записываются в текстовый файл.
"""
#report_title = '/report/fns'
for report_title in list_title:
    # Получаем имя тайтла через парсинг 
    name_title = report_title.rstrip('/').split('/')[-1]
    # URL на конкретный title 
    url_title = f'{URL_FORMATS}{report_title}'
    # Объект HTML, конкретного title
    soup = parse_html(url_title)
    # Словарь с нужными данными
    dict_result = parse_reports(soup, report_title, URL_FORMATS, name_title)
    # Запись данных в текстовый файл
    write_report_data(filename_save, dict_result, name_title)




