// Package middleware provides privacy enforcement for experiment access control.
package middleware

import (
	"context"
	"fmt"

	"github.com/jfraeys/fetch_ml/internal/auth"
)

// PrivacyLevel defines experiment visibility levels.
type PrivacyLevel string

const (
	// PrivacyPrivate restricts access to owner only.
	PrivacyPrivate PrivacyLevel = "private"
	// PrivacyTeam allows team members to view.
	PrivacyTeam PrivacyLevel = "team"
	// PrivacyPublic allows all authenticated users.
	PrivacyPublic PrivacyLevel = "public"
	// PrivacyAnonymized allows access with PII stripped.
	PrivacyAnonymized PrivacyLevel = "anonymized"
)

// PrivacyEnforcer handles privacy access control.
type PrivacyEnforcer struct {
	enforceTeams bool
	auditAccess  bool
}

// NewPrivacyEnforcer creates a privacy enforcer.
func NewPrivacyEnforcer(enforceTeams, auditAccess bool) *PrivacyEnforcer {
	return &PrivacyEnforcer{
		enforceTeams: enforceTeams,
		auditAccess:  auditAccess,
	}
}

// CanAccess checks if a user can access an experiment.
func (pe *PrivacyEnforcer) CanAccess(
	ctx context.Context,
	user *auth.User,
	experimentOwner string,
	level string,
	team string,
) (bool, error) {
	privacyLevel := GetPrivacyLevelFromString(level)
	switch privacyLevel {
	case PrivacyPublic:
		return true, nil
	case PrivacyPrivate:
		return user.Name == experimentOwner || user.Admin, nil
	case PrivacyTeam:
		if user.Name == experimentOwner || user.Admin {
			return true, nil
		}
		if !pe.enforceTeams {
			return true, nil // Teams not enforced, allow access
		}
		// Check if user is in same team
		return pe.isUserInTeam(ctx, user, team)
	case PrivacyAnonymized:
		// Anonymized data is accessible but with PII stripped
		return true, nil
	default:
		return false, fmt.Errorf("unknown privacy level: %s", privacyLevel)
	}
}

func (pe *PrivacyEnforcer) isUserInTeam(ctx context.Context, user *auth.User, team string) (bool, error) {
	// Note: Team membership check not yet implemented.
	// Future: query teams database or use JWT claims for verification.
	// Currently denies access when team enforcement is enabled.
	_ = ctx
	_ = user
	_ = team
	return false, nil
}

// GetPrivacyLevelFromString converts string to PrivacyLevel.
func GetPrivacyLevelFromString(level string) PrivacyLevel {
	switch level {
	case "private":
		return PrivacyPrivate
	case "team":
		return PrivacyTeam
	case "public":
		return PrivacyPublic
	case "anonymized":
		return PrivacyAnonymized
	default:
		return PrivacyPrivate // Default to private for safety
	}
}
