package dto

import (
	"fmt"
	"time"

	"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
)

// NewDeviceResponse 从数据库模型创建一个新的设备响应 DTO
func NewDeviceResponse(device *models.Device) (*DeviceResponse, error) {
	if device == nil {
		return nil, nil
	}

	var props map[string]interface{}
	if len(device.Properties) > 0 && string(device.Properties) != "null" {
		if err := device.ParseProperties(&props); err != nil {
			return nil, fmt.Errorf("解析设备属性失败 (ID: %d): %w", device.ID, err)
		}
	}

	// 确保 DeviceTemplate 和 AreaController 已预加载
	deviceTemplateName := ""
	if device.DeviceTemplate.ID != 0 {
		deviceTemplateName = device.DeviceTemplate.Name
	}

	areaControllerName := ""
	if device.AreaController.ID != 0 {
		areaControllerName = device.AreaController.Name
	}

	return &DeviceResponse{
		ID:                 device.ID,
		Name:               device.Name,
		DeviceTemplateID:   device.DeviceTemplateID,
		DeviceTemplateName: deviceTemplateName,
		AreaControllerID:   device.AreaControllerID,
		AreaControllerName: areaControllerName,
		Location:           device.Location,
		Properties:         props,
		CreatedAt:          device.CreatedAt.Format(time.RFC3339),
		UpdatedAt:          device.UpdatedAt.Format(time.RFC3339),
	}, nil
}

// NewListDeviceResponse 从数据库模型切片创建一个新的设备列表响应 DTO 切片
func NewListDeviceResponse(devices []*models.Device) ([]*DeviceResponse, error) {
	list := make([]*DeviceResponse, 0, len(devices))
	for _, device := range devices {
		resp, err := NewDeviceResponse(device)
		if err != nil {
			return nil, err
		}
		list = append(list, resp)
	}
	return list, nil
}

// NewAreaControllerResponse 从数据库模型创建一个新的区域主控响应 DTO
func NewAreaControllerResponse(ac *models.AreaController) (*AreaControllerResponse, error) {
	if ac == nil {
		return nil, nil
	}

	// 解析 firmware_version
	var firmwareVersion string
	// 使用模型上的辅助方法来解析强类型属性
	acProps := &models.AreaControllerProperties{}
	if err := ac.ParseProperties(acProps); err == nil {
		firmwareVersion = acProps.FirmwareVersion
	}
	// 如果解析出错，firmwareVersion 将保持为空字符串，这通常是可接受的降级行为

	// 解析完整的 properties 以便向后兼容或用于其他未知属性
	var allProps map[string]interface{}
	if len(ac.Properties) > 0 && string(ac.Properties) != "null" {
		// 这里我们使用通用的 ParseProperties 方法
		if err := ac.ParseProperties(&allProps); err != nil {
			return nil, fmt.Errorf("解析区域主控完整属性失败 (ID: %d): %w", ac.ID, err)
		}
	}

	return &AreaControllerResponse{
		ID:              ac.ID,
		Name:            ac.Name,
		NetworkID:       ac.NetworkID,
		FirmwareVersion: firmwareVersion,
		Location:        ac.Location,
		Status:          ac.Status,
		Properties:      allProps, // 填充完整的 properties
		CreatedAt:       ac.CreatedAt.Format(time.RFC3339),
		UpdatedAt:       ac.UpdatedAt.Format(time.RFC3339),
	}, nil
}

// NewListAreaControllerResponse 从数据库模型切片创建一个新的区域主控列表响应 DTO 切片
func NewListAreaControllerResponse(acs []*models.AreaController) ([]*AreaControllerResponse, error) {
	list := make([]*AreaControllerResponse, 0, len(acs))
	for _, ac := range acs {
		resp, err := NewAreaControllerResponse(ac)
		if err != nil {
			return nil, err
		}
		list = append(list, resp)
	}
	return list, nil
}

// NewDeviceTemplateResponse 从数据库模型创建一个新的设备模板响应 DTO
func NewDeviceTemplateResponse(dt *models.DeviceTemplate) (*DeviceTemplateResponse, error) {
	if dt == nil {
		return nil, nil
	}

	var commands map[string]interface{}
	if err := dt.ParseCommands(&commands); err != nil {
		return nil, fmt.Errorf("解析设备模板命令失败 (ID: %d): %w", dt.ID, err)
	}

	var values []models.ValueDescriptor
	if dt.Category == models.CategorySensor {
		if err := dt.ParseValues(&values); err != nil {
			return nil, fmt.Errorf("解析设备模板值描述符失败 (ID: %d): %w", dt.ID, err)
		}
	}

	return &DeviceTemplateResponse{
		ID:           dt.ID,
		Name:         dt.Name,
		Manufacturer: dt.Manufacturer,
		Description:  dt.Description,
		Category:     dt.Category,
		Commands:     commands,
		Values:       values,
		CreatedAt:    dt.CreatedAt.Format(time.RFC3339),
		UpdatedAt:    dt.UpdatedAt.Format(time.RFC3339),
	}, nil
}

// NewListDeviceTemplateResponse 从数据库模型切片创建一个新的设备模板列表响应 DTO 切片
func NewListDeviceTemplateResponse(dts []*models.DeviceTemplate) ([]*DeviceTemplateResponse, error) {
	list := make([]*DeviceTemplateResponse, 0, len(dts))
	for _, dt := range dts {
		resp, err := NewDeviceTemplateResponse(dt)
		if err != nil {
			return nil, err
		}
		list = append(list, resp)
	}
	return list, nil
}
