package service

import (
	"context"
	"fmt"
	"strconv"

	"github.com/lvhao0419/fetch_flash/dao"
	"github.com/lvhao0419/fetch_flash/model"
	"github.com/lvhao0419/fetch_flash/resource"
)

type ActivityQueryParams struct {
	StartDate string  `json:"startDate"`
	EndDate   string  `json:"endDate"`
	StartTime string  `json:"startTime"`
	EndTime   string  `json:"endTime"`
	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
	Distance  float64 `json:"distance"`
}

type ActivityResult struct {
	ID              int     `json:"id"`
	Title           string  `json:"title"`
	Date            string  `json:"date"`
	Time            string  `json:"time"`
	Location        string  `json:"location"`
	Address         string  `json:"address"`
	Latitude        float64 `json:"latitude"`
	Longitude       float64 `json:"longitude"`
	Participants    int     `json:"participants"`
	MaxParticipants int     `json:"maxParticipants"`
	Cost            string  `json:"cost"`
	Description     string  `json:"description"`
	Club            string  `json:"club"`
}

func QueryActivities(ctx context.Context, params ActivityQueryParams) ([]ActivityResult, error) {
	if params.Distance <= 0 {
		params.Distance = 5
	}

	placeIDs := dao.SearchNearbyPlaces(ctx, params.Longitude, params.Latitude, params.Distance)

	var places []model.Place
	resource.MysqlDB.Where("placeId IN ?", placeIDs).Find(&places)

	placeMap := make(map[int32]model.Place)
	for _, place := range places {
		placeMap[place.PlaceID] = place
	}

	var activities []model.Activity
	query := resource.MysqlDB.Where("placeId IN ?", placeIDs)
	if params.StartDate != "" {
		query = query.Where("activityDate >= ?", params.StartDate)
	}
	if params.EndDate != "" {
		query = query.Where("endDate <= ?", params.EndDate)
	}
	if params.StartTime != "" {
		query = query.Where("startTime >= ?", params.StartTime)
	}
	if params.EndTime != "" {
		query = query.Where("endTime <= ?", params.EndTime)
	}

	query.Find(&activities)

	activityIDs := make([]int32, len(activities))
	for i, activity := range activities {
		activityIDs[i] = activity.ActivityID
	}

	var members []model.ActivityMember
	resource.MysqlDB.Where("activityId IN ?", activityIDs).Find(&members)

	memberMap := make(map[int32][]model.ActivityMember)
	for _, member := range members {
		memberMap[member.ActivityID] = append(memberMap[member.ActivityID], member)
	}

	var results []ActivityResult
	for _, activity := range activities {
		if place, ok := placeMap[activity.PlaceID]; ok {
			var avgLevel float64
			if activityMembers, exists := memberMap[activity.ActivityID]; exists && len(activityMembers) > 0 {
				var totalLevel float64
				for _, member := range activityMembers {
					if level, err := strconv.ParseFloat(member.Level, 64); err == nil {
						totalLevel += level
					}
				}
				avgLevel = totalLevel / float64(len(activityMembers))
			}

			result := ActivityResult{
				ID:              int(activity.ActivityID),
				Title:           activity.ActivityTitle,
				Date:            activity.ActivityDate,
				Time:            activity.StartTime + "-" + activity.EndTime,
				Location:        place.PlaceName,
				Address:         activity.ActivityAddress,
				Latitude:        place.Latitude,
				Longitude:       place.Longitude,
				Participants:    int(activity.ApplyMemberNum),
				MaxParticipants: int(activity.NeedMemberNum),
				Cost:            activity.ShowCost,
				Description:     fmt.Sprintf(`平均等级：%s`, strconv.FormatFloat(avgLevel, 'f', 2, 64)),
				Club:            activity.OrganizerName,
			}
			results = append(results, result)
		}
	}

	return results, nil
}

type ActivityDetailResult struct {
	ID              int                    `json:"id"`
	Title           string                 `json:"title"`
	Date            string                 `json:"date"`
	Time            string                 `json:"time"`
	Location        string                 `json:"location"`
	Address         string                 `json:"address"`
	Latitude        float64                `json:"latitude"`
	Longitude       float64                `json:"longitude"`
	Participants    int                    `json:"participants"`
	MaxParticipants int                    `json:"maxParticipants"`
	Cost            string                 `json:"cost"`
	Description     string                 `json:"description"`
	Organizer       string                 `json:"organizer"`
	Contact         string                 `json:"contact"`
	Requirements    string                 `json:"requirements"`
	CreatedTime     string                 `json:"createdTime"`
	Club            string                 `json:"club"`
	Place           *model.Place           `json:"place,omitempty"`
	Members         []model.ActivityMember `json:"members,omitempty"`
	ClubInfo        *model.Club            `json:"clubInfo,omitempty"`
}

func GetActivityDetail(ctx context.Context, activityID int32) (*ActivityDetailResult, error) {
	var activity model.Activity
	if err := resource.MysqlDB.First(&activity, "activityId = ?", activityID).Error; err != nil {
		return nil, err
	}

	var place model.Place
	placeResult := resource.MysqlDB.First(&place, "placeId = ?", activity.PlaceID)
	var placePtr *model.Place
	if placeResult.Error == nil {
		placePtr = &place
	}

	var members []model.ActivityMember
	resource.MysqlDB.Where("activityId = ?", activityID).Find(&members)

	var club model.Club
	clubResult := resource.MysqlDB.First(&club, "clubId = ?", activity.ClubID)
	var clubPtr *model.Club
	if clubResult.Error == nil {
		clubPtr = &club
	}

	var avgLevel float64
	if len(members) > 0 {
		var totalLevel float64
		for _, member := range members {
			if level, err := strconv.ParseFloat(member.Level, 64); err == nil {
				totalLevel += level
			}
		}
		avgLevel = totalLevel / float64(len(members))
	}

	result := &ActivityDetailResult{
		ID:              int(activity.ActivityID),
		Title:           activity.ActivityTitle,
		Date:            activity.ActivityDate,
		Time:            activity.StartTime + "-" + activity.EndTime,
		Location:        place.PlaceName,
		Address:         activity.ActivityAddress,
		Latitude:        place.Latitude,
		Longitude:       place.Longitude,
		Participants:    int(activity.ApplyMemberNum),
		MaxParticipants: int(activity.NeedMemberNum),
		Cost:            activity.ShowCost,
		Description:     fmt.Sprintf(`平均等级：%s`, strconv.FormatFloat(avgLevel, 'f', 2, 64)),
		Organizer:       activity.OrganizerName,
		Contact:         "", // 联系电话，需要从数据库获取
		Requirements:    "", // 活动要求，需要从数据库获取
		CreatedTime:     activity.CreateTime.Format("2006-01-02 15:04:05"),
		Club:            activity.OrganizerName,
		Place:           placePtr,
		Members:         members,
		ClubInfo:        clubPtr,
	}

	return result, nil
}
