package common

import (
	"context"

	modelUser "github.com/perfect-panel/server/internal/model/user"
	"github.com/perfect-panel/server/pkg/xerr"
	"github.com/pkg/errors"
	"gorm.io/gorm"
)

const (
	EntitlementSourceSelf        = "self"
	EntitlementSourceFamilyOwner = "family_owner"
)

type EntitlementContext struct {
	EffectiveUserID int64
	Source          string
	OwnerUserID     int64
	ReadOnly        bool
}

type familyEntitlementRelation struct {
	Role         uint8 `gorm:"column:role"`
	FamilyStatus uint8 `gorm:"column:family_status"`
	OwnerUserID  int64 `gorm:"column:owner_user_id"`
}

func ResolveEntitlementUser(ctx context.Context, db *gorm.DB, currentUserID int64) (*EntitlementContext, error) {
	entitlement := buildEntitlementContext(currentUserID, nil)
	if currentUserID <= 0 {
		return entitlement, nil
	}

	var relation familyEntitlementRelation
	query := db.WithContext(ctx).
		Table("user_family_member").
		Select("user_family_member.role, user_family.status AS family_status, user_family.owner_user_id").
		Joins("JOIN user_family ON user_family.id = user_family_member.family_id AND user_family.deleted_at IS NULL").
		Where("user_family_member.user_id = ? AND user_family_member.deleted_at IS NULL AND user_family_member.status = ?", currentUserID, modelUser.FamilyMemberActive).
		Order("user_family_member.role").
		Limit(1).
		Find(&relation)
	if query.Error != nil {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query family entitlement relation failed")
	}
	if query.RowsAffected == 0 {
		return entitlement, nil
	}

	return buildEntitlementContext(currentUserID, &relation), nil
}

func DenyIfFamilyMemberReadonly(ctx context.Context, db *gorm.DB, currentUserID int64) error {
	entitlement, err := ResolveEntitlementUser(ctx, db, currentUserID)
	if err != nil {
		return err
	}
	return denyReadonlyEntitlement(entitlement)
}

func buildEntitlementContext(currentUserID int64, relation *familyEntitlementRelation) *EntitlementContext {
	entitlement := &EntitlementContext{
		EffectiveUserID: currentUserID,
		Source:          EntitlementSourceSelf,
	}
	if relation == nil {
		return entitlement
	}
	if relation.Role == modelUser.FamilyRoleMember &&
		relation.FamilyStatus == modelUser.FamilyStatusActive &&
		relation.OwnerUserID > 0 &&
		relation.OwnerUserID != currentUserID {
		return &EntitlementContext{
			EffectiveUserID: relation.OwnerUserID,
			Source:          EntitlementSourceFamilyOwner,
			OwnerUserID:     relation.OwnerUserID,
			ReadOnly:        true,
		}
	}
	return entitlement
}

func denyReadonlyEntitlement(entitlement *EntitlementContext) error {
	if entitlement != nil && entitlement.ReadOnly {
		return errors.Wrapf(xerr.NewErrCode(xerr.FamilyOwnerOperationForbidden), "family member operation is forbidden")
	}
	return nil
}
