import os
import sys

current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(current_dir)
lambda_layers_path = os.path.join(parent_dir, '..', 'ramh-lambda-layers')
sys.path.insert(0, lambda_layers_path)
from container import db_repo, s3_repo, bucket

import datetime as dt
import json
from decimal import Decimal
from json import JSONEncoder

import requests

import admData
import apiCalls
import query

queries = query


def send_json(url, data):
    headers = {'Content-Type': 'application/json'}
    response = requests.post(url, headers=headers, data=json.dumps(data))
    return response


def getPdc():
    return (db_repo.query(queries.pdc))


def getAcledGeojson():
    results = db_repo.query(queries.acled)
    geo_json = {
        'type': 'FeatureCollection',
        'features': [{
            'type': 'Feature',
            'geometry': {
                'type': 'Point',
                'coordinates': [item['longitude'], item['latitude']]
            },
            'properties': {
                'count': item['count'],
                'event_type': item['event_type']
            }
        } for item in results]
    }
    return (geo_json)


def getUndernourishmentTotal():
    return (db_repo.query(queries.undernourishmentTotal))


def getIpcScatterData():
    return (db_repo.query(queries.ipcGlobal))


def post_process_undernourishment(data):
    china_value = None

    for item in data:
        if item['adm0_code'] == 53:
            china_value = item['value']
            break

    mapped_data = []
    for item in data:
        adm0_code = item['adm0_code']
        value = item['value']

        if adm0_code in [15, 2]:
            new_value = 10
        elif adm0_code in [149, 33364, 147296]:
            new_value = china_value
        else:
            new_value = value

        mapped_data.append({'adm0_code': adm0_code, 'value': new_value})

    special_codes = [15, 2]
    for code in special_codes:
        if not any(item['adm0_code'] == code for item in mapped_data):
            mapped_data.append({'adm0_code': code, 'value': 10})

    return mapped_data


def getAdm0Info(blacklisted_adm0s, visibility_blacklist_iso3):
    try:
        adm0_data = admData.getAdm0()
        undernourishment_data = db_repo.query(queries.undernourishment)
        ipc_population = db_repo.query(queries.ipcPopulation)
        ipc_admin_areas = db_repo.query(queries.ipcAdm0Areas)
        income_levels = db_repo.query(queries.countryIncomeLevels)
        alerts = apiCalls.getAdm0Alerts()
        centroids = db_repo.query(queries.adm0Centroids)
        adm0_data_types = db_repo.query(queries.adm0DataTypes)
    except Exception as e:
        return ({'error': f"Error retrieving data: {e}"})

    undernourishment_data = post_process_undernourishment(undernourishment_data)
    # undernourishment_by_adm0 = {item['adm0_code']: item['value'] for item in undernourishment_data}
    undernourishment_by_adm0 = {}
    for item in undernourishment_data:
        adm0_code = item['adm0_code']
        value = item['value']
        undernourishment_by_adm0[adm0_code] = value

    # ipc_population_by_adm0 = {item['adm0_code']: item['ipc_popnmbr'] for item in ipc_population}
    ipc_population_by_adm0 = {}
    for item in ipc_population:
        adm0_code = item['adm0_code']
        ipc_popnmbr = item['ipc_popnmbr']
        ipc_population_by_adm0[adm0_code] = {
            'ipc_popnmbr': float(ipc_popnmbr)
        }

    # ipc_areas_by_adm0 = {item['adm0_code']: item['analysis_id'] for item in ipc_admin_areas}
    ipc_areas_by_adm0 = {}
    for item in ipc_admin_areas:
        adm0_code = item['adm0_code']
        analysis_id = item['analysis_id']
        ipc_areas_by_adm0[adm0_code] = {
            'analysis_id': analysis_id
        }

    income_levels_by_iso3 = {item['iso3']: item['income_level'] for item in income_levels}

    default_alerts = {
        'covid': False,
        # 'fcs': False,
        'marketAccess': False,
        'conflict': False,
        'ndvi': False,
        'climateDry': False,
        'climateWet': False
    }

    alerts_by_adm0 = {}
    for alert in alerts:
        alert_type = {}
        type_ = alert['type']
        if type_ == 'COVID_INCIDENCE_HIGH':
            alert_type = {'covid': True}
        elif type_ == 'FCS_DETERIORATION_HIGH':
            alert_type = {'fcs': True}
        elif type_ == 'MARKET_ACCESS_PREVALENCE_HIGH':
            alert_type = {'marketAccess': True}
        elif type_ == 'CONFLICT_FATALITIES_INCIDENCE_HIGH':
            alert_type = {'conflict': True}
        elif type_ == 'CLIMATE_MIN_NDVI_ANOMALY_HIGH':
            alert_type = {'ndvi': True}
        elif type_ == 'CLIMATE_PEOPLE_PREVALENCE_DRY_AREAS_HIGH':
            alert_type = {'climateDry': True}
        elif type_ == 'CLIMATE_PEOPLE_PREVALENCE_WET_AREAS_HIGH':
            alert_type = {'climateWet': True}

        country_id = alert['country']['id']
        country_alerts = alerts_by_adm0.get(country_id, default_alerts)
        alerts_by_adm0[country_id] = {**country_alerts, **alert_type}

    # centroids_by_adm0 = {item['adm0_code']: {'latitude': item['latitude'], 'longitude': item['longitude']} for item in centroids}
    centroids_by_adm0 = {}
    for item in centroids:
        latitude = item['latitude']
        longitude = item['longitude']
        adm0_code = item['adm0_code']
        centroids_by_adm0[adm0_code] = {
            'latitude': latitude,
            'longitude': longitude
        }

    data_types_by_adm0 = {}
    for item in adm0_data_types:
        adm0_code = item['adm0_code']
        data_types_by_adm0[adm0_code] = 'MIXED' if adm0_code in data_types_by_adm0 else item['data_type']

    for feature in adm0_data['features']:
        properties = feature['properties']
        iso3 = properties.get('iso3')
        adm0_id = properties.get('adm0_id')

        if str(iso3) not in visibility_blacklist_iso3:
            properties['interactive'] = True

        properties['undernourishment'] = undernourishment_by_adm0.get(adm0_id, None)
        properties['ipcPopulation'] = ipc_population_by_adm0.get(str(adm0_id), {}).get('ipc_popnmbr', None)
        properties['ipcAreasAnalysis'] = ipc_areas_by_adm0.get(str(adm0_id), {}).get('analysis_id', None)
        properties['incomeLevel'] = income_levels_by_iso3.get(iso3, None)
        properties['alerts'] = alerts_by_adm0.get(adm0_id, default_alerts)
        properties['centroid'] = centroids_by_adm0.get(str(adm0_id), {})
        properties['dataType'] = data_types_by_adm0.get(adm0_id, None)

    return (adm0_data)


