package model

import (
	"fmt"
	"net/url"
	"regexp"
	"strconv"
	"time"
)

// DeviceType 定义设备类型
type DeviceType int

const (
	DeviceTypeWIFI DeviceType = iota
	DeviceTypeRS485
)

// WeatherData 存储WIFI设备的气象数据
type WeatherData struct {
	StationID      string
	Password       string
	TempF          float64
	Humidity       int
	DewpointF      float64
	WindchillF     float64
	WindDir        int
	WindSpeedMph   float64
	WindGustMph    float64
	RainIn         float64
	DailyRainIn    float64
	WeeklyRainIn   float64
	MonthlyRainIn  float64
	YearlyRainIn   float64
	TotalRainIn    float64
	SolarRadiation float64
	UV             int
	IndoorTempF    float64
	IndoorHumidity int
	AbsBarometerIn float64
	BarometerIn    float64
	LowBattery     bool
	SoftwareType   string
	DateUTC        string
	Action         string
	RealTime       int
	RTFreq         int
}

var urlRegex = regexp.MustCompile(`/weatherstation/updateweatherstation\.php\?([^&\s]+(&[^&\s]+)*)`)

// ParseData 根据数据类型解析气象数据
func ParseData(data []byte) (interface{}, DeviceType, error) {
	// 检查是否为RS485数据
	if len(data) == 25 && data[0] == 0x24 {
		// 创建协议解析器
		protocol := NewProtocol(data)
		rs485Protocol := NewRS485Protocol(data)

		// 获取设备ID
		idParts, err := protocol.GetCompleteID()
		if err != nil {
			return nil, DeviceTypeRS485, fmt.Errorf("获取设备ID失败: %v", err)
		}

		// 解析RS485数据
		rs485Data, err := rs485Protocol.ParseRS485Data()
		if err != nil {
			return nil, DeviceTypeRS485, err
		}

		// 添加设备ID和时间戳
		rs485Data.DeviceID = idParts.Complete.Hex
		rs485Data.ReceivedAt = time.Now()
		rs485Data.RawDataHex = fmt.Sprintf("%X", data)

		return rs485Data, DeviceTypeRS485, nil
	}

	// 尝试解析为WIFI数据
	wifiData, err := ParseWIFIWeatherData(string(data))
	return wifiData, DeviceTypeWIFI, err
}

