#!/usr/bin/env python3.6

import codecs
import csv
import logging.config
import os
import shutil
import time

from openpyxl import load_workbook

def setup_logging(log_path):
    # Set up logging
    log_file = os.path.join(log_path, '{}.log'.format(time.strftime("%Y%m%d-%H%M%S")))

    logging.config.dictConfig({
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'standard': {
                'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
            },
        },
        'handlers': {
            'default': {
                'level': 'NOTSET',
                'class': 'logging.StreamHandler',
                'formatter': 'standard'
            },
            'logfile': {
                'filename': log_file,
                'class': 'logging.FileHandler',
                'formatter': 'standard'
            }
        },
        'loggers': {
            '': {
                'handlers': ['default', 'logfile'],
                'level': 'NOTSET',
                'propagate': True
            }
        }
    })


def read_exclude_ref(ref_path):
    ref_list = list()
    header_read = False

    full_ref_path = os.path.join(ref_path, "ref_negativ_adidas_pricat.csv")
    with codecs.open(full_ref_path, "rU", encoding='utf-8') as f:
        reader = csv.reader(f, delimiter=';')

        for row in reader:
            if header_read and len(row) == 1:
                seg_filter = row[0].strip()
                ref_list.append(seg_filter)
            else:
                header_read = True

    return ref_list

def read_include_ref(ref_path):
    ref_list = list()
    header_read = False

    full_ref_path = os.path.join(ref_path, "ref_positiv_adidas_pricat.csv")
    with codecs.open(full_ref_path, "rU", encoding='utf-8') as f:
        reader = csv.reader(f, delimiter=';')

        for row in reader:
            if header_read and len(row) == 1:
                seg_filter = row[0].strip()
                ref_list.append(seg_filter)
            else:
                header_read = True

    return ref_list

def read_include_ean_ref(ref_path):
    ref_set = set()
    ean_idx = -1
    header_read = False

    full_ref_path = os.path.join(ref_path, "ref_positiv_ean.csv")
    with codecs.open(full_ref_path, "rU", encoding='utf-8') as f:
        reader = csv.reader(f, delimiter=';')

        for row in reader:
            if header_read:
                ean = row[ean_idx].strip()
                ref_set.add(ean)
            else:
                if "EAN" in row:
                    ean_idx = row.index("EAN")
                else:
                    raise Exception("No EAN column found")

                header_read = True

    return ref_set


def remove_matches(in_file, out_excl_file, out_incl_file, out_ean_file, \
        excl_list, incl_list, ean_set):
    header_read = False
    bus_seg_idx = -1
    article_idx = -1
    label_idx = -1
    ean_idx = -1

    with codecs.open(out_excl_file, "w", encoding='utf-8') as nof, \
        codecs.open(out_incl_file, "w", encoding='utf-8') as pof, \
        codecs.open(out_ean_file, "w", encoding='utf-8') as eof:
        nwriter = csv.writer(nof, delimiter=';')
        pwriter = csv.writer(pof, delimiter=';')
        ewriter = csv.writer(eof, delimiter=';')

        logging.debug("Loading workbook...")
        wb = load_workbook(filename=in_file, read_only=True)
        ws = wb.active

        logging.debug("Parsing rows")
        for row in ws.rows:
            new_row = [cell.value for cell in row]

            if header_read:
                bus_seg = new_row[bus_seg_idx].strip()
                ean = new_row[ean_idx].strip()
                if not bus_seg in excl_list:
                    new_row.append("ADI{}#{}".format(new_row[article_idx], new_row[label_idx]))
                    nwriter.writerow(new_row)
                if bus_seg in incl_list:
                    new_row.append("ADI{}#{}".format(new_row[article_idx], new_row[label_idx]))
                    pwriter.writerow(new_row)
                if ean in ean_set:
                    new_row.append("ADI{}#{}".format(new_row[article_idx], new_row[label_idx]))
                    ewriter.writerow(new_row)

            else:
                if "Business segment" in new_row:
                    bus_seg_idx = new_row.index("Business segment")
                else:
                    raise Exception("Header column 'Business segment' not found")

                if "Article" in new_row:
                    article_idx = new_row.index("Article")
                else:
                    raise Exception("Header column 'Article' not found")

                if "Label text" in new_row:
                    label_idx = new_row.index("Label text")
                else:
                    raise Exception("Header column 'Label text' not found")

                if "EAN" in new_row:
                    ean_idx = new_row.index("EAN")
                else:
                    raise Exception("Header column 'EAN' not found")

                new_row.append("Variantennummer")
                nwriter.writerow(new_row)
                pwriter.writerow(new_row)
                ewriter.writerow(new_row)
                header_read = True
    wb.close()


def process(data_root):
    path_in = os.path.join(data_root, "in")
    path_out = os.path.join(data_root, "out")
    path_prc = os.path.join(data_root, "processed")
    path_err = os.path.join(data_root, "error")
    path_log = os.path.join(data_root, "log")
    path_ref = os.path.join(data_root, "ref")

    setup_logging(path_log)

    files = os.listdir(path_in)
    num_files = len(files)

    logging.debug("Found {0} files...".format(num_files))

    if num_files == 0:
        return

    logging.debug("Reading Refs...")
    exclude_ref_list = read_exclude_ref(path_ref)
    include_ref_list = read_include_ref(path_ref)
    include_ean_ref = read_include_ean_ref(path_ref)

    for f in files:
        in_file = os.path.join(path_in, f)
        out_neg_file = os.path.join(path_out, os.path.splitext(f)[0] + '.csv')
        out_pos_file = os.path.join(path_out, 'ref_positiv_Lizenzware.csv')
        out_ean_file = os.path.join(path_out, "Teamsport_" + os.path.splitext(f)[0] + ".csv")
        prc_file = os.path.join(path_prc, f)
        err_file = os.path.join(path_err, f)

        if not os.path.isfile(in_file):
            continue

        msg = "Matching {0}...".format(in_file)
        logging.debug(msg)

        try:
            remove_matches(in_file, out_neg_file, out_pos_file, out_ean_file, \
                exclude_ref_list, include_ref_list, include_ean_ref)

            if os.path.isfile(prc_file):
                os.remove(prc_file)

            shutil.move(in_file, prc_file)
        except Exception as e:
            logging.error(e)
            print("Error : {}".format(e))
            try:
                shutil.move(in_file, err_file)
            except Exception as e:
                logging.error(e)


def main():
    if os.path.exists(r"/ftproot/"):
        data_root = r"/ftproot/"
    elif os.path.exists(r"/home/holger/git/bitbucket/thelen/data/"):
        data_root = r"/home/holger/git/bitbucket/thelen/data/"
    else:
        print("Unknown environment. Please set data_root to data folder location. Aborting.")
        return

    project_data_root = os.path.join(data_root, "Matching_Adidas_Pricat")
    process(project_data_root)
    print("Done.")


if __name__ == "__main__":
    main()

