package user

import (
	"context"
	"strconv"
	"strings"

	modelUser "github.com/perfect-panel/server/internal/model/user"
	"github.com/perfect-panel/server/internal/svc"
	"github.com/perfect-panel/server/internal/types"
	"github.com/perfect-panel/server/pkg/logger"
	"github.com/perfect-panel/server/pkg/xerr"
	"github.com/pkg/errors"
)

type GetFamilyListLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logger.Logger
}

func NewGetFamilyListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetFamilyListLogic {
	return &GetFamilyListLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logger.WithContext(ctx),
	}
}

func (l *GetFamilyListLogic) GetFamilyList(req *types.GetFamilyListRequest) (*types.GetFamilyListResponse, error) {
	page := req.Page
	size := req.Size
	if page <= 0 {
		page = 1
	}
	if size <= 0 {
		size = 20
	}
	if size > 200 {
		size = 200
	}

	query := l.svcCtx.DB.WithContext(l.ctx).
		Model(&modelUser.UserFamily{}).
		Where("user_family.deleted_at IS NULL")

	if req.OwnerUserId != nil {
		query = query.Where("user_family.owner_user_id = ?", *req.OwnerUserId)
	}
	if req.FamilyId != nil {
		query = query.Where("user_family.id = ?", *req.FamilyId)
	}
	if req.UserId != nil {
		query = query.Where(
			"EXISTS (SELECT 1 FROM user_family_member ufm WHERE ufm.family_id = user_family.id AND ufm.deleted_at IS NULL AND ufm.status = ? AND ufm.user_id = ?)",
			modelUser.FamilyMemberActive, *req.UserId,
		)
	}
	if statusValue, ok := normalizeFamilyStatusInput(req.Status); ok {
		query = query.Where("user_family.status = ?", statusValue)
	}

	keyword := strings.TrimSpace(req.Keyword)
	if keyword != "" {
		keywordLike := "%" + keyword + "%"
		query = query.Where(
			"(CAST(user_family.id AS CHAR) LIKE ? OR CAST(user_family.owner_user_id AS CHAR) LIKE ? OR "+
				"EXISTS (SELECT 1 FROM user_auth_methods owner_auth WHERE owner_auth.user_id = user_family.owner_user_id AND owner_auth.deleted_at IS NULL AND owner_auth.auth_identifier LIKE ?) OR "+
				"EXISTS (SELECT 1 FROM user_family_member keyword_member JOIN user_auth_methods keyword_auth ON keyword_auth.user_id = keyword_member.user_id AND keyword_auth.deleted_at IS NULL WHERE keyword_member.family_id = user_family.id AND keyword_member.deleted_at IS NULL AND keyword_auth.auth_identifier LIKE ?))",
			keywordLike, keywordLike, keywordLike, keywordLike,
		)
	}

	var total int64
	if err := query.Count(&total).Error; err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "count family list failed")
	}

	var families []modelUser.UserFamily
	if err := query.Order("user_family.id DESC").
		Limit(size).
		Offset((page - 1) * size).
		Find(&families).Error; err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query family list failed")
	}

	if len(families) == 0 {
		return &types.GetFamilyListResponse{
			Total: total,
			List:  []types.FamilySummary{},
		}, nil
	}

	ownerIDs := make([]int64, 0, len(families))
	familyIDs := make([]int64, 0, len(families))
	for _, family := range families {
		ownerIDs = append(ownerIDs, family.OwnerUserId)
		familyIDs = append(familyIDs, family.Id)
	}

	identifierMap, identifierErr := findUserIdentifiers(l.ctx, l.svcCtx.DB, ownerIDs)
	if identifierErr != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query family owner identifiers failed")
	}

	type familyCount struct {
		FamilyId int64
		Count    int64
	}
	var counts []familyCount
	if err := l.svcCtx.DB.WithContext(l.ctx).
		Table("user_family_member").
		Select("family_id, COUNT(1) as count").
		Where("family_id IN ? AND deleted_at IS NULL AND status = ?", familyIDs, modelUser.FamilyMemberActive).
		Group("family_id").
		Scan(&counts).Error; err != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query family member counts failed")
	}
	countMap := make(map[int64]int64, len(counts))
	for _, count := range counts {
		countMap[count.FamilyId] = count.Count
	}

	list := make([]types.FamilySummary, 0, len(families))
	for _, family := range families {
		ownerInfo := identifierMap[family.OwnerUserId]
		ownerIdentifier := ownerInfo.Identifier
		ownerAuthType := ownerInfo.AuthType
		if ownerIdentifier == "" {
			ownerIdentifier = strconv.FormatInt(family.OwnerUserId, 10)
		}

		list = append(list, types.FamilySummary{
			FamilyId:          family.Id,
			OwnerUserId:       family.OwnerUserId,
			OwnerIdentifier:   ownerIdentifier,
			OwnerAuthType:     ownerAuthType,
			Status:            mapFamilyStatus(family.Status),
			ActiveMemberCount: countMap[family.Id],
			MaxMembers:        family.MaxMembers,
			CreatedAt:         family.CreatedAt.Unix(),
			UpdatedAt:         family.UpdatedAt.Unix(),
		})
	}

	return &types.GetFamilyListResponse{
		Total: total,
		List:  list,
	}, nil
}
