package media

import (
	"encoding/json"
	"eta/eta_mini_ht_api/common/component/config"
	"eta/eta_mini_ht_api/common/component/es"
	logger "eta/eta_mini_ht_api/common/component/log"
	"eta/eta_mini_ht_api/common/contants"
	"eta/eta_mini_ht_api/common/utils/page"
	reportService "eta/eta_mini_ht_api/domian/report"
	"eta/eta_mini_ht_api/models"
	mediaDao "eta/eta_mini_ht_api/models/media"
	"sort"
	"time"
)

var (
	htConfig = config.GetConfig(contants.HT).(*config.HTBizConfig)
)

const (
	DESC            models.Order = "desc"
	ASC             models.Order = "asc"
	ESColumn                     = "mediaName"
	ESRangeColumn                = "mediaId"
	ConditionColumn              = "mediaType"
)

var (
	sortField = []string{"_score:desc"}
)

func elastic() *es.ESClient {
	return es.GetInstance()
}

type MediaDTO struct {
	MediaId                int      `json:"mediaId"`
	AuthorId               int      `json:"authorId"`
	AuthorName             string   `json:"authorName,omitempty"`
	MediaType              string   `json:"mediaType"`
	Src                    string   `json:"src"`
	MediaName              string   `json:"mediaName"`
	CoverSrc               string   `json:"coverSrc"`
	SourceType             string   `json:"sourceType"`
	MediaPlaySeconds       int      `json:"-"`
	MediaPlayMillisSeconds int      `json:"mediaPlayMillisSeconds"`
	PublishedTime          string   `json:"publishedTime"`
	PermissionIDs          string   `json:"permissionIds"`
	PermissionNames        []string `json:"permissionNames,omitempty"`
	Highlight              []string `json:"highlight,omitempty"`
}

func SearchMediaList(mediaType string, key string, from int, size int, max int64) (reports []MediaDTO, err error) {
	//同步es
	sorts := append(sortField, "publishedTime:desc")
	request := matchRangeByCondition(key, from, size, max, sorts, ConditionColumn, mediaType)
	re, err := elastic().Search(request)
	if err != nil {
		logger.Error("es搜索失败:%v", err)
	}
	hits := elastic().GetSource(re.Hits)
	for _, hit := range hits {
		var content map[string][]string
		err = json.Unmarshal(hit.Highlight, &content)
		meida := MediaDTO{}
		err = json.Unmarshal(hit.Source, &meida)
		if err != nil {
			logger.Error("解析媒体数据失败:%v", err)
			continue
		}
		meida.Highlight = content[ESColumn]
		meida.PublishedTime = meida.PublishedTime[:10]
		meida.MediaPlayMillisSeconds = meida.MediaPlaySeconds * 1000
		reports = append(reports, meida)
	}
	return
}
func SearchMaxMediaId(mediaType string, key string) (total int64, latestId int64) {
	mediaSort := []string{"mediaId:desc"}
	request := matchAllByCondition(mediaSort, key, ConditionColumn, mediaType)
	//同步es
	//re, err := elastic().Search(request)
	re, err := elastic().Count(request)
	if err != nil {
		logger.Error("es搜索失败:%v", err)
	}
	count := re.Count
	total = int64(count)
	if total > 0 {
		request = matchByCondition(mediaSort, key, ConditionColumn, mediaType, 0, count)
		re, err = elastic().Search(request)
		if err != nil {
			logger.Error("es搜索异常:%v", err)
		}
		hits := elastic().GetSource(re.Hits)
		data := hits[0].Source
		media := MediaDTO{}
		err = json.Unmarshal(data, &media)
		if err != nil {
			logger.Error("获取当前最大媒体id失败:%v", err)
			return
		}
		total = int64(len(hits))
		latestId = int64(media.MediaId)
		return
	}
	return
}
func GetMediaPermissionMappingByPermissionIds(mediaType string, permissionIds []int) (total int64, latestId int64, ids []int) {
	ids, err := mediaDao.GetMediaPermissionMappingByPermissionId(mediaType, permissionIds)
	if err != nil {
		logger.Error("获取当前最大媒体id失败:%v", err)
		return 0, 0, ids
	}
	sort.Slice(ids, func(i, j int) bool {
		return ids[i] > ids[j]
	})
	return int64(len(ids)), int64(ids[0]), ids
}
func GetTotalPageCount(mediaType string) (count int64, latestId int64) {
	return mediaDao.GetCountByMediaType(mediaType)
}
func GetTotalPageCountByAnalystId(mediaType string, analystId int) (count int64, latestId int64) {
	return mediaDao.GetCountByMediaTypeByAnalystId(mediaType, analystId)
}
func GetMediaPageByIds(mediaType string, pageInfo page.PageInfo, mediaIds []int) (list []MediaDTO, err error) {
	offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize)
	medias, err := mediaDao.GetMediaPageByIds(pageInfo.LatestId, pageInfo.PageSize, offset, mediaType, mediaIds)
	if err == nil && medias != nil {
		for _, media := range medias {
			dto := convertMediaDTO(media, false)
			list = append(list, dto)
		}
	}
	return
}

