package cache

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/go-redis/redis/v8"
	"sensor-server/internal/models"
)

var RedisClient *redis.Client

// InitRedis Redis 초기화
func InitRedis() error {
	RedisClient = redis.NewClient(&redis.Options{
		Addr:     fmt.Sprintf("%s:%s", getEnv("REDIS_HOST", "localhost"), getEnv("REDIS_PORT", "6379")),
		Password: getEnv("REDIS_PASSWORD", ""),
		DB:       0,
	})

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	_, err := RedisClient.Ping(ctx).Result()
	if err != nil {
		return fmt.Errorf("failed to connect to Redis: %v", err)
	}

	log.Println("Redis initialized successfully")
	return nil
}

// GetRedisClient Redis 클라이언트 반환
func GetRedisClient() *redis.Client {
	return RedisClient
}

// CacheLatestReading 최신 센서 데이터 캐시
func CacheLatestReading(deviceID string, reading *models.SensorReading) error {
	ctx := context.Background()
	key := fmt.Sprintf("latest:%s", deviceID)
	
	data, err := json.Marshal(reading)
	if err != nil {
		return err
	}

	// 1시간 동안 캐시
	return RedisClient.Set(ctx, key, data, time.Hour).Err()
}

// GetLatestReading 캐시된 최신 센서 데이터 조회
func GetLatestReading(deviceID string) (*models.SensorReading, error) {
	ctx := context.Background()
	key := fmt.Sprintf("latest:%s", deviceID)
	
	data, err := RedisClient.Get(ctx, key).Result()
	if err != nil {
		return nil, err
	}

	var reading models.SensorReading
	err = json.Unmarshal([]byte(data), &reading)
	if err != nil {
		return nil, err
	}

	return &reading, nil
}

// CacheDeviceInfo 디바이스 정보 캐시
func CacheDeviceInfo(device *models.Device) error {
	ctx := context.Background()
	key := fmt.Sprintf("device:%s", device.DeviceID)
	
	data, err := json.Marshal(device)
	if err != nil {
		return err
	}

	// 24시간 동안 캐시
	return RedisClient.Set(ctx, key, data, 24*time.Hour).Err()
}

// GetDeviceInfo 캐시된 디바이스 정보 조회
func GetDeviceInfo(deviceID string) (*models.Device, error) {
	ctx := context.Background()
	key := fmt.Sprintf("device:%s", deviceID)
	
	data, err := RedisClient.Get(ctx, key).Result()
	if err != nil {
		return nil, err
	}

	var device models.Device
	err = json.Unmarshal([]byte(data), &device)
	if err != nil {
		return nil, err
	}

	return &device, nil
}

// BroadcastSensorData WebSocket 브로드캐스트용 데이터 캐시
func BroadcastSensorData(reading *models.SensorReading) error {
	ctx := context.Background()
	key := "broadcast:sensor_data"
	
	data, err := json.Marshal(reading)
	if err != nil {
		return err
	}

	// Redis Pub/Sub을 통해 브로드캐스트
	return RedisClient.Publish(ctx, key, data).Err()
}

// getEnv 환경변수 조회 (기본값 포함)
func getEnv(key, defaultValue string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return defaultValue
} 