# def getAdm1Fcs(adm0_id):
#     result = db_repo.query(queries.fcsDataTypesPerCountry, adm0_id)
#     data_types = int(result[0].get('data_types', None))
#     r = db_repo.query(queries.fcsAdm1(data_types), [int(adm0_id), int(adm0_id)])
#     return r


# def getCountryFcs(adm0_id, months_less):
#     result = db_repo.query(queries.fcsDataTypesPerCountry, [adm0_id])
#     data_types = int(result[0].get('data_types', None))
#     r = db_repo.query(queries.fcsCountryTotal2(data_types, months_less, adm0_id))
#     return r


# def getCountryFcsRcsiGraphData(adm0_id):
#     result = db_repo.query(queries.fcsDataTypesPerCountry, [adm0_id])
#     data_types = int(result[0].get('data_types', None))
#     r = db_repo.query(queries.fcsRcsiGraph(0, data_types), [adm0_id, adm0_id, adm0_id])
#     return r


def getAreasIpc(adm0_id):
    if not (int(adm0_id) > 0):
        return ({'Error': 'Not found'}), 500
    ipc_data = db_repo.query(queries.ipcAreasData, [adm0_id])

    if len(ipc_data) < 0:
        return ({'Error': 'Not found'}), 500

    ipc_data_by_area = {item['area_id']: item for item in ipc_data}
    analysis_id = ipc_data[0]['analysis_id']
    # object_path = f'hunger_map/ipc/{analysis_id}.geojson'
    object_path = f's3://{bucket}/hunger_map/ipc/{analysis_id}.geojson'

    try:
        # aws_client = Aws()
        areas_geo_data = json.loads(s3_repo.find(object_path))
        areas_geo_data['features'] = [
            feature for feature in areas_geo_data['features']
            if feature['geometry']['type'] == "Polygon" or feature['geometry']['type'] == "MultiPolygon"
        ]

        for feature in areas_geo_data['features']:
            area_id = feature['properties']['area_id']
            ipc_data = ipc_data_by_area.get(area_id)

            feature['properties']['areaName'] = ipc_data['area_name'] if ipc_data and 'area_name' in ipc_data else None
            feature['properties']['ipcPhase'] = ipc_data['phase'] if ipc_data and 'phase' in ipc_data else None
            feature['properties']['ipcValidity'] = ipc_data[
                'analysis_period'] if ipc_data and 'analysis_period' in ipc_data else None
            feature['properties']['ipcDate'] = str(
                ipc_data['analysis_date']) if ipc_data and 'analysis_date' in ipc_data else None

        return (areas_geo_data)
    except Exception as e:
        print(f"Error fetching object from S3: {e}")
        return ({'error': f'Error retrieving data: {e}'}), 500


