import os
import datetime, calendar
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
import pyrebase
import time


## Creating Credentials ##
CLIENT_FILE = 'acc1_fitplaydash.json'
SCOPES = ['https://www.googleapis.com/auth/fitness.activity.read',
          'https://www.googleapis.com/auth/fitness.location.read',
          'https://www.googleapis.com/auth/fitness.body.read',
          'https://www.googleapis.com/auth/fitness.nutrition.read',
          'https://www.googleapis.com/auth/fitness.blood_pressure.read',
          'https://www.googleapis.com/auth/fitness.blood_glucose.read',
          'https://www.googleapis.com/auth/fitness.oxygen_saturation.read',
          'https://www.googleapis.com/auth/fitness.body_temperature.read',
          'https://www.googleapis.com/auth/fitness.reproductive_health.read'
          ]

creds = None
if os.path.exists('token.json'):
    credit = Credentials.from_authorized_user_file('token.json', SCOPES)

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(CLIENT_FILE, SCOPES)
        creds = flow.run_local_server(port=0)
    with open('token.json', 'w') as token:
        token.write(creds.to_json())
## Creating Credentials End ##




# Create a client to interact with the Fit API
fit_service = build('fitness', 'v1', credentials=credit)

#Configure Firebase Database
config = {
    "apiKey": " ",
    "authDomain": " ",
    "databaseURL": " ",
    "projectId": " ",
    "storageBucket": " "
    }

pyrebase = pyrebase.initialize_app(config)
#End Configure Firebase Database


while True: 
    # Get a list of data sources
    data_sources = fit_service.users().dataSources().list(userId='me').execute()

    # Specify the data source (for step count, use "derived:com.google.step_count.delta:com.google.android.gms:estimated_steps")
    data_source_steps = "derived:com.google.step_count.delta:com.google.android.gms:estimated_steps"
    data_source_calories = "derived:com.google.calories.expended:com.google.android.gms:merge_calories_expended"
    data_source_distance = "derived:com.google.distance.delta:com.google.android.gms:merge_distance_delta"

    data_stream_id_steps = 0
    data_stream_id_calories = 0
    data_stream_id_distance = 0

    # Search for the desired data source
    for source in data_sources.get('dataSource', []):
        if data_source_steps in source['dataStreamId']:
            data_stream_id_steps = source['dataStreamId']
        if data_source_calories in source['dataStreamId']:
            data_stream_id_calories = source['dataStreamId']
        if data_source_distance in source['dataStreamId']:
            data_stream_id_distance = source['dataStreamId']
        

    def retrieve_steps(start_date, end_date):

        start_date_epoch = calendar.timegm(start_date.timetuple())*1000000000
        end_date_epoch = calendar.timegm(end_date.timetuple())*1000000000


        # Query step count data from the specified data source
        step_count_data = fit_service.users().dataSources().datasets().get(
            userId='me',
            dataSourceId=data_stream_id_steps,
            datasetId=f"{start_date_epoch}-{end_date_epoch}"
        ).execute()

        totsteps = 0

        # Extract and print the step count data
        if 'point' in step_count_data:
            for point in step_count_data['point']:
                if 'value' in point:
                    for value in point['value']:
                        if value['intVal']:
                            totsteps = totsteps + value['intVal']
                            #print(f"Step count: {value['intVal']}")

        return totsteps



    def retrieve_calories(start_date, end_date):

        start_date_epoch = calendar.timegm(start_date.timetuple())*1000000000
        end_date_epoch = calendar.timegm(end_date.timetuple())*1000000000


        # Query step count data from the specified data source
        calorie_count_data = fit_service.users().dataSources().datasets().get(
            userId='me',
            dataSourceId=data_stream_id_calories,
            datasetId=f"{start_date_epoch}-{end_date_epoch}"
        ).execute()

        totcalories = 0

        # Extract and print the step count data
        if 'point' in calorie_count_data:
            for point in calorie_count_data['point']:
                if 'value' in point:
                    for value in point['value']:
                        if value['fpVal']:

                            totcalories = totcalories + value['fpVal']
                            #print(f"Step count: {value['intVal']}")

        return round(totcalories, 2)



    def retrieve_distance(start_date, end_date):

        start_date_epoch = calendar.timegm(start_date.timetuple())*1000000000
        end_date_epoch = calendar.timegm(end_date.timetuple())*1000000000


        # Query step count data from the specified data source
        distance_count_data = fit_service.users().dataSources().datasets().get(
            userId='me',
            dataSourceId=data_stream_id_distance,
            datasetId=f"{start_date_epoch}-{end_date_epoch}"
        ).execute()

        totdistance = 0

        # Extract and print the step count data
        if 'point' in distance_count_data:
            for point in distance_count_data['point']:
                if 'value' in point:
                    for value in point['value']:
                        if value['fpVal']:
                            totdistance = totdistance + value['fpVal']
                            #print(f"Step count: {value['intVal']}")

        return round(float(totdistance/1000),2)





    now = datetime.datetime.now()
    today = datetime.date.today()

    chart_data_steps = {
        today.strftime("%m-%d, %a %d %b") : retrieve_steps(now, today)
        }

    for i in range(1,14):
        chart_data_steps[(today - datetime.timedelta(days = i)).strftime("%m-%d, %a %d %b")] = retrieve_steps( today - datetime.timedelta(days = (i-1)) , today - datetime.timedelta(days =i) )





    chart_data_calories = {
        today.strftime("%m-%d, %a %d %b") : retrieve_calories(now, today)
        }

    for i in range(1,14):
        chart_data_calories[(today - datetime.timedelta(days = i)).strftime("%m-%d, %a %d %b")] = retrieve_calories( today - datetime.timedelta(days = (i-1)) , today - datetime.timedelta(days =i) )  - 650
        




    chart_data_distance = {
        today.strftime("%m-%d, %a %d %b") : retrieve_distance(now, today)
        }

    for i in range(1,14):
        chart_data_distance[(today - datetime.timedelta(days = i)).strftime("%m-%d, %a %d %b")] = retrieve_distance( today - datetime.timedelta(days = (i-1)) , today - datetime.timedelta(days =i) )
        



            

    




    # Send the dictionary to Firebase
    db = pyrebase.database()
    db.child("usersData/josh/calories").update(chart_data_calories) #Note that you have to change the location based on your firebase database
    db.child("usersData/josh/distance").update(chart_data_distance)
    db.child("usersData/josh/steps").update(chart_data_steps)


    print("Database Updated")
    #time.sleep(1)
