import pytest
from unittest.mock import MagicMock, patch
from datetime import datetime
from datetime import timedelta
import importlib
code = importlib.import_module('ines_core_utils')
from datetime import datetime
from datetime import timedelta
import numpy as np
from map_handler import END_DATE
from map_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)

@pytest.fixture
def netcdf_data():
    return f'/data/products/median/netcdf/{END_DATE}_3H_MEDIAN.nc'

def test_concat_dataframes():
    assert code.concat_dataframes('expect_fail', ['AUG', 'SEP'], 'OD550_DUST', None, None) == (None, None)
#needs more tests

# def test_retrieve_single_point_1(netcdf_data):
#     result =  np.float32(0.031516124)
#     assert code.retrieve_single_point(netcdf_data, 1, 45, 45, 'OD550_DUST') == result
# 
# def test_retrieve_single_point_2(netcdf_data):
#     result =  np.float32(0.00066542445)
#     assert code.retrieve_single_point(netcdf_data, 9, 145, -45, 'OD550_DUST') == result
# 
# def test_retrieve_single_point_3(netcdf_data):
#     result =  np.float32(0.00046437158)
#     assert code.retrieve_single_point(netcdf_data, 1, -5, 175, 'OD550_DUST') == result

def test_retrieve_timeseries_1(netcdf_data):
    run = code.retrieve_timeseries(netcdf_data, 0, 0, 'OD550_DUST' , method='netcdf', forecast=False)
    assert run[0] == 0.25

def test_retrieve_timeseries_2(netcdf_data):
    run = code.retrieve_timeseries(netcdf_data, 45, 35, 'OD550_DUST' , method='netcdf', forecast=False)
    assert run[0] == 45.25

def test_retrieve_timeseries_3(netcdf_data):
    run = code.retrieve_timeseries(netcdf_data, 0, 0, 'OD550_DUST' , method='netcdf', forecast=False)
    assert run[-1].long_name == 'OD550_DUST'

def test_find_nearest():
    lst = np.array([-7.75, -6.25, -3, -1, 0, 1, 3.35, 5, 7])
    target = 2.5
    assert code.find_nearest(lst, target) == 3.35

    lst = np.array([-7.75, -6.25, -3, -1, 0, 1, 3.35, 5, 7])
    target = -5
    assert code.find_nearest(lst, target) == -6.25

    target = -50
    assert code.find_nearest(lst, target) == -7.75

# NOT USED
# def find_nearest2(array, value):

def test_calc_matrix():
    assert code.calc_matrix(0) == (1, 0)
    assert code.calc_matrix(1) == (1, 1)
    assert code.calc_matrix(2) == (2, 1)
    assert code.calc_matrix(3) == (2, 2)
    assert code.calc_matrix(4) == (2, 2)
    assert code.calc_matrix(5) == (3, 2)
    assert code.calc_matrix(6) == (3, 2)
    assert code.calc_matrix(9) == (3, 3)
    assert code.calc_matrix(12) == (4, 3)

def test_magnitude():
    assert code.magnitude(0)==0
    assert code.magnitude(1)==0
    assert code.magnitude(12)==1
    assert code.magnitude(20)==1
    assert code.magnitude(21)==1
    assert code.magnitude(211)==2
    assert code.magnitude(3112)==3
    assert code.magnitude(31124)==4

def test_normalize_vals():
    bounds = [-0.1, -0.08, -0.06, -0.04, -0.02, 0., 0.02, 0.04, 0.06, 0.08, 0.1]
    bounds = np.array(bounds).astype('float32')
    result = [0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ]
    magn = code.magnitude(bounds[-1])
    n_bounds = code.normalize_vals(bounds, bounds[0], bounds[-1], magn)
    assert np.array_equiv(n_bounds, np.array(result).astype('float32'))

    bounds = [0., 0.2, 0.4, 0.6, 0.8, 1., 1.2, 1.4, 1.6, 1.8, 2.]
    bounds = np.array(bounds).astype('float32')
    result = [0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ]
    magn = code.magnitude(bounds[-1])
    n_bounds = code.normalize_vals(bounds, bounds[0], bounds[-1], magn)
    assert np.array_equiv(n_bounds, np.array(result).astype('float32'))

def test_get_404_link_prod(monkeypatch):
    """ Test the production url"""
    # Mocking PATHNAME for testing
    mock_pathname = "/daily_dashboard/"  # Set your desired value for testing
    # Assign the mocked value to PATHNAME
    monkeypatch.setattr("ines_core_utils.PATHNAME", mock_pathname)
    assert code.get_404_link('forecast') == 'https://dust.aemet.es/products/daily-dust-products/?tab=forecast'
    assert code.get_404_link('evaluation') == 'https://dust.aemet.es/products/daily-dust-products/?tab=evaluation'
    assert code.get_404_link('observations') == 'https://dust.aemet.es/products/daily-dust-products/?tab=observations'

def test_get_404_link_dev():
    """ Test the dev url"""
    assert code.get_404_link('forecast') == ('/dashboard//?tab=forecast',)
    assert code.get_404_link('evaluation') == ('/dashboard//?tab=evaluation',)
    assert code.get_404_link('observations') == ('/dashboard//?tab=observations',)

def test_render404():
    assert "Div(children=[Div(children=[H2(children='404 Error', id='error_title')" in str(code.render404()[0])
    assert "P('Here are some links that might help:'), Link(children='Forecast', href=('/dashboard//?tab=forecast',), target='_parent', refresh=True, className='error_links', id='forecast_link'), Br(None), Br(None), Link(children='Evaluation', href=('/dashboard//?tab=evaluation',), target='_parent', refresh=True, className='error_links', id='evaluation_link'), Br(None), Br(None), Link(children='Observations', href=('/dashboard//?tab=observations',), target='_parent', refresh=True, className='error_links', id='observations_link')], id='error_div')], className='background')" in str(code.render404()[0])

def test_extend_list():
    assert code.extend_list([[1],[2],[3]]) == [1,2,3]