def getCountryData(adm0_id):
    news_adm0_list = [adm0_id]
    news_adm0_list_len = len(news_adm0_list)

    if adm0_id == admData.WEST_BANK_ADM0_CODE:
        news_adm0_list.append(admData.GAZA_ADM0_CODE)

    try:
        population = db_repo.query(queries.countryPopulation, [adm0_id])
        # country_fcs = getCountryFcs(adm0_id, 0)
        # country_fcs1 = getCountryFcs(adm0_id, 1)
        # country_fcs3 = getCountryFcs(adm0_id, 3)
        import_dependency_raw = db_repo.query(queries.importDependency, [adm0_id])
        # fcs_rcsi_graph_data = getCountryFcsRcsiGraphData(adm0_id)
        news_data = db_repo.query(queries.news(news_adm0_list_len), news_adm0_list)

        data = {
            'population': population[0]['value'] if len(population) == 1 else None,
            'populationSource': population[0]['source'] if len(population) == 1 else None,
            # 'fcs': country_fcs[0]['value'] if len(country_fcs) == 1 else None,
            # 'fcsMinus1': country_fcs1[0]['value'] if len(country_fcs1) == 1 else None,
            # 'fcsMinus3': country_fcs3[0]['value'] if len(country_fcs3) == 1 else None,
            'importDependency': import_dependency_raw[0]['value'] if len(import_dependency_raw) == 1 else None,
            # 'fcsGraph': [
            #     {'x': item['x'], 'fcs': item['fcs'], 'fcsHigh': item['fcs_upper_bound'], 'fcsLow': item['fcs_lower_bound']}
            #     for item in fcs_rcsi_graph_data
            # ],
            # 'rcsiGraph': [
            #     {'x': item['x'], 'rcsi': item['rcsi'], 'rcsiHigh': item['rcsi_upper_bound'], 'rcsiLow': item['rcsi_lower_bound']}
            #     for item in fcs_rcsi_graph_data
            # ],
            'news': [
                {'author': item['author'], 'title': item['title'], 'description': item['description'], 'url': item['url'],
                 'image': item['urlToImage'], 'publishedAt': item['publishedAt'], 'content': item['content']}
                for item in news_data
            ]
        }

        return data

    except Exception as e:
        return json.dumps({'error': 'Error retrieving data', 'details': str(e)})


def getIso3CountryData(iso3):
    try:
        nutrition_data = db_repo.query(queries.nutritionData, [iso3])
        currency_exchange_data = db_repo.query(queries.currencyExchange, [iso3])
        currency_exchange_unofficial_data = db_repo.query(queries.currencyExchangeUnofficial, [iso3])
        balance_of_trade_data = db_repo.query(queries.balanceOfTrade, [iso3])
        headline_food_inflation_data = db_repo.query(queries.headlineFoodInflation, [iso3, iso3])

        currenency_exchange = currency_exchange_unofficial_data if currency_exchange_unofficial_data else currency_exchange_data

        data = {
            'nutrition': {
                'wasting': nutrition_data[0]['wasting'] if nutrition_data else None,
                'stunting': nutrition_data[0]['stunting'] if nutrition_data else None,
                'source': nutrition_data[0]['source'] if nutrition_data else '',
            },
            'currencyExchangeGraph': {
                'name': currenency_exchange[0]['economicdatasymbol'] if currenency_exchange else '',
                'source': 'WFP' if currency_exchange_unofficial_data else 'Trading Economics',
                'updated': 'Monthly' if currency_exchange_unofficial_data else 'Daily',
                'data': [{'x': item['x'], 'y': item['economicdatavalue']} for item in
                         currenency_exchange] if currenency_exchange else []
            },
            'balanceOfTradeGraph': {
                'data': balance_of_trade_data
            } if balance_of_trade_data else {
                'name': '',
                'data': []
            },
            'inflationGraphs': {
                'headline': {
                    'data': [{'x': item['x'], 'y': item['y']} for item in headline_food_inflation_data if item['type'] == 116]
                } if headline_food_inflation_data else {
                    'headline': {'data': []},
                    'food': {'data': []}
                },
                'food': {
                    'data': [{'x': item['x'], 'y': item['y']} for item in headline_food_inflation_data if item['type'] == 71]
                } if headline_food_inflation_data else {
                    'headline': {'data': []},
                    'food': {'data': []}
                }
            }
        }

        return data

    except Exception as e:
        return json.dumps({'error': 'Error retrieving data', 'details': str(e)})


