import pytest
from datetime import datetime
from datetime import timedelta
import importlib
code = importlib.import_module('data_handler')
from data_handler import END_DATE
from data_handler import FREQ

FMT_ISO = "%Y%m%d"
FMT_DASH = "%Y-%m-%d"
FMT_MON = "%d %b %Y"
FMT_MON_HR = f"%Hh {FMT_MON}"
FMT_FULLMON = "%d %B %Y"
FMT_FULLMON_HR = f"%Hh {FMT_FULLMON}"
FMT_HR = "%H:%M:%S"
FMT_DASH_HR = f"{FMT_DASH} {FMT_HR}"
EDATE_OBJ = datetime.strptime(END_DATE, FMT_ISO)
EDATE_PREV = (datetime.strptime(END_DATE, FMT_ISO) - timedelta(days=7)).strftime(FMT_ISO)

#.strftime("%d %B %Y"))
@pytest.fixture
def aeronet_instance():
    return code.Observations1dHandler(EDATE_PREV, END_DATE , 'aeronet') 

def test_generate_obs1d_tstep_trace1(aeronet_instance):
    run = aeronet_instance.generate_obs1d_tstep_trace('OD550_DUST')
    assert str(type(run[1])) == "<class 'dash_leaflet.GeoJSON.GeoJSON'>"

# @pytest.fixture 
# def obsTSHandler_instance():
#     return code.ObsTimeSeriesHandler('aeronet','20220404','20220405', 'OD550_DUST', ['median', 'monarch']) 
#
# def test_retrieve_timeseries():
#     assert obsTSHandler_instance.retrieve_timeseries(idx, st_name, model) == 'hello'

    
# =================== TIME SERIES HANDLER ============================
@pytest.fixture
def TSHandler():
    return code.TimeSeriesHandler('median', END_DATE, 'OD550_DUST')

# def test_TimeSeriesHandler(TSHandler):
#     run = TSHandler.retrieve_single_point(1, 45, 45, model='median')
#     assert float(run) == 0.10633552074432373
# 
# def test_TimeSeriesHandler_1(TSHandler):
#     run = TSHandler.retrieve_single_point(3, 5, 5, model=None)
#     assert float(run) == 0.00830854382365942

def test_retrieve_timeseries(TSHandler):
    run = TSHandler.retrieve_timeseries(5, 5, model=None, method='netcdf', forecast=False)
    assert run.layout.title.text =='Dust Optical Depth @ lat = 5 and lon = 5'

def test_retrieve_timeseries_1(TSHandler):
    run = TSHandler.retrieve_timeseries(35, 15, model='monarch', method='netcdf', forecast=True)
    assert run.layout.title.text =='Dust Optical Depth @ lat = 35 and lon = 15'

def test_retrieve_timeseries_2(TSHandler):
    run = TSHandler.retrieve_timeseries(35, 15, model='monarch', method='netcdf', forecast=True)
    assert run.layout.title.text =='Dust Optical Depth @ lat = 35 and lon = 15'

# =================== FIGURE HANDLER ============================
@pytest.fixture
def FigureHandler():
    return code.FigureHandler('median', END_DATE)

def test_FH_get_center(FigureHandler):
    assert FigureHandler.get_center([35,45]) == [35, 45]
    assert FigureHandler.get_center([-35,-45]) == [-35, -45]

def test_set_data_AOD(FigureHandler):
    assert FigureHandler.set_data('OD550_DUST', tstep=0)[0][0] == -26.75

def test_set_data_SCONC(FigureHandler):
    assert FigureHandler.set_data('SCONC_DUST', tstep=0)[0][0] == -26.75

def test_retrieve_cdatetime(FigureHandler):
    assert str(FigureHandler.retrieve_cdatetime(tstep=0)) == EDATE_OBJ.strftime(FMT_DASH_HR)  # '2022-06-06 12:00:00'
    assert str(FigureHandler.retrieve_cdatetime(tstep=6)) == (EDATE_OBJ + timedelta(hours=6*FREQ)).strftime(FMT_DASH_HR)  # '2022-06-07 06:00:00'
    assert str(FigureHandler.retrieve_cdatetime(tstep=12)) == (EDATE_OBJ + timedelta(hours=12*FREQ)).strftime(FMT_DASH_HR)  # '2022-06-08 00:00:00'

