package feichibridge

import (
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"
)

var shanghai = time.FixedZone("Asia/Shanghai", 8*60*60)

type Vehicle struct {
	VehicleID    string `json:"vehicleId"`
	VIN          string `json:"vin"`
	OnlineStatus any    `json:"onlineStatus"`
	UpdateTime   string `json:"updateTime"`
	RuleTypeName string `json:"ruleTypeName"`
}

type Snapshot struct {
	VehicleID string            `json:"vehicleId"`
	VIN       string            `json:"vin"`
	DataItems map[string]string `json:"dataItems"`
}

type Record map[string]string

type collectionEnvelope[T any] struct {
	Code any `json:"code"`
	Data []T `json:"data"`
}

type objectEnvelope[T any] struct {
	Code any `json:"code"`
	Data T   `json:"data"`
}

type historySegment struct {
	Subdata []Record `json:"subdata"`
}

func apiCodeOK(code any) bool {
	switch value := code.(type) {
	case nil:
		return true
	case float64:
		return value == 0 || value == 200
	case string:
		return value == "" || value == "0" || value == "200"
	default:
		return false
	}
}

func recordTime(record Record) (time.Time, error) {
	for _, key := range []string{"2000", "9999", "dataTime", "updateTime", "time"} {
		if raw := strings.TrimSpace(record[key]); raw != "" {
			return parseSourceTime(raw)
		}
	}
	return time.Time{}, fmt.Errorf("source record has no timestamp")
}

func parseSourceTime(raw string) (time.Time, error) {
	raw = strings.TrimSpace(raw)
	for _, layout := range []string{
		"2006-01-02 15:04:05",
		"2006-01-02T15:04:05",
		time.RFC3339Nano,
	} {
		if layout == time.RFC3339Nano {
			if parsed, err := time.Parse(layout, raw); err == nil {
				return parsed, nil
			}
			continue
		}
		if parsed, err := time.ParseInLocation(layout, raw, shanghai); err == nil {
			return parsed, nil
		}
	}
	if unixMS, err := strconv.ParseInt(raw, 10, 64); err == nil {
		if unixMS < 10_000_000_000 {
			return time.Unix(unixMS, 0).In(shanghai), nil
		}
		return time.UnixMilli(unixMS).In(shanghai), nil
	}
	return time.Time{}, fmt.Errorf("unsupported source timestamp %q", raw)
}

func canonicalHash(record Record) string {
	encoded, _ := json.Marshal(record)
	return hashBytes(encoded)
}