def getAdm1Info(adm0_id):
    bd = get_blacklisted_data()
    if int(adm0_id) <= 0 or int(adm0_id) in bd[0]:
        return ({'Error': 'Not found'}), 404

    try:
        result = db_repo.query(queries.fcsDataTypesPerCountry, [adm0_id])
        data_types = result[0].get('data_types') if result else None

        if not data_types:
            raise ValueError("Data types not found")

        fcs_data_task = getAdm1Fcs(adm0_id)
        adm1_data_task = admData.getAdm1(adm0_id)
        fcs_rcsi_graph_task = db_repo.query(queries.fcsRcsiGraph(1, data_types), [adm0_id, adm0_id, adm0_id])
        fcs_data = fcs_data_task
        adm1_data = adm1_data_task
        fcs_rcsi_graph_data = fcs_rcsi_graph_task

        fcs_by_adm1 = {item['adm1_code']: {k: v for k, v in item.items() if k != 'adm1_code'} for item in fcs_data}
        fsc_graph_by_adm1 = {}
        for item in fcs_rcsi_graph_data:
            adm1_code = item['adm1_code']
            if adm1_code not in fsc_graph_by_adm1:
                fsc_graph_by_adm1[adm1_code] = []
            fsc_graph_by_adm1[adm1_code].append(item)
        for feature in adm1_data['features']:
            properties = feature['properties']
            code = properties.get('Code')

            if code in fcs_by_adm1:
                fcs_data = fcs_by_adm1[code]
                properties['fcs'] = {
                    'score': fcs_data.get('fcs_score'),
                    'scoreLow': fcs_data.get('fcs_score_lower_bound'),
                    'scoreHigh': fcs_data.get('fcs_score_upper_bound'),
                    'ratio': fcs_data.get('fcs_ratio'),
                    'ratioLow': fcs_data.get('fcs_ratio_lower_bound'),
                    'ratioHigh': fcs_data.get('fcs_ratio_upper_bound'),
                    'people': fcs_data.get('fcs_people'),
                    'peopleLow': fcs_data.get('fcs_people_lower_bound'),
                    'peopleHigh': fcs_data.get('fcs_people_upper_bound'),
                    'dataType': fcs_data.get('data_type'),
                }
                properties['centroid'] = {
                    'latitude': fcs_data.get('latitude'),
                    'longitude': fcs_data.get('longitude')
                }
                properties['rcsi'] = {
                    'ratio': fcs_data.get('rcsi_ratio'),
                    'ratioLow': fcs_data.get('rcsi_ratio_lower_bound'),
                    'ratioHigh': fcs_data.get('rcsi_ratio_upper_bound'),
                    'people': fcs_data.get('rcsi_people'),
                    'peopleLow': fcs_data.get('rcsi_people_lower_bound'),
                    'peopleHigh': fcs_data.get('rcsi_people_upper_bound')
                }
                properties['fcsGraph'] = [
                    {
                        'x': item['x'],
                        'fcs': item['fcs'],
                        'fcsHigh': item.get('fcs_upper_bound'),
                        'fcsLow': item.get('fcs_lower_bound')
                    } for item in fsc_graph_by_adm1.get(code, [])
                ]
            else:
                properties['fcs'] = None
                properties['centroid'] = None
                properties['rcsi'] = None
                properties['fcsGraph'] = None

        return (adm1_data)

    except Exception as e:
        return ({'error': 'Error retrieving data', 'details': str(e)})


def getChangelog():
    return (db_repo.query(queries.changeLog))


def getMimiCountries(event):
    data = db_repo.query(queries.mimiCountries)
    return data


def getMimiCountryData(iso3):
    return (db_repo.query(queries.mimiCountryData, [iso3]))


def getIso3CountryNotes(iso3):
    return (db_repo.query(queries.countryNotes, [iso3]))


