package service

import (
	"fmt"
	"log"

	"metazone.cc/metalab/internal/common"
	"metazone.cc/metalab/internal/model"
)

// FollowStatus 关注关系状态
type FollowStatus struct {
	IFollow    bool `json:"i_follow"`
	TheyFollow bool `json:"they_follow"`
}

// FollowListResult 关注/粉丝列表结果
type FollowListResult struct {
	Items      []model.UserFollow `json:"items"`
	Total      int64              `json:"total"`
	Page       int                `json:"page"`
	TotalPages int                `json:"total_pages"`
	ListPublic bool               `json:"list_public"`
	Accessible bool               `json:"accessible"`
}

// followNotifier 关注通知接口（ISP）
type followNotifier interface {
	NotifyFollow(followerID, followeeID uint)
}

// FollowService 关注业务逻辑
type FollowService struct {
	repo     FollowStore
	notifier followNotifier
}

// NewFollowService 构造函数
func NewFollowService(repo FollowStore) *FollowService {
	return &FollowService{repo: repo}
}

// SetNotifier 注入通知服务
func (s *FollowService) SetNotifier(n followNotifier) {
	s.notifier = n
}

// Toggle 关注/取消关注，返回操作后的关注状态（true=已关注）
func (s *FollowService) Toggle(followerID, followeeID uint) (bool, error) {
	if followerID == followeeID {
		return false, fmt.Errorf("不能关注自己")
	}

	var isFollowing bool
	err := s.repo.Transaction(func(txRepo FollowStore) error {
		exists, err := txRepo.Exists(followerID, followeeID)
		if err != nil {
			return fmt.Errorf("查询关注状态失败: %w", err)
		}

		if exists {
			if err := txRepo.Delete(followerID, followeeID); err != nil {
				return fmt.Errorf("取消关注失败: %w", err)
			}
			if err := txRepo.IncrFollowingCount(followerID, -1); err != nil {
				return fmt.Errorf("更新关注数失败: %w", err)
			}
			if err := txRepo.IncrFollowersCount(followeeID, -1); err != nil {
				return fmt.Errorf("更新粉丝数失败: %w", err)
			}
			isFollowing = false
		} else {
			follow := &model.UserFollow{
				FollowerID: followerID,
				FolloweeID: followeeID,
			}
			if err := txRepo.Create(follow); err != nil {
				return fmt.Errorf("关注失败: %w", err)
			}
			if err := txRepo.IncrFollowingCount(followerID, 1); err != nil {
				return fmt.Errorf("更新关注数失败: %w", err)
			}
			if err := txRepo.IncrFollowersCount(followeeID, 1); err != nil {
				return fmt.Errorf("更新粉丝数失败: %w", err)
			}
			isFollowing = true
		}
		return nil
	})

	if err == nil && isFollowing {
		s.sendFollowNotification(followerID, followeeID)
	}

	return isFollowing, err
}

// sendFollowNotification 发送关注通知（非关键路径）
func (s *FollowService) sendFollowNotification(followerID, followeeID uint) {
	if s.notifier != nil && followerID != followeeID {
		s.notifier.NotifyFollow(followerID, followeeID)
	}
}

// GetStatus 查询当前用户对目标用户的关注关系
func (s *FollowService) GetStatus(currentUserID, targetUserID uint) (*FollowStatus, error) {
	if currentUserID == 0 {
		return &FollowStatus{}, nil
	}

	iFollow, err := s.repo.Exists(currentUserID, targetUserID)
	if err != nil {
		return nil, fmt.Errorf("查询我是否关注: %w", err)
	}

	theyFollow, err := s.repo.Exists(targetUserID, currentUserID)
	if err != nil {
		return nil, fmt.Errorf("查询对方是否关注: %w", err)
	}

	return &FollowStatus{
		IFollow:    iFollow,
		TheyFollow: theyFollow,
	}, nil
}

// ListFollowers 粉丝列表（含隐私控制）
func (s *FollowService) ListFollowers(userID, currentUserID uint, page, pageSize int) (*FollowListResult, error) {
	listPublic, err := s.repo.GetFollowListPublic(userID)
	if err != nil {
		log.Printf("[FollowService] ListFollowers GetFollowListPublic error uid=%d: %v, fallback to public", userID, err)
		listPublic = true
	}

	p := common.Pagination{Page: page, PageSize: pageSize}
	p.DefaultPagination()

	accessible := listPublic || currentUserID == userID

	var items []model.UserFollow
	var total int64

	if accessible {
		items, total, err = s.repo.ListFollowers(userID, p.Offset(), p.PageSize)
		if err != nil {
			return nil, fmt.Errorf("查询粉丝列表: %w", err)
		}
	} else {
		total, err = s.repo.CountFollowers(userID)
		if err != nil {
			return nil, fmt.Errorf("查询粉丝数: %w", err)
		}
		items = []model.UserFollow{}
	}

	if items == nil {
		items = []model.UserFollow{}
	}

	return &FollowListResult{
		Items:      items,
		Total:      total,
		Page:       p.Page,
		TotalPages: common.PageCount(total, p.PageSize),
		ListPublic: listPublic,
		Accessible: accessible,
	}, nil
}

// ListFollowing 关注列表（含隐私控制）
func (s *FollowService) ListFollowing(userID, currentUserID uint, page, pageSize int) (*FollowListResult, error) {
	listPublic, err := s.repo.GetFollowListPublic(userID)
	if err != nil {
		log.Printf("[FollowService] ListFollowing GetFollowListPublic error uid=%d: %v, fallback to public", userID, err)
		listPublic = true
	}

	p := common.Pagination{Page: page, PageSize: pageSize}
	p.DefaultPagination()

	accessible := listPublic || currentUserID == userID

	var items []model.UserFollow
	var total int64

	if accessible {
		items, total, err = s.repo.ListFollowing(userID, p.Offset(), p.PageSize)
		if err != nil {
			return nil, fmt.Errorf("查询关注列表: %w", err)
		}
	} else {
		total, err = s.repo.CountFollowing(userID)
		if err != nil {
			return nil, fmt.Errorf("查询关注数: %w", err)
		}
		items = []model.UserFollow{}
	}

	if items == nil {
		items = []model.UserFollow{}
	}

	return &FollowListResult{
		Items:      items,
		Total:      total,
		Page:       p.Page,
		TotalPages: common.PageCount(total, p.PageSize),
		ListPublic: listPublic,
		Accessible: accessible,
	}, nil
}
