# -*- coding: utf-8 -*-
import os
import argparse

from datacloud.input_pipeline.input_checker.constants import (
    delimiter_vars, allowed_headers, id_fields,
    DEFAULT_PHONE_LENGTH, retro_date_formats, birth_date_formats
)
from datacloud.dev_utils.validators.csv_validator import enumeration
from datacloud.input_pipeline.input_checker.xprod_csv_validator import (
    XProdCsvValidator, check_phone, check_email,
    check_md5, check_val_is_md5, check_client_id_site, check_one_of_required_fields,
    check_uuid_app_id, check_date, unique_validate, unique_tuple_validate, check_yuid
)
from datacloud.input_pipeline.input_pipeline.helpers import check_target_prefix
from datacloud.input_pipeline.normalizer.constants import DEFAULT_OUTPUT_FILE


def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '-d',
        '--delimiter',
        default='tab',
        choices=delimiter_vars.keys(),
        help='delimiter of csv file'
    )
    parser.add_argument(
        '-f',
        '--file',
        default=os.path.join(os.getcwd(), DEFAULT_OUTPUT_FILE),
        help='csv file to parse',
    )
    parser.add_argument(
        '-ul',
        '--use-list',
        action='store_true',
        help='first validation of all file, then writeing problems',
    )
    parser.add_argument(
        '-s',
        '--summary',
        action='store_true',
        help='only report problem codes, no other details',
    )
    parser.add_argument(
        '-l',
        '--limit',
        type=int,
        help='limit number of problems',
    )
    parser.add_argument(
        '-hh',
        '--hard-headers-check',
        action='store_true',
        help='hard check of headers. only allowed from consts/allowed_headers',
    )

    args = parser.parse_args()
    return (
        delimiter_vars[args.delimiter],
        args.file,
        args.use_list,
        args.summary,
        args.limit,
        args.hard_headers_check
    )


def get_xprod_validator(full_path_to_file, delimiter, hard_headers=False, phone_length=None):
    if not phone_length:
        phone_length = DEFAULT_PHONE_LENGTH
    validator = XProdCsvValidator(full_path_to_file, delimiter, allowed_headers, id_fields, hard_headers)
    target_fields = filter(check_target_prefix, validator.fields_set)

    validator.add_header_check('EX_BAD_HEADER', 'bad header')
    validator.add_record_length_check('EX_RECORD_LENGTH', 'unexpected record length')

    # Check client identificators
    validator.add_value_check_if_exists('phone', check_phone(phone_length),
                                        'EX_BAD_PHONE', 'invalid phone')
    validator.add_value_check_if_exists('phone_id_value', check_md5(),
                                        'EX_BAD_PHONEID', 'invalid phone_id_value')
    validator.add_value_check_if_exists('email', check_email(),
                                        'EX_BAD_EMAIL', 'invalid email')
    validator.add_value_check_if_exists('email_id_value', check_md5(),
                                        'EX_BAD_EMAILID', 'invalid email_id_value')

    # TODO: this doesn't work with multiple values in field
    validator.add_record_check(check_val_is_md5('phone', 'phone_id_value'))
    validator.add_record_check(check_val_is_md5('email', 'email_id_value'))

    validator.add_value_check_if_exists('ClientID@site', check_client_id_site(),
                                        'EX_BAD_CLIENT_ID_SITE', 'invalid bad client id site')
    validator.add_value_check_if_exists('UUID@app_id', check_uuid_app_id(),
                                        'EX_BAD_UUID_APP_ID', 'invalid UUID@app_id')

    for field in id_fields:
        validator.add_value_check_if_exists(field, unique_validate(field, validator),
                                            'EX_UNIQUE', 'duplicate {}'.format(field))

    # validator.add_unique_check('contract_id', 'EX_UNIQUE_CONTRACT_ID', 'duplicate contract_id')
    validator.add_record_check(unique_tuple_validate(
        ('external_id', 'retro_date'),
        target_fields,
        validator
    ))

    validator.add_record_check(check_one_of_required_fields(id_fields))

    validator.add_value_check_if_exists('gender', enumeration('M', 'F', ''),
                                        'EX_GENDER', 'invalid gender')

    validator.add_value_check_if_exists('birth_date', check_date(birth_date_formats, allow_empty=True),
                                        'EX_BIRTH_DATE', 'invalid birth date')

    # This is not how it works in real life. Will use int :)
    # validator.add_value_check_if_exists('target', enumeration('1', '0', '-1'),
    #                         'EX_TARGET', 'invalid target')
    for field in target_fields:
        validator.add_value_check(field, int, 'EX_TARGET', 'invalid target')
    validator.add_value_check('retro_date', check_date(retro_date_formats, allow_empty=False),
                              'EX_RETRO_DATE', 'invalid retro date')

    validator.add_value_check_if_exists('yuid', check_yuid(), 'EX_YUID', 'invalid yuid')

    return validator
