#!/usr/bin/env python
import csv
import codecs
import logging
import os
import re
import shutil
import time

HEADER_REF_EAN = "EAN"
HEADER_REF_ITEM_NUM = "Artikelnummer"
HEADER_REF_BRAND = "Brand"
HEADER_REF_DESC = "Description"
HEADER_REF_SIZE = "IDE_SIZE_NAME"
HEADER_REF_PURCHP = "PURCHASE_PRICE"
HEADER_REF_RETAILP = "RETAIL_PRICE"
HEADER_REF_COLOR = "SUP_COLOR_NAME"

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 get_column_index(row, col_name):
    if not col_name:
        return -1

    if not row:
        return -1

    row_lower = [x.lower() for x in row]
    col_name_lower = col_name.lower()

    if col_name_lower in row_lower:
        return row_lower.index(col_name_lower)

    return -1


def read_refs(ref_folder):
    ref_dict = dict()
    item_dict = dict()
    ref_files = os.listdir(ref_folder)
    file_num = 1

    for f in ref_files:
        print("#{} of {} : Reading ref file {}...".format(file_num, len(ref_files), f))
        file_num += 1

        # Reset vars
        header_read = False
        ean_index = -1
        item_num_index = -1
        brand_index = -1
        desc_index = -1
        size_index = -1
        pp_index = -1
        rp_index = -1
        col_index = -1

        ref_filename = os.path.join(ref_folder, f)

        prefix = ""
        if "_" in f:
            prefix = os.path.splitext(f)[0].split("_")[0]

            if "__" in f:
                prefix += "_"

        with codecs.open(ref_filename, "rb", encoding='utf-8') as f:
            reader = csv.reader(f, delimiter=';')

            for row in reader:
                if header_read:
                    ean = row[ean_index].strip()

                    item_num = row[item_num_index].strip()

                    if "_" in item_num:
                        item_num = item_num[item_num.find("_")+1:]

                    # Replace the item number with new prefix
                    item_num = "{}{}".format(prefix, item_num)

                    final_row = [prefix, item_num, "{} {} - {}"
                                 .format(row[brand_index], row[desc_index], row[col_index]), ean, \
                                row[size_index], row[pp_index], row[rp_index], "temp_CT"]
                    if ean in ref_dict:
                        ref_dict[ean].append(item_num)
                    else:
                        ref_dict[ean] = [item_num]
                    if item_num in item_dict:
                        item_dict[item_num].append(final_row)
                    else:
                        item_dict[item_num] = [final_row]
                else:
                    ean_index = get_column_index(row, HEADER_REF_EAN)
                    item_num_index = get_column_index(row, HEADER_REF_ITEM_NUM)
                    brand_index = get_column_index(row, HEADER_REF_BRAND)
                    desc_index = get_column_index(row, HEADER_REF_DESC)
                    size_index = get_column_index(row, HEADER_REF_SIZE)
                    pp_index = get_column_index(row, HEADER_REF_PURCHP)
                    rp_index = get_column_index(row, HEADER_REF_RETAILP)
                    col_index = get_column_index(row, HEADER_REF_COLOR)

                    if ean_index < 0 or item_num_index < 0 or brand_index < 0 or size_index < 0 \
                        or pp_index < 0 or rp_index < 0 or col_index < 0:
                        raise Exception("Cannot find all columns")

                    header_read = True

    print("Read a total of {} ref keys.\n\n".format(len(ref_dict)))

    return ref_dict, item_dict

def match_eans(in_file, out_file_template, ean_ref, item_ref):
    header_read = False

    variant_list = []
    missing_list = []

    regex = re.compile(r".*\[(.+)\].*")

    with codecs.open(in_file, "rb", encoding='utf-8') as f:
        reader = csv.reader(f, delimiter=';')

        for row in reader:
            if header_read:
                ean = row[0]

                if len(ean) > 13:
                    # Look for something like
                    # [PO 123456][EAN13] ; ...
                    matches = regex.search(ean)
                    if matches:
                        for g in matches.groups():
                            if len(g) == 13:
                                ean = g
                if len(ean) > 13:
                    logging.warning("Could not find EAN in %s", ean)
                    continue

                if ean in ean_ref:
                    for variant in ean_ref[ean]:
                        variant_list.append(variant)
                else:
                    missing_list.append(ean)
            else:
                header_read = True


    if variant_list:
        prefix_dict = {}

        for variant in sorted(variant_list, reverse=True):
            for item in item_ref[variant]:
                prefix = item[0]
                line = item[1:]

                if prefix in prefix_dict:
                    prefix_dict[prefix].append(line)
                else:
                    prefix_dict[prefix] = [line]

        if prefix_dict:
            for k, v in prefix_dict.items():
                out_file = out_file_template.format(k)
                with codecs.open(out_file, "w", encoding='utf-8') as of:
                    writer = csv.writer(of, delimiter=';', quoting=csv.QUOTE_NONNUMERIC)
                    writer.writerow(["ns1:ordernumber", "ns1:modelname", "ns1:ean", "ns1:print",
                                     "ns1:EK", "ns1:VK", "ns1:kat1"])
                    for item in v:
                        writer.writerow(item)


    if missing_list:
        out_file = out_file_template.format("missing")
        with codecs.open(out_file, "w", encoding='utf-8') as of:
            writer = csv.writer(of, delimiter=';', quoting=csv.QUOTE_NONNUMERIC)
            writer.writerow(["ns1:ordernumber", "ns1:modelname", "ns1:ean", "ns1:print",
                             "ns1:EK", "ns1:VK", "ns1:kat1"])

            for ean in missing_list:
                writer.writerow(["", "", ean, "", "", "", ""])

def process_files(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")

    files = os.listdir(path_in)
    num_files = len(files)

    print("Found {0} files...".format(num_files))

    if num_files == 0:
        return

    ean_ref, item_ref = read_refs(path_ref)

    for f in files:
        in_filename = os.path.splitext(f)[0]
        in_fileext = os.path.splitext(f)[1]
        dt = time.strftime("%Y%m%d-%H%M%S")

        log_filename = dt + ".log"
        out_filename = "{}_" + in_filename + "_" + dt + in_fileext

        in_file = os.path.join(path_in, f)
        out_file = os.path.join(path_out, out_filename)
        prc_file = os.path.join(path_prc, f)
        err_file = os.path.join(path_err, f)
        log_file = os.path.join(path_log, log_filename)

        if os.path.isfile(in_file):
            logging.basicConfig(filename=log_file, level=logging.DEBUG)
            print("Looking up EANs in {}...".format(in_file))

            try:
                match_eans(in_file, out_file, ean_ref, item_ref)
                shutil.move(in_file, prc_file)
            except Exception as e:
                logging.error(e)
                print("Error : {}".format(e))
                shutil.move(in_file, err_file)


def main():
    data_root = r"/ftproot/"
    # data_root = r"/home/holger/git/bitbucket/thelen/data/"
    # data_root = r"c:/temp/thelen/"

    data_root = os.path.join(data_root, "Matching_Plenty_Artikelanlage")
    process_files(data_root)
    print("Done.")

if __name__ == "__main__":
    main()

