# coding: utf-8
"""Usage:
  ta-report [<report_type>... [--sheets <NAME>...| --presets <NAME>...] --lang <NAME> --pptx --work-dir <PATH> --user <NAME> --zip --clean --dumps-src -d]

Options:
  -h --help             Show this message
  -V --version          Show version
  -s --sheets <NAME>    Create only selected sheets
  -p --presets <NAME>   Create only selected presets of sheets (mks_light)
  -l --lang <NAME>      Choose language of sheet names, notes (ru). If not set
                        code names will be used.
  -p --pptx             Create presentation
  -w --work-dir <PATH>  Path to sources
  -u --user <NAME>      Set user for logging
  -z --zip              Compress to `result.zip`
  -c --clean            Delete created files except result
  --dumps-src           Try to save merged sources into xlsx or tsv:
                          <report_type>_dumps-src.{xlsx|tsv}
  -d --debug            Dump log into the local file `ta-report.log`

Note:
  <report_type> : keywords | search_queries | mobile
  --presets: mks_light
  --lang:    ru
"""
from .const import (
    __version__,
    CLI_REPORTS,
    SESSION_ID,
    ARGS_FILE_PATH
)
from configure_reports import return_reports, return_report_sheets, return_report_name
from pptx_ta import return_pptx_name
from .logger import make_logger
from .error import (ForecastError, get_error_code)
from pptx_ta.presentation import make_ta_pptx
from .reports import REPORTS
import os
import sys
import logging
import traceback
import warnings
import json
from docopt import docopt
warnings.filterwarnings("ignore")


def main():
    """() -> None; CLI Entry Point"""
    try:
        ARGS = docopt(__doc__, version=__version__)

        make_logger(ARGS["--debug"])
        logging.info("version: %s" % __version__)
        logging.debug("session_id: %s" % SESSION_ID)
        if '--work-dir' in ARGS and ARGS['--work-dir']:
            os.chdir(ARGS['--work-dir'])
        with open(ARGS_FILE_PATH, 'w') as dst:
            json.dump(ARGS, dst)
        # if empty try to do all known reports
        if "<report_type>" in ARGS and not ARGS["<report_type>"]:
            ARGS["<report_type>"] = CLI_REPORTS
        for fn in ARGS["<report_type>"]:
            if fn not in CLI_REPORTS:
                raise KeyError("unknown report type `%s`. Valid options: %s" % (fn, CLI_REPORTS))

        if ARGS["--sheets"]:
            ARGS["<report_type>"] = return_reports(selected_sheets=ARGS["--sheets"],
                                                   selected_reports=ARGS["<report_type>"])
        elif ARGS["--presets"]:
            ARGS["--sheets"], ARGS["<report_type>"] = return_reports(selected_presets=ARGS["--presets"],
                                                                     selected_reports=ARGS["<report_type>"])
        else:
            ARGS["--sheets"] = return_reports(selected_reports=ARGS["<report_type>"])

        logging.info("START APP")
        for fn_name, fn in REPORTS.items():
            if fn_name not in ARGS["<report_type>"]:
                continue
            try:
                report = fn([sheet_name for sheet_name in ARGS["--sheets"]
                             if sheet_name in return_report_sheets(fn_name)]
                            )
            except ForecastError as err:
                logging.warn(err.message)

            if ARGS['--dumps-src'] and report is not None:
                if report.shape[0] < 500000:  # ограничение с потолка
                    assert report.shape[0] < 1000000, "1000000 is max for xlsx"
                    report.to_excel("./%s_dumps-src.xlsx" % fn_name, encoding="utf-8", sheet_name="data")
                else:
                    report.to_csv(
                        "./%s_dumps-src.tsv" % fn_name,
                        sep='\t',
                        # compression="gzip", # compression + encoding does not supported yet
                        encoding="utf-8",
                        chunksize=100000)

        if ARGS['--pptx']:
            reports_for_pptx = {}
            for report in ARGS['<report_type>']:
                reports_for_pptx[report] = {"path": "./%s.xlsx" % return_report_name(report)}
            make_ta_pptx(reports_for_pptx)

        if ARGS['--zip']:
            import zipfile
            import shutil
            from glob import glob

            logging.info("create archive")
            try:
                ext_name = 'extras'  # extra data
                if glob("./images/*.png"):
                    shutil.make_archive(ext_name, 'zip', base_dir='images')
                    logging.info("add `images` to %s" % ext_name)

                zip_name = 'reports.zip'  # minimum
                zf = zipfile.ZipFile(zip_name, mode='w')
                for report in ARGS["<report_type>"]:
                    report_file = "%s.xlsx" % return_report_name(report)
                    if not os.path.exists(report_file):
                        continue
                    zf.write(report_file)
                    os.remove(report_file)
                    logging.info("add file to %s" % zip_name)

                pptx_file = u"%s.pptx" % return_pptx_name()
                if os.path.exists(pptx_file):
                    zf.write(pptx_file)
                    os.remove(pptx_file)
                    logging.info("add file to %s" % zip_name)

                zf.close()
            except:
                raise

        if ARGS['--clean']:
            import shutil
            for x in ["charts", "images", "tmp_data"]:
                if not os.path.isdir(x):
                    continue
                shutil.rmtree(x, ignore_errors=True)
                logging.info("remove (--clean): %s" % x)
        logging.info("FINISH APP")
        sys.exit(0)
    except Exception as err:
        with open('stderr.txt', 'w') as f:
            f.write("SessionId: %s\n" % SESSION_ID)
            traceback.print_exc(file=f)
        logging.error(err, exc_info=0)
        sys.exit(get_error_code(err))
    finally:
        if os.path.exists(ARGS_FILE_PATH):
            os.remove(ARGS_FILE_PATH)


if __name__ == "__main__":
    main()
