package report

import (
	"encoding/json"
	logger "eta/eta_mini_ht_api/common/component/log"
	"eta/eta_mini_ht_api/common/exception"
	"eta/eta_mini_ht_api/common/utils/date"
	"eta/eta_mini_ht_api/common/utils/page"
	mediaService "eta/eta_mini_ht_api/domian/media"
	reportService "eta/eta_mini_ht_api/domian/report"
	userService "eta/eta_mini_ht_api/domian/user"
	"sync"
	"time"
)

const (
	SourceETA = "ETA"
	SourceHT  = "HT"
)

type PublishRankedReport struct {
	Id              int         `json:"reportId"`
	OrgId           int         `json:"orgId"`
	Title           string      `json:"title"`
	Abstract        string      `json:"abstract"`
	PermissionNames interface{} `json:"permissionNames,omitempty"`
	PublishedTime   string      `json:"publishedTime"`
	CoverUrl        string      `json:"coverUrl"`
}

type HotRankedReport struct {
	Id                int            `json:"reportId"`
	OrgId             int            `json:"orgId"`
	Abstract          string         `json:"abstract"`
	Count             int            `json:"count"`
	Title             string         `json:"title"`
	PublishedTime     string         `json:"publishedTime"`
	SecondPermissions map[int]string `json:"-"`
	Permissions       map[int]string `json:"-"`
	PermissionNames   interface{}    `json:"permissionNames,omitempty"`
	CoverUrl          string         `json:"coverUrl"`
}

type PermissionNode struct {
	ID       int               `json:"id"`
	Name     string            `json:"name"`
	ParentID int               `json:"parentId"`
	Children []*PermissionNode `json:"children,omitempty"`
}

type RecordCount struct {
	UserId     int
	Mobile     string
	ReportId   int
	IpAddress  string
	Location   string
	Referer    string
	Additional string
}

func GetReportById(reportId int) (report reportService.ReportDTO, err error) {
	report, err = reportService.GetGetReportById(reportId)
	if err != nil {
		logger.Error("获取研报失败:%v", err)
		err = exception.New(exception.GetReportFailed)
		return
	}
	var detail interface{}
	var pdfUrl string
	switch report.Source {
	case SourceETA:
		detail, err = getETAReportDetail(&report)
		if err != nil {
			logger.Error("获取研报详情失败失败:%v")
			err = exception.New(exception.GetReportFailed)
			return
		}
		var jsonStr []byte
		jsonStr, err = json.Marshal(detail)
		if err != nil {
			logger.Error("生成研报详情失败:%v", err)
			err = exception.New(exception.GetReportFailed)
		}
		report.Detail = jsonStr
		return
	case SourceHT:
		pdfUrl, err = getHTReportDetail(&report)
		if err != nil {
			logger.Error("获取研报详情失败失败:%v")
			err = exception.New(exception.GetReportFailed)
			return
		}
		report.PdfUrl = pdfUrl
		return
	default:
		logger.Error("不支持的研报来演:%v")
		err = exception.New(exception.GetReportFailed)
		return
	}
}

func getETAReportDetail(report *reportService.ReportDTO) (etaReport reportService.ETAReportDTO, err error) {
	return reportService.GetETAReport(report.OrgId)
}

func getHTReportDetail(report *reportService.ReportDTO) (url string, err error) {
	return reportService.GetHtReport(report.OrgId)
}
func GetTotalPageCount() (total int64, latestId int64, err error) {
	return reportService.GetTotalPageCount()
}

func GetTotalPageCountByPermissionIds(permissionIds []int) (total int64, latestId int64, ids map[string][]int) {
	if len(permissionIds) == 0 {
		var err error
		total, latestId, err = GetTotalPageCount()
		if err != nil {
			logger.Error("获取统计信息失败:%v", err)
		}
		return total, latestId, map[string][]int{}
	}
	return reportService.GetTotalPageCountByPermissionIds(permissionIds)
}
func SearchReportList(key string, pageInfo page.PageInfo) (reports []reportService.ReportDTO, err error) {
	offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize)
	reports, err = reportService.SearchReportList(key, offset, pageInfo.PageSize, pageInfo.LatestId)
	var wg sync.WaitGroup
	wg.Add(len(reports))
	for i := 0; i < len(reports); i++ {
		go func(report *reportService.ReportDTO) {
			defer wg.Done()
			report.PermissionNames = getReportPermissionNames(report.OrgId, report.Source)
			var src string
			src, err = mediaService.GetImageSrc(report.CoverSrc)
			if err != nil {
				logger.Error("获取图片地址失败:%v", err)
				src = ""
			} else {
				report.CoverUrl = src
			}
		}(&reports[i])
	}
	wg.Wait()
	if err != nil {
		err = exception.New(exception.SearchReportPageFailed)
	}
	return
}

