import json
import pathlib

import click
import praw
from prawcore import OAuthException
from selenium.common.exceptions import NoSuchElementException

from crunchy_bot.config.json_config_parser import JsonConfigParser
from crunchy_bot.fetcher.guest_pass_fetcher import GuestPassFetcher
from crunchy_bot.logging.click_logger import ClickLogger
from crunchy_bot.publisher.reddit_publisher import RedditPublisher


class Context(object):
    def __init__(self):
        self.logger = ClickLogger()


@click.group()
@click.pass_context
def cli(context):
    context.obj = Context()


@cli.command()
@click.pass_obj
def init(context):
    crunchy_username = click.prompt("Crunchyroll Username")
    crunchy_password = click.prompt("Crunchyroll Password", hide_input=True)
    reddit_client_id = click.prompt("Reddit Client ID")
    reddit_client_secret = click.prompt("Reddit Client Secret", hide_input=True)
    reddit_username = click.prompt("Reddit Username")
    reddit_user_agent = click.prompt("Reddit User Agent", default=f"CrunchyBot:v4.0.0 (hosted by /u/{reddit_username})",
                                     show_default=True)
    reddit_password = click.prompt("Reddit Password", hide_input=True)
    log_dir = click.prompt("Log output directory", default="/tmp/crunchybot/logs", show_default=True)
    config_path = click.prompt("Where to save config", default=pathlib.Path.home().joinpath(".crunchybot").as_posix(),
                               show_default=True)

    config = dict(crunchy_username=crunchy_username,
                  crunchy_password=crunchy_password,
                  reddit_client_id=reddit_client_id,
                  reddit_client_secret=reddit_client_secret,
                  reddit_user_agent=reddit_user_agent,
                  reddit_username=reddit_username,
                  reddit_password=reddit_password,
                  log_dir=log_dir)

    config_path = pathlib.Path(config_path).resolve()
    if config_path.exists():
        if config_path.is_dir():
            context.logger.error("{} is a directory".format(config_path.as_posix()))
            exit(1)
        else:
            overwrite = click.confirm("Overwrite {}".format(config_path.as_posix()), default=False, show_default=True)
            if not overwrite:
                exit(1)
    with open(config_path, "w") as f:
        json.dump(config, f, indent=True)


@cli.command()
@click.option("--config", type=click.Path(exists=True), default=pathlib.Path.home().joinpath(".crunchybot").as_posix())
@click.option("--debug", "-d", type=bool, is_flag=True, default=False)
@click.pass_obj
def publish(context: Context, config: str, debug: bool):
    logger = context.logger
    data_path = pathlib.Path(config)

    config_parser = JsonConfigParser(logger=logger)
    config = None
    try:
        config = config_parser.parse(data_path)
    except ValueError as e:
        logger.error("Failed to parse config: {}".format(str(e)))
        exit(1)

    fetcher = GuestPassFetcher(config, logger=logger)
    guest_passes = []
    try:
        guest_passes.extend(fetcher.fetch(debug=debug))

        if len(guest_passes) == 0:
            logger.info("No valid Guest Passes to publish")
            exit(0)
        logger.info(f"Received Guest Passes: {guest_passes}")
    except NoSuchElementException:
        logger.error("Failed to fetch Guest Passes. Please check your Crunchyroll credentials.")
        exit(1)

    client = praw.Reddit(client_id=config.reddit_client_id,
                         client_secret=config.reddit_client_secret,
                         user_agent=config.reddit_user_agent,
                         username=config.reddit_username,
                         password=config.reddit_password)
    publisher = RedditPublisher(client, logger=logger)

    try:
        logger.info("Publishing Guest Passes to Reddit...")
        if publisher.publish(guest_passes):
            logger.info("Published Guest Passes to Reddit")
        else:
            logger.warn("Failed to find thread to publish to Reddit")
    except OAuthException as e:
        logger.error("Failed to login to Reddit: {}".format(str(e)))
        exit(1)