def test_generate_contour_tstep_trace_leaflet(FigureHandler):
    result = "GeoJSON(hideout={'colorscale': ['rgba(255,255,255,0.4)', '#a1ede3', '#5ce3ba', '#fcd775', '#da7230', '#9e6226', '#714921', '#392511', '#1d1309'], 'bounds': array([ 0. ,  0.1,  0.2,  0.4,  0.8,  1.2,  1.6,  3.2,  6.4, 10. ]"
    assert result in str(FigureHandler.generate_contour_tstep_trace_leaflet('OD550_DUST', tstep=0)[0])
    result2 = "Colorbar(classes=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], colorscale=['rgba(255,255,255,0.4)', '#a1ede3', '#5ce3ba', '#fcd775', '#da7230', '#9e6226', '#714921', '#392511', '#1d1309']"
    assert result2 in str(FigureHandler.generate_contour_tstep_trace_leaflet('OD550_DUST', tstep=0)[1])

def test_generate_contour_tstep_trace_AOD(FigureHandler):
    assert FigureHandler.generate_contour_tstep_trace('OD550_DUST', tstep=0)['name'] == 'Dust Optical Depth_contours'
    assert FigureHandler.generate_contour_tstep_trace('OD550_DUST', tstep=0)['showlegend'] == False

def test_generate_contour_tstep_trace_SCONC(FigureHandler):
    assert FigureHandler.generate_contour_tstep_trace('SCONC_DUST', tstep=0)['name'] == 'Dust Surface Conc. (µg/m³)_contours'
    assert FigureHandler.generate_contour_tstep_trace('SCONC_DUST', tstep=0)['showlegend'] == False

def test_generate_var_tstep_trace_leaflet_AOD(FigureHandler):
    assert str(FigureHandler.generate_var_tstep_trace_leaflet(varname='OD550_DUST', tstep=0))[0:162] == "GeoJSON(data={'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'geometry': {'type': 'Point', 'coordinates': [-26.75, 0.25]}, 'properties': {'value': "

def test_generate_var_tstep_trace_leaflet_SCONC(FigureHandler):
    assert str(FigureHandler.generate_var_tstep_trace_leaflet(varname='SCONC_DUST', tstep=0))[0:162] == "GeoJSON(data={'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'geometry': {'type': 'Point', 'coordinates': [-26.75, 0.25]}, 'properties': {'value': "

def test_generate_var_tstep_trace_AOD(FigureHandler):
    assert FigureHandler.generate_var_tstep_trace(varname='OD550_DUST', tstep=0)['name'] == "MULTI-MODEL" 

def test_generate_var_tstep_trace_SCONC(FigureHandler):
    assert FigureHandler.generate_var_tstep_trace(varname='SCONC_DUST', tstep=6)['name'] == "MULTI-MODEL" 

def test_get_title(FigureHandler):
    assert FigureHandler.get_title('OD550_DUST', tstep=0) == 'MULTI-MODEL Dust Optical Depth (550nm)<br>Valid: {edate} (H+00)'.format(edate=EDATE_OBJ.strftime(FMT_MON_HR))
    assert FigureHandler.get_title('SCONC_DUST', tstep=9) == 'MULTI-MODEL Dust Surface Conc. (µg/m³)<br>Valid: {edate} (H+27)'.format(edate=(EDATE_OBJ + timedelta(hours=9*FREQ)).strftime(FMT_MON_HR))

def test_hour_to_step(FigureHandler):
    assert FigureHandler.hour_to_step(0) == 0
    assert FigureHandler.hour_to_step(3) == int(3/FREQ)
    assert FigureHandler.hour_to_step(6) == int(6/FREQ)
    assert FigureHandler.hour_to_step(36) == int(36/FREQ)

