from math import floor
from random import randint

import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from pandas import DataFrame
from prodict import Prodict

from datasource import datasource
from datasource.datasource import ApiResult, ApiProfile
from outputs import outputhelper


def import_additional_results_from_csv(filename: str) -> DataFrame:
    return import_additional_results(filename, "csv")


def import_additional_results(filename: str, extension: str) -> DataFrame:
    full_filename = filename + "." + extension
    csv_path = datasource.get_file_path(full_filename)
    df = pd.read_csv(csv_path, header=0, names=["x", filename], usecols=[0, 1])
    return df


def foo():
    csv_path = datasource.get_input_file_path()

    df = pd.read_csv(csv_path, header=1, names=["x", "y"], usecols=["x", "y"])
    # print(df)

    # print(df.iloc[:, 0])
    # print(df.iloc[:, 1])

    df2 = pd.read_csv(datasource.get_file_path("additional.csv"),
                      header=1, names=["a", "b", "c"], usecols=["b", "c"])

    second_run = import_additional_results("input2", "csv")
    run_3 = import_additional_results_from_csv("input3")

    print(run_3)
    # print(df.join(df2))
    # print(df.join(df2.iloc[:,0]))

    # df['b'] = df2.b

    df = df.join(second_run.input2)
    df = df.join(run_3.input3)

    fig = px.scatter(df, x=df.x, y=df.y)

    # fig.show()

    df_melt = df.melt(id_vars="x", value_vars=["y", "input2"])
    print(df_melt)

    # fig = px.scatter(df, x=df_melt.x, y=df_melt.value, color=df_melt.variable)

    trace2 = go.Scatter(x=df.x, y=df.input2, mode="lines+markers")
    fig.add_trace(trace2)

    fig.show()


def api():
    df = import_additional_results_from_csv("api_input")

    mean = df.groupby("x").mean()
    print(mean)
    fig = px.scatter(df, x=df.x, y=df.api_input)
    trace2 = go.Scatter(x=mean.index, y=mean.api_input, mode="lines+markers", name="Mean")
    fig.add_trace(trace2)
    outputhelper.save_figure(fig, "test1")


def api_live():
    apicalls: [ApiProfile] = datasource.create_dummy_api_csv()
    df = DataFrame.from_records([dict(entry) for entry in apicalls])

    df.duration = pd.to_numeric(df.duration)
    df.ticketcount = pd.to_numeric(df.ticketcount)
    # print(df.shape)
    print(df.info())

    mean = df.groupby("ticketcount").mean()
    # print(mean)

    api_improved = datasource.create_dummy_api_improvement_csv()
    df2 = DataFrame.from_records([dict(entry2) for entry2 in api_improved])
    df2.duration = pd.to_numeric(df2.duration)
    df2.ticketcount = pd.to_numeric(df2.ticketcount)
    trace3 = go.Scatter(x=df2.ticketcount, y=df2.duration, mode="markers", name="Improved")

    mean2 = df2.groupby("ticketcount").mean()
    trace4 = go.Scatter(x=mean2.index, y=mean2.duration, mode="lines+markers", name="Improved-Mean")

    fig = go.Figure()
    trace1 = go.Scatter(x=df.ticketcount, y=df.duration, mode="markers", name="Base")
    fig.add_trace(trace1)
    # fig = px.scatter(df, x=df.ticketcount, y=df.duration)
    trace2 = go.Scatter(x=mean.index, y=mean.duration, mode="lines+markers", name="Base-Mean")
    fig.add_trace(trace2)
    fig.add_trace(trace3)
    fig.add_trace(trace4)

    results = df[['ticketcount', 'duration']].copy()
    results['improved'] = df2.duration
    print(results)

    outputhelper.save_figure(fig)
    outputhelper.dump_data_as_csv(results, "api-mean-changes")


def generate_api_url(entity_id: int):
    return f"rest/v1/accounts/{entity_id}/tickets"


class ApiCallSheet(Prodict):
    ticketcount: int
    url: str
    duration: int


def raw_api_call_data():
    output = []

    keys = ApiCallSheet.attr_names()

    for entry in range(100):
        entity_id = randint(19283, 23671)
        num_tickets = randint(1, 25)
        url = generate_api_url(entity_id)
        duration = randint(100, 800)

        output.append({
            keys[0]: num_tickets,
            keys[1]: url,
            keys[2]: duration
        })
    datasource.write_to_csv(output, "raw-calls", keys)


def probably_speed_up(x):
    if randint(1, 10) > 8:
        return x + randint(1, floor(x / 4))
    else:
        return x - randint(1, floor(x / 3))


def raw_api_call_second():
    df = pd.read_csv(datasource.get_file_path("raw-calls.csv"))
    df.duration = df.duration.apply(lambda x: probably_speed_up(x))
    df.to_csv(datasource.get_file_path("raw-calls-2.csv"), index=False)


if __name__ == '__main__':
    # foo()
    # api()
    # api_live()
    raw_api_call_data()
    raw_api_call_second()
