package sync

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"github.com/sstent/garminsync-go/internal/database"
	"github.com/sstent/garminsync-go/internal/garmin"
	"github.com/sstent/garminsync-go/internal/parser"
)

type SyncService struct {
	garminClient *garmin.Client
	db           *database.SQLiteDB
	dataDir      string
}

func NewSyncService(garminClient *garmin.Client, db *database.SQLiteDB, dataDir string) *SyncService {
	return &SyncService{
		garminClient: garminClient,
		db:           db,
		dataDir:      dataDir,
	}
}

func (s *SyncService) FullSync(ctx context.Context) error {
	fmt.Println("=== Starting full sync ===")
	defer fmt.Println("=== Sync completed ===")

	// Check credentials first
	email := os.Getenv("GARMIN_EMAIL")
	password := os.Getenv("GARMIN_PASSWORD")
	
	if email == "" || password == "" {
		return fmt.Errorf("Missing credentials - GARMIN_EMAIL: '%s', GARMIN_PASSWORD: %s", 
			email, 
			map[bool]string{true: "SET", false: "EMPTY"}[password != ""])
	}
	
	fmt.Printf("Using credentials - Email: %s, Password: %s\n", email, 
		map[bool]string{true: "***SET***", false: "EMPTY"}[password != ""])

	// 1. Fetch activities from Garmin
	fmt.Println("Fetching activities from Garmin Connect...")
	activities, err := s.garminClient.GetActivities(0, 10) // Start with just 10 for testing
	if err != nil {
		return fmt.Errorf("failed to get activities: %w", err)
	}
	
	fmt.Printf("✅ Found %d activities from Garmin\n", len(activities))
	
	if len(activities) == 0 {
		fmt.Println("⚠️ No activities returned - this might be expected if:")
		fmt.Println("   - Your Garmin account has no activities")
		fmt.Println("   - The API response format changed")
		fmt.Println("   - Authentication succeeded but data access failed")
		return nil
	}

	// 2. Process each activity
	for i, activity := range activities {
		select {
		case <-ctx.Done():
			return ctx.Err()
		default:
			fmt.Printf("[%d/%d] Processing activity %d (%s)...\n", 
				i+1, len(activities), activity.ActivityID, activity.ActivityName)
			if err := s.syncActivity(&activity); err != nil {
				fmt.Printf("❌ Error syncing activity %d: %v\n", activity.ActivityID, err)
			} else {
				fmt.Printf("✅ Successfully synced activity %d\n", activity.ActivityID)
			}
		}
	}

	return nil
}

func (s *SyncService) syncActivity(activity *garmin.GarminActivity) error {
	// Skip if already downloaded
	if exists, _ := s.db.ActivityExists(activity.ActivityID); exists {
		return nil
	}

	// Download the activity file (FIT format)
	fileData, err := s.garminClient.DownloadActivity(activity.ActivityID, "fit")
	if err != nil {
		return fmt.Errorf("download failed: %w", err)
	}

	// Save file
	filename := filepath.Join(s.dataDir, "activities", fmt.Sprintf("%d.fit", activity.ActivityID))
	if err := os.MkdirAll(filepath.Dir(filename), 0755); err != nil {
		return fmt.Errorf("directory creation failed: %w", err)
	}
	if err := os.WriteFile(filename, fileData, 0644); err != nil {
		return fmt.Errorf("file write failed: %w", err)
	}

	// Parse the file
	fileParser := parser.NewParser()
	metrics, err := fileParser.ParseData(fileData)
	if err != nil {
		return fmt.Errorf("parsing failed: %w", err)
	}

	// Parse start time
	startTime, err := time.Parse("2006-01-02 15:04:05", activity.StartTimeLocal)
	if err != nil {
		startTime = time.Now()
	}

	// Save to database
	if err := s.db.CreateActivity(&database.Activity{
		ActivityID:    activity.ActivityID,
		StartTime:     startTime,
		ActivityType:  getActivityType(activity),
		Distance:      metrics.Distance,
		Duration:      int(metrics.Duration.Seconds()),
		MaxHeartRate:  metrics.MaxHeartRate,
		AvgHeartRate:  metrics.AvgHeartRate,
		AvgPower:      float64(metrics.AvgPower),
		Calories:      metrics.Calories,
		Filename:      filename,
		FileType:      "fit",
		Downloaded:    true,
		ElevationGain: metrics.ElevationGain,
		Steps:         metrics.Steps,
	}); err != nil {
		return fmt.Errorf("database error: %w", err)
	}

	fmt.Printf("Synced activity %d\n", activity.ActivityID)
	return nil
}

// Add missing Sync method
func (s *SyncService) Sync(ctx context.Context) error {
    return s.FullSync(ctx)
}

func getActivityType(activity *garmin.GarminActivity) string {
	if activityType, ok := activity.ActivityType["typeKey"]; ok {
		return activityType.(string)
	}
	return "unknown"
}