def test_retrieve_var_tstep(FigureHandler):
    assert FigureHandler.retrieve_var_tstep(varname='OD550_DUST', tstep=0, hour=None, static=True, aspect=(1,1), center=None, selected_tiles='carto-positron', zoom=None, layer=None, tag='empty').children[0].id == {'tag': 'model-tile-layer', 'index': 'median'}
    assert FigureHandler.retrieve_var_tstep(varname='OD550_DUST', tstep=0, hour=None, static=True, aspect=(1,1), center=None, selected_tiles='carto-positron', zoom=None, layer=None, tag='empty').children[3].classes == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    assert str(FigureHandler.retrieve_var_tstep(varname='OD550_DUST', tstep=0, hour=None, static=True, aspect=(1,1), center=None, selected_tiles='carto-positron', zoom=None, layer=None, tag='empty').children[4].children) == "P(B(['MULTI-MODEL Dust Optical Depth (550nm)', Br(None), 'Valid: {edate} (H+00)']))".format(edate=EDATE_OBJ.strftime(FMT_MON_HR))

# =================== Scores Figure Handler ============================
@pytest.fixture
def ScoresFigureHandler():
    return code.ScoresFigureHandler('aeronet', 'bias', '{edate}'.format(edate=EDATE_OBJ.strftime("%Y%m")))

def test_get_mapbox(ScoresFigureHandler):
    assert ScoresFigureHandler.get_mapbox('carto-positron', False, 2.8, None)['bearing'] == 0
    assert ScoresFigureHandler.get_mapbox('carto-positron', False, 2.8, None)['pitch'] == 0
    assert ScoresFigureHandler.get_mapbox('carto-positron', False, 2.8, None)['uirevision'] == True
    assert ScoresFigureHandler.get_mapbox('carto-positron', False, 2.8, None)['zoom'] == 2.8
    assert str(ScoresFigureHandler.get_mapbox('carto-positron', False, 2.8, None)['center']) == "layout.mapbox.Center({\n    'lat': 33.5, 'lon': 16.5\n})"

def test_generate_trace(ScoresFigureHandler):
    stats = ['Lille', 'Mainz', 'Palaiseau', 'Paris', 'Kyiv']
    vals = [-0.11, -0.12, -0.07, -0.09, -0.14]
    assert ScoresFigureHandler.generate_trace(35, 35, stats, vals)['name'] == 'MBE'
    assert ScoresFigureHandler.generate_trace(35, 35, stats, vals)['marker']['cmin'] == -0.1
    assert ScoresFigureHandler.generate_trace(35, 35, stats, vals)['marker']['cmax'] == 0.1
    assert ScoresFigureHandler.generate_trace(35, 35, stats, vals)['marker']['colorbar']['x'] == 0.94

def test_retrieve_scores(ScoresFigureHandler):
    assert ScoresFigureHandler.retrieve_scores('median', aspect=(1,1), center=None).data[1].name == 'MBE'  
    assert ScoresFigureHandler.retrieve_scores('median', aspect=(1,1), center=None).data[1].type == 'scattermapbox'  

# =================== Vis Handler ============================
@pytest.fixture
def VisFigureHandler():
    return code.VisFigureHandler(END_DATE)

# def test_set_data(VisFigureHandler):
#     assert VisFigureHandler.set_data(0)[5][1][0] == [11]
#     assert VisFigureHandler.set_data(0)[5][3][0][1] == 1
#     assert VisFigureHandler.set_data(24) == ([], [], [], [], [], ())
#     assert VisFigureHandler.set_data(36) == ([], [], [], [], [], ())

def test_generate_var_tstep_trace(VisFigureHandler):
    returned = VisFigureHandler.generate_var_tstep_trace([], [], [], [], [], (), ('#714921', '#da7230', '#fcd775', 'CadetBlue'), ('<1 km', '1 - 2 km', '2 - 5 km', 'Haze'), ('o', 'o', 'o', '^'), 6)
    assert len(returned) == 2
    assert str(type(returned[0])) == "<class 'pandas.core.frame.DataFrame'>"
    assert returned[1][1].id == 'vis-info'
    assert returned[1][1].children ==['NO DATA AVAILABLE']
    assert returned[1][0].data['type'] == 'FeatureCollection'

