from lang_main.analysis import graphs
from lang_main.analysis.preprocessing import (
    analyse_feature,
    clean_string_slim,
    entry_wise_cleansing,
    load_raw_data,
    merge_similarity_dupl,
    numeric_pre_filter_feature,
    remove_duplicates,
    remove_NA,
)
from lang_main.analysis.timeline import (
    filter_activities_per_obj_id,
    generate_model_input,
    get_timeline_candidates,
    remove_non_relevant_obj_ids,
)
from lang_main.analysis.tokens import build_token_graph
from lang_main.constants import (
    ACTIVITY_FEATURE,
    ACTIVITY_TYPES,
    DATE_COLS,
    FEATURE_NAME_OBJ_ID,
    MODEL_INPUT_FEATURES,
    SAVE_PATH_FOLDER,
    SPCY_MODEL,
    STFR_MODEL,
    THRESHOLD_AMOUNT_CHARACTERS,
    THRESHOLD_EDGE_WEIGHT,
    THRESHOLD_NUM_ACTIVITIES,
    THRESHOLD_SIMILARITY,
    THRESHOLD_TIMELINE_SIMILARITY,
    THRESHOLD_UNIQUE_TEXTS,
    UNIQUE_CRITERION_FEATURE,
)
from lang_main.pipelines.base import Pipeline
from lang_main.types import EntryPoints


# ** pipeline configuration
# ** target feature preparation
def build_base_target_feature_pipe() -> Pipeline:
    pipe_target_feat = Pipeline(name='TargetFeature', working_dir=SAVE_PATH_FOLDER)
    pipe_target_feat.add(
        load_raw_data,
        {
            'date_cols': DATE_COLS,
        },
    )
    pipe_target_feat.add(remove_duplicates)
    pipe_target_feat.add(remove_NA, save_result=True)
    pipe_target_feat.add(
        entry_wise_cleansing,
        {
            'target_feature': 'VorgangsBeschreibung',
            'cleansing_func': clean_string_slim,
        },
        save_result=True,
        filename=EntryPoints.TIMELINE,
    )
    pipe_target_feat.add(
        analyse_feature,
        {
            'target_feature': 'VorgangsBeschreibung',
        },
        save_result=True,
    )

    return pipe_target_feat


# output: DataFrame containing target feature with
# number of occurrences and associated ObjectIDs

# ** embedding pipe
# ?? still needed?
# using similarity between entries to catch duplicates with typo or similar content
# pipe_embds = BasePipeline(name='Embedding1', working_dir=SAVE_PATH_FOLDER)


# pipe_embds.add(build_cosSim_matrix, {'model': model_stfr}, save_result=True)
# pipe_embds.add(
#     filt_thresh_cosSim_matrix, {'threshold': THRESHOLD_SIMILARITY}, save_result=True
# )
# pipe_embds.add(
#     list_cosSim_dupl_candidates,
#     {
#         'save_candidates': True,
#         'saving_path': SAVE_PATH_FOLDER,
#         'filename': FILENAME_COSSIM_FILTER_CANDIDATES,
#         'pipeline': pipe_embds,
#     },
#     save_result=True,
# )


# ** Merge duplicates
def build_merge_duplicates_pipe() -> Pipeline:
    pipe_merge = Pipeline(name='Merge_Duplicates', working_dir=SAVE_PATH_FOLDER)
    # pipe_merge.add(merge_similarity_dupl, save_result=True)
    pipe_merge.add(
        numeric_pre_filter_feature,
        {
            'feature': 'len',
            'bound_lower': THRESHOLD_AMOUNT_CHARACTERS,
            'bound_upper': None,
        },
    )
    pipe_merge.add(
        merge_similarity_dupl,
        {
            'model': STFR_MODEL,
            'cos_sim_threshold': THRESHOLD_SIMILARITY,
        },
        save_result=True,
        filename=EntryPoints.TOKEN_ANALYSIS,
    )

    return pipe_merge


# ** token analysis
def build_tk_graph_pipe() -> Pipeline:
    pipe_token_analysis = Pipeline(name='Token_Analysis', working_dir=SAVE_PATH_FOLDER)
    pipe_token_analysis.add(
        build_token_graph,
        {
            'model': SPCY_MODEL,
            'target_feature': 'entry',
            'weights_feature': 'num_occur',
            'batch_idx_feature': 'batched_idxs',
            'build_map': False,
            'batch_size_model': 50,
        },
        save_result=True,
        filename=EntryPoints.TK_GRAPH_POST,
    )

    return pipe_token_analysis


def build_tk_graph_post_pipe() -> Pipeline:
    pipe_graph_postprocessing = Pipeline(
        name='Graph_Postprocessing', working_dir=SAVE_PATH_FOLDER
    )
    pipe_graph_postprocessing.add(
        graphs.filter_graph_by_edge_weight,
        {
            'bound_lower': THRESHOLD_EDGE_WEIGHT,
            'bound_upper': None,
        },
    )
    pipe_graph_postprocessing.add(
        graphs.filter_graph_by_node_degree,
        {
            'bound_lower': 1,
            'bound_upper': None,
        },
        save_result=True,
        filename=EntryPoints.TK_GRAPH_ANALYSIS,
    )

    return pipe_graph_postprocessing


# ** timeline analysis
def build_timeline_pipe() -> Pipeline:
    pipe_timeline = Pipeline(name='Timeline_Analysis', working_dir=SAVE_PATH_FOLDER)
    pipe_timeline.add(
        remove_non_relevant_obj_ids,
        {
            'thresh_unique_feat_per_id': THRESHOLD_UNIQUE_TEXTS,
            'feature_uniqueness': UNIQUE_CRITERION_FEATURE,
            'feature_obj_id': FEATURE_NAME_OBJ_ID,
        },
        save_result=True,
    )
    pipe_timeline.add(
        generate_model_input,
        {
            'target_feature_name': 'nlp_model_input',
            'model_input_features': MODEL_INPUT_FEATURES,
        },
    )
    pipe_timeline.add(
        filter_activities_per_obj_id,
        {
            'activity_feature': ACTIVITY_FEATURE,
            'relevant_activity_types': ACTIVITY_TYPES,
            'feature_obj_id': FEATURE_NAME_OBJ_ID,
            'threshold_num_activities': THRESHOLD_NUM_ACTIVITIES,
        },
    )
    pipe_timeline.add(
        get_timeline_candidates,
        {
            'model': STFR_MODEL,
            'cos_sim_threshold': THRESHOLD_TIMELINE_SIMILARITY,
            'feature_obj_id': FEATURE_NAME_OBJ_ID,
            'model_input_feature': 'nlp_model_input',
        },
        save_result=True,
        filename=EntryPoints.TIMELINE_POST,
    )

    return pipe_timeline