// ParseWIFIWeatherData 解析WIFI设备数据
func ParseWIFIWeatherData(data string) (*WeatherData, error) {
	matches := urlRegex.FindStringSubmatch(data)
	if len(matches) < 2 {
		return nil, fmt.Errorf("无法找到有效的气象站数据URL")
	}

	queryString := matches[1]
	values, err := url.ParseQuery(queryString)
	if err != nil {
		return nil, fmt.Errorf("解析查询参数失败: %v", err)
	}

	wd := &WeatherData{}

	wd.StationID = values.Get("ID")
	wd.Password = values.Get("PASSWORD")
	wd.SoftwareType = values.Get("softwaretype")
	wd.Action = values.Get("action")

	if tempF, err := strconv.ParseFloat(values.Get("tempf"), 64); err == nil {
		wd.TempF = tempF
	}

	if humidity, err := strconv.Atoi(values.Get("humidity")); err == nil {
		wd.Humidity = humidity
	}

	if dewpointF, err := strconv.ParseFloat(values.Get("dewptf"), 64); err == nil {
		wd.DewpointF = dewpointF
	}

	if windchillF, err := strconv.ParseFloat(values.Get("windchillf"), 64); err == nil {
		wd.WindchillF = windchillF
	}

	if windDir, err := strconv.Atoi(values.Get("winddir")); err == nil {
		wd.WindDir = windDir
	}

	if windSpeedMph, err := strconv.ParseFloat(values.Get("windspeedmph"), 64); err == nil {
		wd.WindSpeedMph = windSpeedMph
	}

	if windGustMph, err := strconv.ParseFloat(values.Get("windgustmph"), 64); err == nil {
		wd.WindGustMph = windGustMph
	}

	if rainIn, err := strconv.ParseFloat(values.Get("rainin"), 64); err == nil {
		wd.RainIn = rainIn
	}

	if dailyRainIn, err := strconv.ParseFloat(values.Get("dailyrainin"), 64); err == nil {
		wd.DailyRainIn = dailyRainIn
	}

	if weeklyRainIn, err := strconv.ParseFloat(values.Get("weeklyrainin"), 64); err == nil {
		wd.WeeklyRainIn = weeklyRainIn
	}

	if monthlyRainIn, err := strconv.ParseFloat(values.Get("monthlyrainin"), 64); err == nil {
		wd.MonthlyRainIn = monthlyRainIn
	}

	if yearlyRainIn, err := strconv.ParseFloat(values.Get("yearlyrainin"), 64); err == nil {
		wd.YearlyRainIn = yearlyRainIn
	}

	if totalRainIn, err := strconv.ParseFloat(values.Get("totalrainin"), 64); err == nil {
		wd.TotalRainIn = totalRainIn
	}

	if solarRadiation, err := strconv.ParseFloat(values.Get("solarradiation"), 64); err == nil {
		wd.SolarRadiation = solarRadiation
	}

	if uv, err := strconv.Atoi(values.Get("UV")); err == nil {
		wd.UV = uv
	}

	if indoorTempF, err := strconv.ParseFloat(values.Get("indoortempf"), 64); err == nil {
		wd.IndoorTempF = indoorTempF
	}

	if indoorHumidity, err := strconv.Atoi(values.Get("indoorhumidity")); err == nil {
		wd.IndoorHumidity = indoorHumidity
	}

	if absBarometerIn, err := strconv.ParseFloat(values.Get("absbaromin"), 64); err == nil {
		wd.AbsBarometerIn = absBarometerIn
	}

	if barometerIn, err := strconv.ParseFloat(values.Get("baromin"), 64); err == nil {
		wd.BarometerIn = barometerIn
	}

	if lowBatt, err := strconv.Atoi(values.Get("lowbatt")); err == nil {
		wd.LowBattery = lowBatt != 0
	}

	if realTime, err := strconv.Atoi(values.Get("realtime")); err == nil {
		wd.RealTime = realTime
	}

	if rtFreq, err := strconv.Atoi(values.Get("rtfreq")); err == nil {
		wd.RTFreq = rtFreq
	}

	return wd, nil
}

func (w *WeatherData) String() string {
	return fmt.Sprintf(`
站点ID: %s
温度: %.1f°F (%.1f°C)
湿度: %d%%
露点: %.1f°F (%.1f°C)
风寒指数: %.1f°F (%.1f°C)
风向: %d°
风速: %.2f mph (%.2f km/h)
阵风: %.2f mph (%.2f km/h)
降雨量: %.3f 英寸 (%.2f mm)
日降雨量: %.3f 英寸 (%.2f mm)
周降雨量: %.3f 英寸 (%.2f mm)
月降雨量: %.3f 英寸 (%.2f mm)
年降雨量: %.3f 英寸 (%.2f mm)
总降雨量: %.3f 英寸 (%.2f mm)
太阳辐射: %.2f W/m²
紫外线指数: %d
室内温度: %.1f°F (%.1f°C)
室内湿度: %d%%
绝对气压: %.3f 英寸汞柱 (%.2f hPa)
相对气压: %.3f 英寸汞柱 (%.2f hPa)
低电量: %v
软件类型: %s
日期UTC: %s`,
		w.StationID,
		w.TempF, (w.TempF-32)*5/9,
		w.Humidity,
		w.DewpointF, (w.DewpointF-32)*5/9,
		w.WindchillF, (w.WindchillF-32)*5/9,
		w.WindDir,
		w.WindSpeedMph, w.WindSpeedMph*1.60934,
		w.WindGustMph, w.WindGustMph*1.60934,
		w.RainIn, w.RainIn*25.4,
		w.DailyRainIn, w.DailyRainIn*25.4,
		w.WeeklyRainIn, w.WeeklyRainIn*25.4,
		w.MonthlyRainIn, w.MonthlyRainIn*25.4,
		w.YearlyRainIn, w.YearlyRainIn*25.4,
		w.TotalRainIn, w.TotalRainIn*25.4,
		w.SolarRadiation,
		w.UV,
		w.IndoorTempF, (w.IndoorTempF-32)*5/9,
		w.IndoorHumidity,
		w.AbsBarometerIn, w.AbsBarometerIn*33.8639,
		w.BarometerIn, w.BarometerIn*33.8639,
		w.LowBattery,
		w.SoftwareType,
		w.DateUTC,
	)
}