def test_vis_get_title(VisFigureHandler):
    assert str(VisFigureHandler.get_title(tstep=0)) =="['Visibility reduced by airborne dust', Br(None), '{edate} 00-06 UTC']".format(edate=EDATE_OBJ.strftime(FMT_FULLMON))
    assert str(VisFigureHandler.get_title(tstep=9)) =="['Visibility reduced by airborne dust', Br(None), '{edate} 09-15 UTC']".format(edate=EDATE_OBJ.strftime(FMT_FULLMON))
    assert str(VisFigureHandler.get_title(tstep=39)) =="['Visibility reduced by airborne dust', Br(None), '{edate} 39-45 UTC']".format(edate=EDATE_OBJ.strftime(FMT_FULLMON))
    assert str(VisFigureHandler.get_title(tstep=72)) =="['Visibility reduced by airborne dust', Br(None), '{edate} 72-78 UTC']".format(edate=EDATE_OBJ.strftime(FMT_FULLMON))

def test_vis_retrieve_var_tstep(VisFigureHandler):
    result = VisFigureHandler.retrieve_var_tstep(tstep=0, hour=None, static=True, aspect=(1,1), center=None)
    assert str(type(result[0])) == "<class 'pandas.core.frame.DataFrame'>"
    assert result[1][0].data['type'] =='FeatureCollection'

    result = VisFigureHandler.retrieve_var_tstep(tstep=1, hour=1, static=True, aspect=(1,1), center=None)
    assert str(type(result[0])) == "<class 'pandas.core.frame.DataFrame'>"
    assert result[1][0].data['type'] =='FeatureCollection'

# =================== Prob Handler ============================
@pytest.fixture
def ProbFigureHandler():
    return code.ProbFigureHandler('OD550_DUST', 0.1, END_DATE)

# def test_prob_set_data(ProbFigureHandler):
#     assert ProbFigureHandler.set_data('OD550_DUST', tstep=0)[0].data[0] == -24.75
#     assert ProbFigureHandler.set_data('OD550_DUST', tstep=0)[0].data[9] == -20.25
#     assert ProbFigureHandler.set_data('OD550_DUST', tstep=0)[1].data[9] == 5.25

def test_prob_retrieve_cdatetime(ProbFigureHandler):
    assert str(ProbFigureHandler.retrieve_cdatetime(tstep=0)) == '{edate} 00:00:00'.format(edate=EDATE_OBJ.strftime(FMT_DASH))
    assert str(ProbFigureHandler.retrieve_cdatetime(tstep=1)) == '{edate} 00:00:00'.format(edate=(EDATE_OBJ + timedelta(days=1)).strftime(FMT_DASH))

