package platformoverview

import (
	"fmt"
	"time"

	"github.com/go-openapi/strfmt"
	"github.com/pingcap/log"
	"github.com/pingcap/tep/db/entity"
	"github.com/pingcap/tep/pkg/apis/apiserver"
	"go.uber.org/zap"
	"k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/runtime"
)

func (s *Storage) GetBasicInformation() (runtime.Object, error) {
	platform := &apiserver.PlatformOverview{}
	platform.Name = basicInformation
	event, err := s.getLastOperateEvent()
	if err != nil {
		log.Warn("failed to get last operation event", zap.Error(err))
	} else {
		platform.OperationTime = strfmt.DateTime(time.Unix(event.OperationTime, 0)).String()
	}
	tidbOperatorVersion, err := s.store.Controller().GetTiDBOperatorVersion()
	if err != nil {
		log.Warn("failed to get TiDB Operator version", zap.Error(err))
	} else {
		platform.TiDBOperatorVersion = tidbOperatorVersion
	}

	metaDBVersion, err := s.getMetaDBVersion()
	if err != nil {
		log.Warn("failed to get meta database version", zap.Error(err))
	} else {
		platform.MetaDBVersion = metaDBVersion
	}

	kubernetesVersion, err := s.store.Controller().GetKubernetesServerVersion()
	if err != nil {
		log.Warn("failed to get kubernetes server version", zap.Error(err))
	} else {
		platform.KubernetesVersion = kubernetesVersion.String()
	}

	return platform, nil
}

func (s *Storage) getLastOperateEvent() (*entity.OperateEvent, error) {
	event := &entity.OperateEvent{}
	if err := s.store.DB.Last(event).Error; err != nil {
		msg := fmt.Errorf("failed to query operateEvent table. err: %v", err)
		return nil, errors.NewInternalError(msg)
	}
	return event, nil
}

type MetaDBVersionResult struct {
	Version string
}

func (s *Storage) getMetaDBVersion() (string, error) {
	var result MetaDBVersionResult
	sql := "select version() AS version;"
	if err := s.store.DB.Raw(sql).Scan(&result).Error; err != nil {
		return "", err
	}
	return result.Version, nil
}
