'''This module gets the peer group for a bank'''
from math import radians
import sys
import pandas as pd
from numpy import cos, sin, arcsin, sqrt
import requests
from create_setup import Setup

def haversine(row, banklong, banklat):
    '''Calculates the distance between two points on a sphere using the haversine formula'''
    lon1 = banklong
    lat1 = banklat
    lon2 = row['longitude']
    lat2 = row['latitude']
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * arcsin(sqrt(a))
    mi = 3956 * c
    return mi

def get_bank_info(setup: Setup):
    '''Gets the peer group for a bank'''
    url = 'https://api.fdic.gov/banks/institutions?filters=ACTIVE%3A1&fields=ZIP%2CCITY%2CSTALP%2CNAME%2CCERT%2CASSET%2CRSSD%2CCBSA_METRO_NAME&sort_by=CERT&sort_order=ASC&limit=10000&offset=0&format=json&download=false&filename=data_file'
    JSONContent = requests.get(url).json()
    zips = pd.json_normalize(JSONContent,'data')
    zips.columns = zips.columns.str.lstrip('data.')
    zips.columns = zips.columns.str.lower()
    zips = zips[['cert','name','city','stalp','zip','asset','cbsa_metro_name']]
    zips['zip'] =pd.to_numeric(zips['zip'].astype(str).str.replace('\.0','').str[:5],errors='coerce')
    info = zips[zips['cert']==int(setup.num)]

    custom_assets = input("Enter custom assets (or hit enter to skip): ")
    if custom_assets != '':
        assets = int(custom_assets)
    else:
        assets = info.iloc[0]['asset']
    custom_range = input("Enter custom asset range (or hit enter to skip): ")
    if custom_range != '':
        asset_range = int(custom_range)
    else:
        asset_range = 4
    assetmin = assets / asset_range
    assetmax = assets * asset_range

    state = info.iloc[0]['stalp']
    state_only = input("State only? ('y' or enter to skip): ")
    if state_only == 'y':
        nearby = [state]
    else:
        nearby = setup.db.query_table('nearbystates')
        nearby = nearby[nearby['Abbreviation']==state]
        near1 = nearby.iloc[0]['Near1']
        near2 = nearby.iloc[0]['Near2']
        near3 = nearby.iloc[0]['Near3']
        near4 = nearby.iloc[0]['Near4']
        near5 = nearby.iloc[0]['Near5']
        near6 = nearby.iloc[0]['Near6']
        near7 = nearby.iloc[0]['Near7']
        near8 = nearby.iloc[0]['Near8']
        nearby = [state,near1,near2,near3,near4,near5,near6,near7,near8]

    peers = zips[zips['stalp'].isin(nearby)]
    if custom_assets != '':
        peers['asset'][peers['cert']==int(setup.num)] = assets
    peers = peers[(peers['asset']<=assetmax) & (peers['asset']>=assetmin)]
    peerzips = setup.db.query_table('peerzips')
    peerzips['zip'] = pd.to_numeric(peerzips['zip'])
    peerzips = peerzips[['zip','latitude','longitude']]
    peers = pd.merge(peers,peerzips,how='left',left_on='zip',right_on='zip')

    bankloc = peers[(pd.to_numeric(peers['cert'])).astype(int)==int(setup.num)]
    banklong = bankloc.iloc[0]['longitude'].astype(float)
    banklat = bankloc.iloc[0]['latitude'].astype(float)
    peers['longitude'] = pd.to_numeric(peers['longitude'],errors='coerce')
    peers['latitude'] = pd.to_numeric(peers['latitude'],errors='coerce')
    peers = peers[peers['latitude']>0]
    peers['distance'] = peers.apply(lambda row: haversine(row, banklong, banklat), axis=1)
    peers['distance'] = peers['distance'].round(0).astype(int)
    peers['name'] = peers['name'].str.partition(',')[0]

    custom_radius = input("Enter custom radius (or hit enter to skip): ")
    if custom_radius != '':
        peers = peers[peers['distance']<=int(custom_radius)]
    peers = peers.sort_values(by='distance')
    peers['cert'] = peers['cert'].astype(str).replace('\.0','')
    peers["new"] = range(1,len(peers)+1)
    peers.index = peers['cert']
    peers.loc[str(setup.num),'new'] = 0
    peers = peers.sort_values(by='new')
    if peers.iloc[0]['cert']!=str(setup.num):
        # peers = peers[1:]
        print('the bank is not first in order: needs additional attention')
        sys.exit()

    peers['cert']=peers.index
    peers = peers[['cert','name','city','stalp','zip','asset','distance','cbsa_metro_name']]
    peers['FDIC'] = peers['cert']
    peers = peers.iloc[:65]

    setup.db.upload_table(setup.shortname + 'peergroup', peers)

def main():
    setup = Setup()
    get_bank_info(setup)

if __name__ == "__main__":
    main()