"""
Script to retrieve Fitbit data for the given user
"""
from __future__ import print_function

import json
from pprint import pprint
from fitbit import Fitbit
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from datetime import date, timedelta

import consul

dt = date.today() - timedelta(7)



c = consul.Consul(host='consul.service.dc1.consul')

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']

# The ID and range of a sample spreadsheet.
SAMPLE_SPREADSHEET_ID = '1YkMf_3m2YroHhtyS2FrdLzm3HnJDk4-q8r4cSagYrrg'
SAMPLE_RANGE_NAME = 'fitbit_export!A2:E'



FITBIT_API = 'https://api.fitbit.com'

CLIENT_DETAILS_FILE = 'client_details.json'  # configuration for for the client
USER_DETAILS_FILE = 'user_details.json'  # user details file

RESULT_FILE = 'fitbit_data.json'  # The place where we will place the results


# def refresh_callback(token):
#     """
#     This method is only called when the authenticate token is out of date
#     and a new token has been issued which needs to be stored somewhere for
#     the next run
#     param (token): A dictionary with the new details
#     """
#     print('CALLBACK: The token has been updated since last run')
#     with open(USER_DETAILS_FILE, 'w') as f:
#         json.dump(token, f)
#     print('Successfully written update refresh token')

def refresh_callback(token):
    c.kv.put('access_token', token["access_token"])
    c.kv.put('refresh_token', token["refresh_token"])
    c.kv.put('expires_at', str(token["expires_at"]))

# def _get_user_details():
#     """
#     The specific user that you want to retrieve data for.
#     """
#     with open(USER_DETAILS_FILE) as f:
#         fitbit_user = json.load(f)
#         access_token = fitbit_user['access_token']
#         refresh_token = fitbit_user['refresh_token']
#         expires_at = fitbit_user['expires_at']

#     print(type(expires_at))
#     return access_token, refresh_token, expires_at



def _get_user_details():
    access_token = c.kv.get('access_token')[1]["Value"].decode("utf-8")
    refresh_token = c.kv.get('refresh_token')[1]["Value"].decode("utf-8")
    expires_at = float(c.kv.get('expires_at')[1]["Value"].decode("utf-8"))
    return access_token, refresh_token, expires_at


def _get_client_details():
    """The client is the application which requires access"""
    with open(CLIENT_DETAILS_FILE) as f:
        client_details = json.load(f)
        client_id = client_details['client_id']
        client_secret = client_details['client_secret']

    return client_id, client_secret


def _write_results(json_response):
    with open(RESULT_FILE, 'w') as f:
        json.dump(json_response, f)
    print(f'Successfully written result data to file {RESULT_FILE}')


def _get_api_call():
    """
    Date Api in this format:
    GET /<api-version>/user/<user-id>/<resource-path>/date/<base-date>/<end-date>.<response-format>
    <user-id> can be left as - to get the current user
    date format is '%Y-%m-%d' for example 2020-04-01
    Some examples below
    """
    # # Steps in the last 7 days
    # steps_last_seven_days = '/1/user/-/activities/log/steps/date/today/7d.json'
    # # Steps between two dates
    # steps_dates = '/1/user/-/activities/log/steps/date/2020-04-12/2020-04-18.json'
    # # calories last 7 days
    # calories_last_seven_days = '/1/user/-/activities/log/calories/date/today/7d.json'
    # # profile info
    # profile_info = '/1/user/-/profile.json'
    # # Sleep between two dates
    # sleep_dates = '/1.2/user/-/sleep/date/2020-04-13/2020-04-17.json'
    weight = '/1.2/user/-/body/log/weight/date/' + str(date_start) + '/' + str(date_end) + '.json'

    return weight


def ReadSheet():
    """Shows basic usage of the Sheets API.
    Prints values from a sample spreadsheet.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('sheets', 'v4', credentials=creds)

    # Call the Sheets API
    sheet = service.spreadsheets()
    result = sheet.values().get(spreadsheetId=SAMPLE_SPREADSHEET_ID,
                                range=SAMPLE_RANGE_NAME).execute()
    curr_values = result.get('values', [])
    return curr_values


def UpdateSheet(values):
    """Shows basic usage of the Sheets API.
    Prints values from a sample spreadsheet.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('sheets', 'v4', credentials=creds)

    # Call the Sheets API
    # sheet = service.spreadsheets()
    # result = sheet.values().get(spreadsheetId=SAMPLE_SPREADSHEET_ID,
    #                             range=SAMPLE_RANGE_NAME).execute()
    # values = result.get('values', [])

    # if not values:
    #     print('No data found.')
    # else:
    #     print('Name, Major:')
    #     for row in values:
    #         # Print columns A and E, which correspond to indices 0 and 4.
    #         print('%s, %s' % (row[0], row[4]))

    # values = [
    #     [
    #         "TEST", "TEST"
    #     ],
    # ]
    body = {
        'values': values
    }
    result = service.spreadsheets().values().append(
        spreadsheetId=SAMPLE_SPREADSHEET_ID,range=SAMPLE_RANGE_NAME,
        valueInputOption='RAW', body=body).execute()
    print('{0} cells appended.'.format(result \
                                        .get('updates') \
                                        .get('updatedCells')))



def run():
    client_id, client_secret = _get_client_details()
    access_token, refresh_token, expires_at = _get_user_details()

    #print(f'Running Fitbit request with details: {client_id} {client_secret}'
    #      f' {access_token} {refresh_token} {expires_at}')
    auth2_client = Fitbit(client_id, client_secret, oauth2=True,
                          access_token=access_token,
                          refresh_token=refresh_token, expires_at=expires_at,
                          refresh_cb=refresh_callback)

    fitbit_url = FITBIT_API + _get_api_call()
    json_response = auth2_client.make_request(fitbit_url)
    # _write_results(json_response)
    # pprint(json_response["weight"])
    values = []
    sheet_values = ReadSheet()
    # pprint(sheet_values)

    for row in json_response["weight"]:
        row_exists = 0
        for sheetrow in sheet_values:
            if sheetrow[0] == row["date"]:
                row_exists = 1
        if row_exists == 0:
            if 'fat' in row.keys():
                row_list = [row["date"],row["weight"],row["fat"],row["bmi"]]
            else:
                row_list = [row["date"],row["weight"],"0",row["bmi"]]
            values.append(row_list)
    pprint(date_start)
    pprint(values)
    UpdateSheet(values)
    # sheet_values = ReadSheet()

if __name__ == '__main__':

       
    date_start = date.today() - timedelta(31)
    # date_end = date.today()
    # run()

    ###Bulk import
    # date_start = date(2015, 8, 1)
    end_date = date(2019, 10, 1)

    while date_start != end_date:
        # date_end = date.today() + timedelta(30)
        date_end = date_start + timedelta(30)
        # date_start = date.today() - timedelta(31)
        run()
        # time.sleep(60)
        date_start = date_start - timedelta(29)