func SearchMaxReportId(key string) (total int64, id int64) {
	return reportService.SearchMaxReportId(key)
}

// GetReportPage 分页获取报告列表
func GetReportPage(pageInfo page.PageInfo, orgIds map[string][]int, searchAll bool) (list []reportService.ReportDTO, err error) {
	list, err = reportService.GetReportPageByOrgIds(pageInfo, orgIds, searchAll)
	//并发获取研报的标签
	var wg sync.WaitGroup
	wg.Add(len(list))
	for i := 0; i < len(list); i++ {
		go func(report *reportService.ReportDTO) {
			defer wg.Done()
			report.PermissionNames = getReportPermissionNames(report.OrgId, report.Source)
			var src string
			src, err = mediaService.GetImageSrc(report.CoverSrc)
			if err != nil {
				logger.Error("获取图片地址失败:%v", err)
				src = ""
			} else {
				report.CoverUrl = src
			}
		}(&list[i])
	}
	wg.Wait()
	if err != nil {
		err = exception.New(exception.QueryReportPageFailed)
	}
	return
}

func GetTotalPageCountByAnalyst(analyst string) (total int64, latestId int64) {
	return reportService.GetTotalPageCountByAnalyst(analyst)
}
func GetReportPageByAnalyst(pageInfo page.PageInfo, analyst string) (list []reportService.ReportDTO, err error) {
	list, err = reportService.GetReportPageByAnalyst(pageInfo, analyst)
	//并发获取研报的标签
	var wg sync.WaitGroup
	wg.Add(len(list))
	for i := 0; i < len(list); i++ {
		go func(report *reportService.ReportDTO) {
			defer wg.Done()
			report.PermissionNames = getReportPermissionNames(report.OrgId, report.Source)
		}(&list[i])
	}
	wg.Wait()
	if err != nil {
		err = exception.New(exception.QueryReportPageFailed)
	}
	return
}
func CountReport(count RecordCount) error {
	dto := convertToRecordCountDTO(count)
	return userService.CountReport(dto)
}
func GetRandedReportByWeeklyHot(limit int) (reports []HotRankedReport, err error) {
	end := time.Now()
	begin := date.GetBeginOfTheWeek(end, time.Monday)
	hotReports := userService.GetHotReports(begin.Format(time.DateOnly), end.Format(time.DateOnly), limit)
	if len(hotReports) > 0 {
		var dtoList []reportService.ReportDTO
		var ids []int
		for i := 0; i < len(hotReports); i++ {
			ids = append(ids, hotReports[i].ReportId)
		}
		dtoList, err = reportService.GetListByCondition("id", ids)
		if err != nil {
			logger.Error("获取本周最热研报列表失败:%v", err)
			err = exception.New(exception.GetHotRandListFailed)
			return
		}
		var wg sync.WaitGroup
		wg.Add(len(dtoList))
		for i := 0; i < len(dtoList); i++ {
			go func(report *reportService.ReportDTO) {
				defer wg.Done()
				report.Permissions = getReportPermissionsMap(report.OrgId, report.Source)
				report.SecondPermission = getReportSecondPermissionsMap(report.OrgId, report.Source)
				var label []string
				for _, permission := range report.Permissions {
					label = append(label, permission)
				}
				report.PermissionNames = label
			}(&dtoList[i])
		}
		wg.Wait()
		reports = make([]HotRankedReport, len(ids))
		for i := 0; i < len(dtoList); i++ {
			report := convertToHotRankedReport(dtoList[i])
			for j := 0; j < len(hotReports); j++ {
				if hotReports[j].ReportId == report.Id {
					report.Count = hotReports[j].Count
					reports[j] = report
					break
				}
			}
		}
	} else {
		reports = []HotRankedReport{}
	}
	return
}