def getAdm1WithNutrition(adm0_id):
    try:
        nutrition = db_repo.query(queries.mimiCountryData, [adm0_id])

        adm1_data = admData.getAdm1Nutrition(adm0_id)

        for feature in adm1_data['features']:
            feature['properties']['nutrition'] = {}
            for n in nutrition:
                if feature['properties']['Code'] == n['adm1_code']:
                    feature['properties']['nutrition'] = {
                        'fe_ai': n['fe_ai'],
                        'fol_ai': n['fol_ai'],
                        'mimi_simple': n['mimi_simple'],
                        'va_ai': n['va_ai'],
                        'vb12_ai': n['vb12_ai'],
                        'zn_ai': n['zn_ai'],
                    }

        return (adm1_data)

    except Exception as e:
        return json.dumps({'error': 'Error retrieving ADM1 with nutrition', 'details': str(e)})


def get_blacklisted_data():
    country_blacklist = db_repo.query(queries.countryBlacklist)
    visibility_blacklist = db_repo.query(queries.countryVisibilityBlacklist)

    blacklisted_adm0s = {row['adm0_code']: True for row in country_blacklist}
    blacklisted_iso3s = {row['iso3']: True for row in country_blacklist}
    visibility_blacklist_iso3 = {row['iso3']: True for row in visibility_blacklist}

    return blacklisted_adm0s, blacklisted_iso3s, visibility_blacklist_iso3


# @app.get("/adm0data.json")
def adm0_data(event):
    bd = get_blacklisted_data()

    return getAdm0Info(bd[0], bd[1])


# @app.get("/adm0/<adm0_id>/adm1data.json")
def adm1_data(event, adm0Id=None):
    bd = get_blacklisted_data()
    if int(adm0Id) <= 0 or int(adm0Id) in bd[0]:
        return ({'Error': 'Not found'}), 404
    return getAdm1Info(adm0Id)


# @app.get("/adm0/<adm0_id>/countryData.json")
def country_data(event, adm0Id=None):
    bd = get_blacklisted_data()
    if int(adm0Id) <= 0 or int(adm0Id) in bd[0]:
        return ({'Error': 'Not found'}), 404
    return getCountryData(adm0Id)


# @app.get("/iso3/<iso3>/countryIso3Data.json")
def iso3_country_data(event, iso3=None):
    bd = get_blacklisted_data()
    if iso3 in bd[1]:
        return ({'Error': 'Not found'}), 404
    return getIso3CountryData(iso3)


# @app.get("/iso3/<iso3>/countryIso3Notes.json")
def iso3_country_notes(event, iso3=None):
    return getIso3CountryNotes(iso3)


# @app.get("/adm0/<adm0_id>/ipc.geojson")
def areas_ipc(event, adm0Id=None):
    return getAreasIpc(adm0Id)


# @app.get("/adm1/fcs.json")
def all_adm1_fcs(event):
    return getAllAdm1Fcs()


# @app.get("/pdc.json")
def pdc(event):
    return getPdc()


# @app.get("/acled.geojson")
def acled_geojson(event):
    return getAcledGeojson()


# @app.get("/ipc.json")
def ipc_scatter_data(event):
    return getIpcScatterData()


# @app.get("/undernourishment.json")
def undernourishment_total(event):
    return getUndernourishmentTotal()


class ResponseEncoder(JSONEncoder):
    def default(self, o):
        if isinstance(o, dt.datetime):
            return o.strftime('%Y-%m-%d %H:%M:%S')
        if isinstance(o, dt.date):
            return o.strftime('%Y-%m-%d')
        if isinstance(o, Decimal):
            return int(o)
        return super().default(o)


# TODO move to class
def response(body, status_code=200):
    """Return an API Gateway compliant response"""
    return json.dumps({
        'statusCode': str(status_code),
        'body': body
    }, cls=ResponseEncoder)


# @app.get("/changelog.json")
def changelog(event):
    change_log = getChangelog()
    return change_log


# @app.get("/mimiCountries.json")
# def mimi_countries():
#     return getMimiCountries()

# @app.get("/iso3/<iso3>/mimiCountryData.json")
def mimi_country_data(event, iso3=None):
    return getMimiCountryData(iso3)


# @app.get("/adm0Id/<adm0_id>/mimiAdm1CountryData.json")
def adm1_with_nutrition(event, adm0Id=None):
    return getAdm1WithNutrition(adm0Id)

# if __name__ == '__main__':
#     app.run()


The task is: **Remove FCS Data Processing**:
    - Delete or comment out FCS-related data processing steps and dictionary creation logic (e.g., `fcs_by_adm0`).

Should the getAdm1Info function be completely deleted? Or if not and it only has to be modified, how?