import dataiku
import pandas as pd
import numpy as np
from flask import request
import json
from ast import literal_eval

from market_basket_analysis.dku_utils import get_current_project_and_variables
from market_basket_analysis.utils import add_sort_table_to_html_header
from market_basket_analysis.config.webapp.constants import WEBAPP_SCHEMA, COLUMNS_RENAMINGS
from market_basket_analysis.config.webapp.functions import (open_html_tag,
                                                            generate_table_header_html,
                                                            enrich_cell_data,
                                                            from_dataframe_values_to_html_table,
                                                            filter_association_rules_dataframe,
                                                            simplify_itemsets,
                                                            format_metrics)


project, variables = get_current_project_and_variables()
compute_refined_rules = variables["standard"]["compute_refined_rules_app"]
print("Loading webapp datasets ...")
df_valid_association_rules = dataiku.Dataset("valid_association_rules").get_dataframe()
df_rules_denormalized_antecedents = dataiku.Dataset("valid_rules_denormalized_antecedents").get_dataframe()
df_rules_denormalized_consequents = dataiku.Dataset("valid_rules_denormalized_consequents").get_dataframe()

print("Preprocessing webapp datasets ...")
dataframe_schema = WEBAPP_SCHEMA
if compute_refined_rules:
    association_rule_scopes = list(np.unique(df_valid_association_rules["rule_scope"].astype(str)))
    dataframe_schema = ["rule_scope"] + dataframe_schema
    df_valid_association_rules["rule_scope"] = df_valid_association_rules["rule_scope"].astype(str)
    df_rules_denormalized_antecedents["rule_scope"] = df_rules_denormalized_antecedents["rule_scope"].astype(str)
    df_rules_denormalized_consequents["rule_scope"] = df_rules_denormalized_consequents["rule_scope"].astype(str)
else:
    association_rule_scopes = []
df_valid_association_rules = df_valid_association_rules[dataframe_schema]

for itemset_column in ["rule_antecedent", "rule_consequent"]:
    df_valid_association_rules[itemset_column] = df_valid_association_rules[itemset_column].apply(lambda x: literal_eval(x))
    itemset_column_values = list(df_valid_association_rules[itemset_column])
    itemset_column_values = simplify_itemsets(itemset_column_values)
    df_valid_association_rules[itemset_column] = itemset_column_values
    
antecedent_items = list(np.unique(df_rules_denormalized_antecedents["antecedent_item"].astype(str)))
consequent_items = list(np.unique(df_rules_denormalized_consequents["consequent_item"].astype(str)))
rules_items = list(np.sort(np.unique(antecedent_items+consequent_items)))
application_columns = list(df_valid_association_rules.columns)

@app.route('/load_rule_scopes_and_itemsets/')
def load_rule_scopes_and_itemsets():
    return json.dumps({"status": 200,
                       "compute_refined_rules": compute_refined_rules,
                       "association_rule_scopes": association_rule_scopes,
                       "rules_items": rules_items
                      })


@app.route('/filter_table_data/', methods=["POST"])
def filter_table_data():
    
    params = request.get_json(force=True)
    selected_rule_scopes = params["selected_rule_scopes"]
    rules_scope_is_set = len(selected_rule_scopes) > 0
    support = float(params["support"])/100.0
    confidence = float(params["confidence"])
    lift = float(params["lift"])
    conviction = float(params["conviction"])
    selected_items = params["selected_items"]
    active_button = params["active_button"]
    metrics_priority = params["metrics_priority"]
    metric_priority_is_set = (len(metrics_priority) > 0)
    sort_results_ascending = params["sort_results_ascending"]

    filtered_association_rules = df_valid_association_rules.copy()
    if active_button == "find_consequents_button":
        df_items_rules_mapping = df_rules_denormalized_antecedents.copy()
    else:
        df_items_rules_mapping = df_rules_denormalized_consequents.copy()
    
    if compute_refined_rules:
        if rules_scope_is_set:
            df_items_rules_mapping = df_items_rules_mapping[df_items_rules_mapping["rule_scope"].isin(selected_rule_scopes)]

    filtered_association_rules = filter_association_rules_dataframe(filtered_association_rules, confidence, lift, conviction, support)
    df_items_rules_mapping = filter_association_rules_dataframe(df_items_rules_mapping, confidence, lift, conviction, support)
    
    
    if active_button == "find_consequents_button":
        items_filtering_column = "antecedent_item"
    else:
        items_filtering_column = "consequent_item"
    
    df_items_rules_mapping = df_items_rules_mapping[df_items_rules_mapping[items_filtering_column].isin(selected_items)]
    valid_rule_ids = np.unique(df_items_rules_mapping["rule_id"])
    filtered_association_rules = filtered_association_rules[filtered_association_rules["rule_id"].isin(valid_rule_ids)]
    if metric_priority_is_set:
        filtered_association_rules.sort_values(by=metrics_priority, ascending=sort_results_ascending, inplace=True)
    filtered_association_rules = format_metrics(filtered_association_rules)
    filtered_association_rules.rename(COLUMNS_RENAMINGS, axis=1, inplace=True)
    column_labels = list(filtered_association_rules.columns)
    association_rules_table_html = generate_table_header_html(column_labels, [])
    association_rules_table_html += from_dataframe_values_to_html_table(filtered_association_rules)
    
    for column_index, column_name in enumerate(application_columns):
        association_rules_table_html = add_sort_table_to_html_header(association_rules_table_html,
                                                                     column_name,
                                                                     column_index)
        pass
    
    matching_rules_text = "{} Matching rules".format(len(df_items_rules_mapping))
        
    return json.dumps({"status": 200,
                       "association_rules_table_data":association_rules_table_html,
                       "matching_rules_text":matching_rules_text
                      })