func GetRandedReportByPublishTimeWeekly(limit int, week bool) (reports []PublishRankedReport, err error) {
	dtoList, err := reportService.GetListOrderByConditionWeekly(week, "published_time", limit, reportService.DESC)
	if err != nil {
		logger.Error("获取最新发布的研报列表失败:%v", err)
		err = exception.New(exception.GetPublishedRandListFailed)
		return
	}
	//并发获取研报的标签
	var wg sync.WaitGroup
	wg.Add(len(dtoList))
	for i := 0; i < len(dtoList); i++ {
		go func(report *reportService.ReportDTO) {
			defer wg.Done()
			report.PermissionNames = getReportPermissionNames(report.OrgId, report.Source)
		}(&dtoList[i])
	}
	wg.Wait()
	reports = convertToPublishRankedReportList(dtoList)
	return
}

func getReportPermissionNames(id int, source string) (labels []string) {
	permissions := reportService.GetReportPermissionsById(id, source)
	for _, permission := range permissions {
		labels = append(labels, permission.Name)
	}
	return
}
func getReportSecondPermissionsMap(id int, source string) (permissionMap map[int]string) {
	permissionMap = make(map[int]string)
	permissions := reportService.GetReportSecondPermissionsById(id, source)
	for _, permission := range permissions {
		permissionMap[permission.ID] = permission.Name
	}
	return
}
func getReportPermissionsMap(id int, source string) (permissionMap map[int]string) {
	permissionMap = make(map[int]string)
	permissions := reportService.GetReportPermissionsById(id, source)
	for _, permission := range permissions {
		permissionMap[permission.ID] = permission.Name
	}
	return
}
func GetPermissionList() (root *PermissionNode, err error) {
	list, err := reportService.GetPermissionList()
	if err != nil {
		logger.Error("获取品种列表失败:%v", err)
		err = exception.New(exception.GetPermissionListFailed)
		return
	}
	root = &PermissionNode{
		ID:       0,
		ParentID: 0,
	}
	assemblePermissionNode(list, root, 0, 2)
	return
}

func assemblePermissionNode(list []reportService.PermissionDTO, node *PermissionNode, current int, level int) {
	if node != nil && current < level {
		for _, permission := range list {
			if permission.ParentID == node.ID {
				childNode := &PermissionNode{
					ID:       permission.ID,
					Name:     permission.Name,
					ParentID: permission.ParentID,
				}
				node.Children = append(node.Children, childNode)
				assemblePermissionNode(list, childNode, current+1, level)
			}
		}
	}
}
func convertToHotRankedReport(dto reportService.ReportDTO) (report HotRankedReport) {
	src, err := mediaService.GetImageSrc(dto.CoverSrc)
	if err != nil {
		logger.Error("获取封面图片失败:%v", err)
		src = ""
	}
	report = HotRankedReport{
		Id:                dto.ReportID,
		OrgId:             dto.OrgId,
		Abstract:          dto.Abstract,
		PublishedTime:     dto.PublishedTime,
		Title:             dto.Title,
		SecondPermissions: dto.SecondPermission,
		Permissions:       dto.Permissions,
		PermissionNames:   dto.PermissionNames,
		CoverUrl:          src,
	}
	return
}
func convertToPublishRankedReportList(dtoList []reportService.ReportDTO) (reports []PublishRankedReport) {
	reports = []PublishRankedReport{}
	for _, dto := range dtoList {
		src, err := mediaService.GetImageSrc(dto.CoverSrc)
		if err != nil {
			logger.Error("获取封面图片失败:%v", err)
			src = ""
		}
		report := PublishRankedReport{
			Id:              dto.ReportID,
			OrgId:           dto.OrgId,
			PublishedTime:   dto.PublishedTime,
			Abstract:        dto.Abstract,
			Title:           dto.Title,
			PermissionNames: dto.PermissionNames,
			CoverUrl:        src,
		}
		reports = append(reports, report)
	}
	return
}

func convertToRecordCountDTO(record RecordCount) (dto userService.RecordCountDTO) {
	return userService.RecordCountDTO{
		UserId:     record.UserId,
		Mobile:     record.Mobile,
		SourceId:   record.ReportId,
		IpAddress:  record.IpAddress,
		Location:   record.Location,
		Referer:    record.Referer,
		Additional: record.Additional,
	}
}
