import os
import pathlib
import json
import argparse
import requests.exceptions
from garth.exc import GarthHTTPError
from garminconnect import (
	Garmin,
	GarminConnectConnectionError,
	GarminConnectTooManyRequestsError,
	GarminConnectAuthenticationError,
)

TOKEN_DIR  = "/var/lib/garminconnect"
OUTPUT_DIR = "/var/www/html/garmin"
MAX_ACTIVITIES = 100

pathlib.Path(TOKEN_DIR).mkdir(parents=True, exist_ok=True)
pathlib.Path(OUTPUT_DIR).mkdir(parents=True, exist_ok=True)

def init_api(email: str, password: str, token_dir: str = TOKEN_DIR):

	g = Garmin()

	try:
		g.login(token_dir)
		return g

	except (FileNotFoundError, GarthHTTPError, GarminConnectAuthenticationError, requests.exceptions.HTTPError):

		try:
			g = Garmin(email=email, password=password)
			g.login()
			g.garth.dump(token_dir)

			for name in ("oauth1_token.json", "oauth2_token.json", "cookies.json"):
				p = os.path.join(token_dir, name)
				if os.path.exists(p):
					try:
						os.chmod(p, 0o600)
					except PermissionError:
						pass
			return g
		except (GarthHTTPError, GarminConnectAuthenticationError, requests.exceptions.RequestException):
			raise

def download_activities_since(client: Garmin, since_activity_id: int):

	downloaded = []
	count = 0

	try:
		activities = client.get_activities(0, MAX_ACTIVITIES)
		for a in activities:
			try:
				activity_id = int(a['activityId'])
			except (KeyError, ValueError, TypeError):
				continue

			if(count > 5):
				break
			if activity_id >  since_activity_id:
				try:
					dl_fmt = client.ActivityDownloadFormat.ORIGINAL
					data = client.download_activity(activity_id, dl_fmt=dl_fmt)

					is_zip = data[:4] == b"PK\x03\x04"
					ext = "zip" if is_zip else "fit"

					out_path = os.path.join(OUTPUT_DIR, f"{activity_id}.{ext}")
					with open(out_path, "wb") as fh:
						fh.write(data)
					downloaded.append(f"{activity_id}.{ext}")
					count += 1
				except Exception:
					continue

		return {"status": 1, "data": downloaded}

	except (GarminConnectConnectionError, GarminConnectTooManyRequestsError, GarminConnectAuthenticationError) as err:
		return {"status": 0, "error": f"An error occured: {str(err)}", "data":[]}

	except requests.exceptions.RequestException as err:
		return {"status": 0, "error": f"Network error: {err}", "data": []}

	except Exception as err:
		return {"status": 0, "error": f"Unexpected error: {str(err)}", "data": []}



def main():

	parser = argparse.ArgumentParser(description="Download new Garmin activities.")
	parser.add_argument('--username', required=True, help='Garmin Connect username')
	parser.add_argument('--password', required=True, help='Garmin Connect password')
	parser.add_argument('--since', required=True, type=int, help='Timestamp of the last downloaded activity')
	args = parser.parse_args()

	try:
		client = init_api(args.username, args.password, TOKEN_DIR)
	except Exception as e:
		print(json.dumps({"status": 0, "error": f"Initialization error: {e}", "data":[]}))
		return

	result = download_activities_since(client, args.since)

	print(json.dumps(result))


if __name__ == "__main__":
	main()
