#!/usr/bin/env python3
"""
Garmin Connect 數據匯入腳本

使用 python-garminconnect 從 Garmin Connect 下載健康數據。

使用方式：
    python import_garmin.py
    python import_garmin.py --days 30
    python import_garmin.py --start 2026-01-01 --end 2026-01-31

依賴套件：
    uv pip install garminconnect pandas

首次使用需要登入 Garmin Connect 帳號。
"""

import sys
sys.stdout.reconfigure(encoding='utf-8')

import argparse
import os
import json
from pathlib import Path
from datetime import datetime, timedelta
import pandas as pd

# 嘗試匯入 garminconnect
try:
    from garminconnect import Garmin
except ImportError:
    print("錯誤：找不到 garminconnect 套件")
    print("請執行：uv pip install garminconnect")
    sys.exit(1)


# 認證資訊儲存路徑
AUTH_FILE = Path(__file__).parent.parent / 'data' / 'raw' / 'garmin' / '.garmin_auth.json'


def get_garmin_client() -> Garmin:
    """
    取得已認證的 Garmin Connect 客戶端。
    首次使用需要輸入帳號密碼。
    """
    # 嘗試載入已儲存的認證
    if AUTH_FILE.exists():
        try:
            with open(AUTH_FILE, 'r') as f:
                auth_data = json.load(f)
            client = Garmin()
            client.login(auth_data)
            print("已使用儲存的認證登入")
            return client
        except Exception as e:
            print(f"無法使用儲存的認證：{e}")

    # 需要重新登入
    print("\n需要登入 Garmin Connect")
    email = input("Email: ")
    password = input("Password: ")

    try:
        client = Garmin(email, password)
        client.login()

        # 儲存認證
        AUTH_FILE.parent.mkdir(parents=True, exist_ok=True)
        with open(AUTH_FILE, 'w') as f:
            json.dump(client.session, f)

        print("登入成功，認證已儲存")
        return client

    except Exception as e:
        print(f"登入失敗：{e}")
        sys.exit(1)


def fetch_garmin_data(days: int = 30,
                      start_date: str = None,
                      end_date: str = None,
                      output_dir: str = None) -> pd.DataFrame:
    """
    從 Garmin Connect 下載健康數據。

    Args:
        days: 下載最近幾天的數據
        start_date: 開始日期 (YYYY-MM-DD)
        end_date: 結束日期 (YYYY-MM-DD)
        output_dir: 輸出目錄

    Returns:
        包含每日健康指標的 DataFrame
    """
    client = get_garmin_client()

    # 計算日期範圍
    if start_date and end_date:
        start = datetime.strptime(start_date, '%Y-%m-%d')
        end = datetime.strptime(end_date, '%Y-%m-%d')
    else:
        end = datetime.now()
        start = end - timedelta(days=days)

    print(f"\n下載數據：{start.date()} 到 {end.date()}")

    daily_data = []
    current = start

    while current <= end:
        date_str = current.strftime('%Y-%m-%d')
        print(f"  正在下載：{date_str}", end='')

        try:
            # 取得每日統計
            stats = client.get_stats(date_str)

            record = {
                'date': date_str,
                'source': 'garmin',
                'steps': stats.get('totalSteps'),
                'active_cal': stats.get('activeKilocalories'),
                'resting_hr': stats.get('restingHeartRate'),
                'stress_avg': stats.get('averageStressLevel'),
                'body_battery_high': stats.get('bodyBatteryChargedValue'),
                'body_battery_low': stats.get('bodyBatteryDrainedValue'),
            }

            # 取得睡眠數據
            try:
                sleep = client.get_sleep_data(date_str)
                if sleep:
                    sleep_seconds = sleep.get('dailySleepDTO', {}).get('sleepTimeSeconds', 0)
                    record['sleep_hours'] = round(sleep_seconds / 3600, 1) if sleep_seconds else None

                    # 深睡時間
                    deep_seconds = sleep.get('dailySleepDTO', {}).get('deepSleepSeconds', 0)
                    if sleep_seconds and deep_seconds:
                        record['deep_sleep_pct'] = round(deep_seconds / sleep_seconds * 100)
            except:
                pass

            # 取得 HRV 數據
            try:
                hrv = client.get_hrv_data(date_str)
                if hrv:
                    record['hrv'] = hrv.get('hrvSummary', {}).get('lastNightAvg')
            except:
                pass

            daily_data.append(record)
            print(" OK")

        except Exception as e:
            print(f" 錯誤: {e}")

        current += timedelta(days=1)

    # 轉換為 DataFrame
    df = pd.DataFrame(daily_data)

    if len(df) == 0:
        print("警告：沒有下載到任何數據")
        return df

    # 排序
    df['date'] = pd.to_datetime(df['date'])
    df = df.sort_values('date')

    # 輸出
    if output_dir is None:
        output_dir = Path(__file__).parent.parent / 'data' / 'processed'

    output_dir = Path(output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)

    output_path = output_dir / 'garmin_daily.csv'
    df.to_csv(output_path, index=False)

    print(f"\n完成！輸出到：{output_path}")
    print(f"共 {len(df)} 天的數據")

    return df


def main():
    parser = argparse.ArgumentParser(
        description='從 Garmin Connect 下載健康數據'
    )
    parser.add_argument(
        '-d', '--days',
        type=int,
        default=30,
        help='下載最近幾天的數據（預設 30 天）'
    )
    parser.add_argument(
        '-s', '--start',
        help='開始日期 (YYYY-MM-DD)'
    )
    parser.add_argument(
        '-e', '--end',
        help='結束日期 (YYYY-MM-DD)'
    )
    parser.add_argument(
        '-o', '--output',
        help='輸出目錄（預設為 data/processed/）',
        default=None
    )

    args = parser.parse_args()

    fetch_garmin_data(
        days=args.days,
        start_date=args.start,
        end_date=args.end,
        output_dir=args.output
    )


if __name__ == '__main__':
    main()