def test_prob_generate_contour_tstep_trace_AOD(ProbFigureHandler):
    #test day 0
    assert ProbFigureHandler.generate_contour_tstep_trace('OD550_DUST', tstep=0)[0].url == '/dashboard/assets/geojsons/prob/od550_dust/0.1/geojson/{edate}/00_{edate}_OD550_DUST.geojson'.format(edate=END_DATE)
    assert ProbFigureHandler.generate_contour_tstep_trace('OD550_DUST', tstep=0)[0].options == {'style': {'variable': 'forecastTab.forecastMaps.styleHandle'}}
    assert ProbFigureHandler.generate_contour_tstep_trace('OD550_DUST', tstep=0)[1].classes ==[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    #test day 1
    assert ProbFigureHandler.generate_contour_tstep_trace('OD550_DUST', tstep=1)[0].url == '/dashboard/assets/geojsons/prob/od550_dust/0.1/geojson/{edate}/01_{edate}_OD550_DUST.geojson'.format(edate=END_DATE)
    assert ProbFigureHandler.generate_contour_tstep_trace('OD550_DUST', tstep=1)[0].options == {'style': {'variable': 'forecastTab.forecastMaps.styleHandle'}}
    assert ProbFigureHandler.generate_contour_tstep_trace('OD550_DUST', tstep=1)[1].classes ==[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def test_prob_generate_contour_tstep_trace_SCONC(ProbFigureHandler):
    #test day 0
    assert ProbFigureHandler.generate_contour_tstep_trace('SCONC_DUST', tstep=0)[0].url == '/dashboard/assets/geojsons/prob/od550_dust/0.1/geojson/{edate}/00_{edate}_OD550_DUST.geojson'.format(edate=END_DATE)
    assert ProbFigureHandler.generate_contour_tstep_trace('SCONC_DUST', tstep=0)[0].options == {'style': {'variable': 'forecastTab.forecastMaps.styleHandle'}}
    assert ProbFigureHandler.generate_contour_tstep_trace('SCONC_DUST', tstep=0)[1].classes ==[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    #test day 1
    assert ProbFigureHandler.generate_contour_tstep_trace('SCONC_DUST', tstep=1)[0].url == '/dashboard/assets/geojsons/prob/od550_dust/0.1/geojson/{edate}/01_{edate}_OD550_DUST.geojson'.format(edate=END_DATE)
    assert ProbFigureHandler.generate_contour_tstep_trace('SCONC_DUST', tstep=1)[0].options == {'style': {'variable': 'forecastTab.forecastMaps.styleHandle'}}
    assert ProbFigureHandler.generate_contour_tstep_trace('SCONC_DUST', tstep=1)[1].classes == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def test_prob_get_title(ProbFigureHandler):
    assert ProbFigureHandler.get_title('OD550_DUST', tstep=0)[-30:] == '{edate} Valid: {edate}'.format(edate=EDATE_OBJ.strftime(FMT_MON))
    assert ProbFigureHandler.get_title('SCONC_DUST', tstep=1)[-30:] == '{edate} Valid: {edate_next}'.format(edate=EDATE_OBJ.strftime(FMT_MON), edate_next=(EDATE_OBJ + timedelta(days=1)).strftime(FMT_MON))

def test_prob_retrieve_var_tstep(ProbFigureHandler):
    assert ProbFigureHandler.retrieve_var_tstep('OD550_DUST', 0, True, (1,1))[0].url == '/dashboard/assets/geojsons/prob/od550_dust/0.1/geojson/{edate}/00_{edate}_OD550_DUST.geojson'.format(edate=END_DATE)
    assert ProbFigureHandler.retrieve_var_tstep('OD550_DUST', 1, True, (1,1))[0].options == {'style': {'variable': 'forecastTab.forecastMaps.styleHandle'}}

    assert ProbFigureHandler.retrieve_var_tstep('SCONC_DUST', 1, True, (1,1))[0].url =='/dashboard/assets/geojsons/prob/od550_dust/0.1/geojson/{edate}/01_{edate}_OD550_DUST.geojson'.format(edate=END_DATE)
    assert ProbFigureHandler.retrieve_var_tstep('SCONC_DUST', 0, True, (1,1))[0].options == {'style': {'variable': 'forecastTab.forecastMaps.styleHandle'}}


# =================== Was Handler ============================
@pytest.fixture
def WasFigureHandler():
    return code.WasFigureHandler(was='burkinafaso', model='median', variable='SCONC_DUST', selected_date=END_DATE)

def test_was_get_regions_data(WasFigureHandler):
    #day 1
    assert WasFigureHandler.get_regions_data(day=1)[0][0] == 'Boucle du Mouhoun'
    assert WasFigureHandler.get_regions_data(day=1)[0][1] == 'Cascades'
    assert WasFigureHandler.get_regions_data(day=1)[0][-1] == 'Sud-Ouest'

    assert WasFigureHandler.get_regions_data(day=1)[1][0] == 'green'
    assert WasFigureHandler.get_regions_data(day=1)[1][1] == 'green'
    assert WasFigureHandler.get_regions_data(day=1)[1][-1] == 'green'

    assert WasFigureHandler.get_regions_data(day=1)[2][0] == 'Normal'
    assert WasFigureHandler.get_regions_data(day=1)[2][1] == 'Normal'
    assert WasFigureHandler.get_regions_data(day=1)[2][-1] =='Normal'

    #day 2
    assert WasFigureHandler.get_regions_data(day=2)[0][0] == 'Boucle du Mouhoun'
    assert WasFigureHandler.get_regions_data(day=2)[0][1] == 'Cascades'
    assert WasFigureHandler.get_regions_data(day=2)[0][-1] == 'Sud-Ouest'

    assert WasFigureHandler.get_regions_data(day=2)[1][0] == 'green'
    assert WasFigureHandler.get_regions_data(day=2)[1][1] == 'green'
    assert WasFigureHandler.get_regions_data(day=2)[1][-1] == 'green'

    assert WasFigureHandler.get_regions_data(day=2)[2][0] == 'Normal'
    assert WasFigureHandler.get_regions_data(day=2)[2][1] == 'Normal'
    assert WasFigureHandler.get_regions_data(day=2)[2][-1] =='Normal'

def test_was_get_geojson_url(WasFigureHandler):
    assert WasFigureHandler.get_geojson_url(day=1) == '/dashboard/assets/geojsons/was/burkinafaso/geojson/{edate}/{edate}_SCONC_DUST_1.geojson'.format(edate=END_DATE)
    assert WasFigureHandler.get_geojson_url(day=2) == '/dashboard/assets/geojsons/was/burkinafaso/geojson/{edate}/{edate}_SCONC_DUST_2.geojson'.format(edate=END_DATE)
    
def test_was_retrieve_cdatetime(WasFigureHandler):
    assert str(WasFigureHandler.retrieve_cdatetime(tstep=0)) == '{edate} 00:00:00'.format(edate=EDATE_OBJ.strftime(FMT_DASH))

def test_was_generate_contour_tstep_trace(WasFigureHandler):
    assert WasFigureHandler.generate_contour_tstep_trace(1)[0].options == {'style': {'variable': 'forecastTab.wasMaps.styleHandle'}}
    assert WasFigureHandler.generate_contour_tstep_trace(1)[0].url == '/dashboard/assets/geojsons/was/burkinafaso/geojson/{edate}/{edate}_SCONC_DUST_1.geojson'.format(edate=END_DATE)
    assert WasFigureHandler.generate_contour_tstep_trace(1)[1].className == 'was-legend'

    assert WasFigureHandler.generate_contour_tstep_trace(2)[0].options == {'style': {'variable': 'forecastTab.wasMaps.styleHandle'}}
    assert WasFigureHandler.generate_contour_tstep_trace(2)[0].url == '/dashboard/assets/geojsons/was/burkinafaso/geojson/{edate}/{edate}_SCONC_DUST_2.geojson'.format(edate=END_DATE)
    assert WasFigureHandler.generate_contour_tstep_trace(2)[1].className == 'was-legend'
    
def test_was_get_title(WasFigureHandler):
    assert str(WasFigureHandler.get_title(0)) =="Barcelona Dust Regional Center - Burkina Faso WAS.<br>Expected concentration of airborne dust.<br>Issued: {edate}. Valid: {edate}".format(edate=EDATE_OBJ.strftime(FMT_MON))
    assert str(WasFigureHandler.get_title(1)) =="Barcelona Dust Regional Center - Burkina Faso WAS.<br>Expected concentration of airborne dust.<br>Issued: {edate}. Valid: {edate_next}".format(edate=EDATE_OBJ.strftime(FMT_MON), edate_next=(EDATE_OBJ + timedelta(days=1)).strftime(FMT_MON))

def test_was_retrieve_var_tstep(WasFigureHandler):
    assert WasFigureHandler.retrieve_var_tstep(1, True, (1,1))[0].url =='/dashboard/assets/geojsons/was/burkinafaso/geojson/{edate}/{edate}_SCONC_DUST_1.geojson'.format(edate=END_DATE)
    assert WasFigureHandler.retrieve_var_tstep(1, True, (1,1))[0].options =={'style': {'variable': 'forecastTab.wasMaps.styleHandle'}}
    assert WasFigureHandler.retrieve_var_tstep(2, True, (1,1))[0].url =='/dashboard/assets/geojsons/was/burkinafaso/geojson/{edate}/{edate}_SCONC_DUST_2.geojson'.format(edate=END_DATE)
    assert WasFigureHandler.retrieve_var_tstep(2, True, (1,1))[0].options =={'style': {'variable': 'forecastTab.wasMaps.styleHandle'}}
