# pylint: disable=missing-module-docstring,missing-class-docstring,invalid-name,bare-except,consider-using-f-string,unused-variable,broad-exception-raised,inconsistent-return-statements,raise-missing-from,no-else-return,too-many-arguments,singleton-comparison
# ruff: noqa: E722,E712
# type: ignore
import urllib

import feedparser  # type: ignore
import requests
from bs4 import BeautifulSoup
from dateparser import parse as parse_date


class GoogleNews:
    def __init__(self, lang="en", country="US", session=None):
        self.lang = lang.lower()
        self.country = country.upper()
        self.BASE_URL = "https://news.google.com/rss"
        self._session = session if session is not None else requests.Session()
        self.timeout = 30.0

    def __top_news_parser(self, text):
        """Return subarticles from the main and topic feeds"""
        try:
            bs4_html = BeautifulSoup(text, "lxml")
            # find all li tags
            lis = bs4_html.find_all("li")
            sub_articles = []
            for li in lis:
                try:
                    sub_articles.append(
                        {
                            "url": li.a["href"],
                            "title": li.a.text,
                            "publisher": li.font.text,
                        }
                    )
                except:
                    pass
            return sub_articles
        except:
            return text

    def __ceid(self):
        """Compile correct country-lang parameters for Google News RSS URL"""
        return "?ceid={}:{}&hl={}&gl={}".format(
            self.country, self.lang, self.lang, self.country
        )

    def __add_sub_articles(self, entries):
        for i, val in enumerate(entries):
            if "summary" in entries[i].keys():
                entries[i]["sub_articles"] = self.__top_news_parser(
                    entries[i]["summary"]
                )
            else:
                entries[i]["sub_articles"] = None
        return entries

    def __scaping_bee_request(self, api_key, url):
        response = self._session.get(
            url="https://app.scrapingbee.com/api/v1/",
            params={"api_key": api_key, "url": url, "render_js": "false"},
            timeout=self.timeout,
        )
        if response.status_code == 200:
            return response
        if response.status_code != 200:
            raise Exception(
                "ScrapingBee status_code: "
                + str(response.status_code)
                + " "
                + response.text
            )

    def __parse_feed(self, feed_url, proxies=None, scraping_bee=None):
        if scraping_bee and proxies:
            raise Exception("Pick either ScrapingBee or proxies. Not both!")

        if proxies:
            r = self._session.get(feed_url, proxies=proxies, timeout=self.timeout)
        elif scraping_bee:
            r = self.__scaping_bee_request(url=feed_url, api_key=scraping_bee)
        else:
            r = self._session.get(feed_url, timeout=self.timeout)

        if "https://news.google.com/rss/unsupported" in r.url:  # pyright: ignore
            raise Exception("This feed is not available")

        d = feedparser.parse(r.text)

        return dict((k, d[k]) for k in ("feed", "entries"))

    def __search_helper(self, query):
        return urllib.parse.quote_plus(query)

    def __from_to_helper(self, validate=None):
        try:
            validate = parse_date(validate).strftime("%Y-%m-%d")
            return str(validate)
        except:
            raise Exception("Could not parse your date")

    def top_news(self, proxies=None, scraping_bee=None):
        """Return a list of all articles from the main page of Google News
        given a country and a language"""
        d = self.__parse_feed(
            self.BASE_URL + self.__ceid(), proxies=proxies, scraping_bee=scraping_bee
        )
        d["entries"] = self.__add_sub_articles(d["entries"])
        return d

    def topic_headlines(self, topic: str, proxies=None, scraping_bee=None):
        """Return a list of all articles from the topic page of Google News
        given a country and a language"""
        # topic = topic.upper()
        if topic.upper() in [
            "WORLD",
            "NATION",
            "BUSINESS",
            "TECHNOLOGY",
            "ENTERTAINMENT",
            "SCIENCE",
            "SPORTS",
            "HEALTH",
        ]:
            d = self.__parse_feed(
                self.BASE_URL
                + "/headlines/section/topic/{}".format(topic.upper())
                + self.__ceid(),
                proxies=proxies,
                scraping_bee=scraping_bee,
            )

        else:
            d = self.__parse_feed(
                self.BASE_URL + "/topics/{}".format(topic) + self.__ceid(),
                proxies=proxies,
                scraping_bee=scraping_bee,
            )

        d["entries"] = self.__add_sub_articles(d["entries"])
        if len(d["entries"]) > 0:
            return d
        else:
            raise Exception("unsupported topic")

    def geo_headlines(self, geo: str, proxies=None, scraping_bee=None):
        """Return a list of all articles about a specific geolocation
        given a country and a language"""
        d = self.__parse_feed(
            self.BASE_URL + "/headlines/section/geo/{}".format(geo) + self.__ceid(),
            proxies=proxies,
            scraping_bee=scraping_bee,
        )

        d["entries"] = self.__add_sub_articles(d["entries"])
        return d

    def search(
        self,
        query: str,
        helper=True,
        when=None,
        from_=None,
        to_=None,
        proxies=None,
        scraping_bee=None,
    ):
        """
        Return a list of all articles given a full-text search parameter,
        a country and a language

        :param bool helper: When True helps with URL quoting
        :param str when: Sets a time range for the artiles that can be found
        """

        if when:
            query += " when:" + when

        if from_ and not when:
            from_ = self.__from_to_helper(validate=from_)
            query += " after:" + from_

        if to_ and not when:
            to_ = self.__from_to_helper(validate=to_)
            query += " before:" + to_

        if helper == True:
            query = self.__search_helper(query)

        search_ceid = self.__ceid()
        search_ceid = search_ceid.replace("?", "&")

        d = self.__parse_feed(
            self.BASE_URL + "/search?q={}".format(query) + search_ceid,
            proxies=proxies,
            scraping_bee=scraping_bee,
        )

        d["entries"] = self.__add_sub_articles(d["entries"])
        return d
