import sys
import logging
import asyncio
import argparse
import textwrap
from domain_email_records import __title__
from domain_email_records import __version__
from domain_email_records.domain_email_records import DomainEmailRecords
from domain_email_records.domain_email_records import DomainEmailRecordsException


def main():
    args = __argparse()

    if args.quiet:
        logging_level = "CRITICAL"
    elif args.verbose:
        logging_level = "DEBUG"
    else:
        logging_level = "INFO"

    try:
        domain_email_records = DomainEmailRecords(
            chunk_size=args.chunk,
            csv_column=args.csv_column,
            max_query_seconds=args.timeout,
            logging_level=logging_level,
        )
        if args.filename:
            domains = domain_email_records.read_domains_file(filename=args.filename, csv_column=args.csv_column)
        else:
            domains = args.domains

        # asyncio.run(domain_email_records.lookups(domains=domains, output=args.out))
        eventloop = asyncio.get_event_loop()
        eventloop.run_until_complete(domain_email_records.lookups(domains=domains, output=args.out))
        eventloop.close()

    except KeyboardInterrupt:
        logging.getLogger(__title__).warning("Exiting...")
        eventloop.stop()
        sys.exit(1)

    except DomainEmailRecordsException as e:
        message = ""
        for part in e.args:
            message = f"{str(message)}\n{part}".strip()
        logging.getLogger(__title__).error(message)
        sys.exit(1)

    except Exception as e:  # noqa pylint:disable=broad-except
        message = ""
        for part in e.args:
            message = f"{str(message)}\n{part}".strip()
        logging.getLogger(__title__).critical(message, exc_info=True)
        sys.exit(1)


def __argparse() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        add_help=True,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description=textwrap.dedent(
            """\
            {name} v{version}

            CLI tool to quickly lookup MX, SPF, DMARC records for many domains
        """.format(
                name=__title__, version=__version__
            )
        ),
    )

    output_parser = parser.add_mutually_exclusive_group(required=False)
    output_parser.add_argument("-q", "--quiet", action="store_true", help="Set quiet logging output")
    output_parser.add_argument("-v", "--verbose", action="store_true", help="Set verbose logging output")

    parser.add_argument(
        "-o",
        "--out",
        metavar="<filename>",
        required=False,
        type=str,
        help="Filename to save JSON formatted output to (default: stdout)",
    )
    parser.add_argument(
        "-t",
        "--timeout",
        metavar="<seconds>",
        required=False,
        type=int,
        default=5,
        help="Timeout seconds per domain-record query (default: 5)",
    )
    parser.add_argument(
        "-c",
        "--chunk",
        metavar="<size>",
        required=False,
        type=int,
        default=1000,
        help="Chunk size per async loop to resolve together (default: 1000)",
    )

    direct_list_parser = parser.add_argument_group(title="direct")
    direct_list_parser.add_argument(
        "-d", "--domains", metavar="<domain>", nargs="*", help="Space separated list of domain names to query"
    )

    file_list_parser = parser.add_argument_group(title="filename")
    file_list_parser.add_argument(
        "-f",
        "--filename",
        metavar="<filename>",
        type=str,
        help="Filename with list of domains to use; plain list text file -or- a comma-separated CSV file list.",
    )
    file_list_parser.add_argument(
        "--csv-column",
        metavar="<col>",
        required=False,
        type=int,
        default=2,
        help="CSV column number to use for domain-names -if- the file is CSV formatted (default: 2)",
    )

    args = parser.parse_args()

    if len(sys.argv) < 2 or (args.filename and args.domains):
        parser.print_help()
        print()
        exit(1)

    return args