func GetMediaPageByAnalystId(mediaType string, pageInfo page.PageInfo, analystId int) (list []MediaDTO, err error) {
	offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize)
	medias, err := mediaDao.GetMediaPageByAnalystId(pageInfo.LatestId, pageInfo.PageSize, offset, mediaType, analystId)
	if err == nil && medias != nil {
		for _, media := range medias {
			dto := convertMediaDTO(media, false)
			list = append(list, dto)
		}
	}
	return
}
func convertMediaDTO(media mediaDao.Media, fullTime bool) MediaDTO {
	if fullTime {
		return MediaDTO{
			MediaId:                media.Id,
			AuthorId:               media.AuthorID,
			AuthorName:             media.AuthorName,
			MediaType:              string(media.MediaType),
			Src:                    media.Src,
			MediaName:              media.MediaName,
			SourceType:             media.SourceType,
			CoverSrc:               media.CoverSrc,
			MediaPlaySeconds:       media.MediaPlayMilliseconds,
			MediaPlayMillisSeconds: media.MediaPlayMilliseconds,
			PermissionIDs:          media.PermissionIDs,
			PublishedTime:          media.PublishedTime.Format(time.DateTime),
		}
	} else {
		return MediaDTO{
			MediaId:                media.Id,
			AuthorId:               media.AuthorID,
			AuthorName:             media.AuthorName,
			MediaType:              string(media.MediaType),
			Src:                    media.Src,
			MediaName:              media.MediaName,
			SourceType:             media.SourceType,
			CoverSrc:               media.CoverSrc,
			MediaPlaySeconds:       media.MediaPlayMilliseconds,
			MediaPlayMillisSeconds: media.MediaPlayMilliseconds,
			PermissionIDs:          media.PermissionIDs,
			PublishedTime:          media.PublishedTime.Format(time.DateOnly),
		}
	}
}
func GetMediaById(mediaType string, mediaId int) (mediaDTO MediaDTO, err error) {
	media, err := mediaDao.GetMediaById(mediaType, mediaId)
	if err != nil {
		logger.Error("查询媒体信息失败:%v", err)
		return
	}
	mediaDTO = convertMediaDTO(media, true)
	return
}
func GetPermissionsByIds(ids []int) (permissionDTOs []reportService.PermissionDTO, err error) {
	return reportService.GetFirstPermissionsByIds(ids)
}

func matchAllByCondition(sorts []string, key string, column string, value string) (request *es.ESQueryRequest) {
	req := new(es.ESQueryRequest)
	return req.CreateESQueryRequest(htConfig.GetMediaIndex(), ESColumn, key, 0, 1, sorts, es.MatchAllByCondition).ByCondition(column, value)
}

func matchByCondition(sorts []string, key string, column string, value string, from int, to int) (request *es.ESQueryRequest) {
	req := new(es.ESQueryRequest)
	return req.CreateESQueryRequest(htConfig.GetMediaIndex(), ESColumn, key, from, to, sorts, es.MatchAllByCondition).ByCondition(column, value)
}
func matchRangeByCondition(key string, from int, to int, max int64, sorts []string, column string, value string) (request *es.ESQueryRequest) {
	req := new(es.ESQueryRequest)
	return req.CreateESQueryRequest(htConfig.GetMediaIndex(), ESColumn, key, from, to, sorts, es.RangeByCondition).Range(0, max, ESRangeColumn).ByCondition(column, value)
}

func GetImageSrc(id int) (src string, err error) {
	return mediaDao.GetImageSrc(id)
}
