import os
import requests
from bs4 import BeautifulSoup
from docx import Document

class WebNovelScraper:
    def __init__(self):
        self.filter_terms = [ ]

    def get_input(self, prompt, input_type=str, error_msg="Invalid input. Please try again."):
        while True:
            try:
                user_input = input_type(input(prompt))
                return user_input
            except ValueError:
                print(error_msg)

    def get_chapter_input(self):
        urls_chapters = []

        urls_input = self.get_input("Enter URLs of the web novels (separated by commas): ")
        urls = [url.strip() for url in urls_input.split(",")]

        for url in urls:
            if url.lower() == "done":
                break
            
            start_chapters = [1]
            end_chapters_input = self.get_input(f"Ending chapter numbers for {url}: ")
            end_chapters = [int(chapter.strip()) for chapter in end_chapters_input.split(",")]
            urls_chapters.append((url, start_chapters, end_chapters))

        return urls_chapters

    def get_chapter_url(self, url, chapter):
       return f"https://bednovel.com/bednovel/{url}/ch{chapter}"

    def scrape_chapter_info(self, chapter_url):
        try:
            response = requests.get(chapter_url)
            response.raise_for_status()
            soup = BeautifulSoup(response.content, "html.parser")
            chapter_title_element = soup.find("span", class_="chapter")
            if chapter_title_element:
                return chapter_title_element.text.strip()
            else:
                print(f"Error: Failed to find chapter title in {chapter_url}")
        except requests.exceptions.RequestException as e:
            print(f"Error: Failed to fetch URL {chapter_url}. Exception: {e}")
        except Exception as e:
            print(f"Error: An unexpected error occurred while processing {chapter_url}. Exception: {e}")
        return None

    def fetch_paragraphs(self, chapter_url):
        try:
            response = requests.get(chapter_url)
            response.raise_for_status()
            soup = BeautifulSoup(response.content, "html.parser")
            return soup.find_all("p")
        except requests.exceptions.RequestException as e:
            print(f"Error: Failed to fetch URL {chapter_url}. Exception: {e}")
        except Exception as e:
            print(f"Error: An unexpected error occurred while processing {chapter_url}. Exception: {e}")
        return []

    def save_chapter_to_document(self, doc, chapter_title, content):
        doc.add_paragraph(f" \n{chapter_title}")
        for line in content:
            doc.add_paragraph(line)

    def save_chapters_for_ranges(self, folder_name, url, start_chapters, end_chapters):
        script_directory = os.path.dirname(os.path.abspath(__file__))
        base_folder_path = os.path.join(script_directory, folder_name)

        if not os.path.exists(base_folder_path):
            os.makedirs(base_folder_path)

        for i, (start, end) in enumerate(zip(start_chapters, end_chapters), start=1):
            document = Document()
            for chapter in range(start, end + 1):
                chapter_url = self.get_chapter_url(url, chapter)
                chapter_title = self.scrape_chapter_info(chapter_url)
                paragraphs = self.fetch_paragraphs(chapter_url)

                if paragraphs:
                    filtered_paragraphs = [paragraph.text for paragraph in paragraphs
                                           if all(term not in paragraph.text for term in self.filter_terms)]

                    if filtered_paragraphs:
                        self.save_chapter_to_document(document, chapter_title, filtered_paragraphs)
                    else:
                        print(f"Missing content in chapter {chapter}")
                else:
                    print(f"Failed to fetch chapter {chapter}")

            doc_name = f"{url}.docx"
            doc_path = os.path.join(base_folder_path, doc_name)

            try:
                document.save(doc_path)
                print(f"Chapters {start}-{end} saved in {doc_name}.")
            except IOError as e:
                print(f"Error: Failed to save chapters in {doc_name}. Exception: {e}")

    def scrape_web_novel(self):
        urls_chapters = self.get_chapter_input()

        for url, start_chapters, end_chapters in urls_chapters:
            url = url.lower().replace(" ", "-")
            self.save_chapters_for_ranges(url, url, start_chapters, end_chapters)


if __name__ == "__main__":
    scraper = WebNovelScraper()
    scraper.scrape_web_novel()