package bootstrap

import (
	"baron-sso-backend/internal/domain"
	"baron-sso-backend/internal/repository"
	"context"
	"log/slog"

	"gorm.io/gorm"
)

// SyncKetoRelations synchronizes all existing DB users, tenants and RPs to Ory Keto via Outbox.
// This ensures data consistency for existing data when ReBAC is introduced.
func SyncKetoRelations(db *gorm.DB, outbox repository.KetoOutboxRepository) error {
	slog.Info("🚀 Starting Keto ReBAC relation synchronization (via Outbox)...")
	ctx := context.Background()

	// 1. Sync All Tenants
	var tenants []domain.Tenant
	if err := db.Find(&tenants).Error; err != nil {
		return err
	}
	slog.Info("Syncing tenants to Keto Outbox", "count", len(tenants))
	for _, t := range tenants {
		// Global Super Admin access to every tenant
		_ = outbox.Create(ctx, &domain.KetoOutbox{
			Namespace: "Tenant",
			Object:    t.ID,
			Relation:  "admins",
			Subject:   "System:global#super_admins",
			Action:    domain.KetoOutboxActionCreate,
		})

		if t.ParentID != nil {
			_ = outbox.Create(ctx, &domain.KetoOutbox{
				Namespace: "Tenant",
				Object:    t.ID,
				Relation:  "parents",
				Subject:   "Tenant:" + *t.ParentID,
				Action:    domain.KetoOutboxActionCreate,
			})
		}
	}

	// 2. Sync All RelyingParties (if needed)
	// Note: We'll need a way to list them from Hydra or local DB if we had them.
	// Assuming they are in a table domain.RelyingParty (though it was removed, let's see)
	// Actually, the comment said SSOT is Hydra. But we might have them in a local table for metadata.
	// If not, we skip for now or fetch from Hydra.

	// 3. Sync All Users Roles and Tenant Memberships
	var users []domain.User
	if err := db.Find(&users).Error; err != nil {
		return err
	}
	slog.Info("Syncing users to Keto Outbox", "count", len(users))
	for _, u := range users {
		// Tenant Membership
		if u.TenantID != nil {
			_ = outbox.Create(ctx, &domain.KetoOutbox{
				Namespace: "Tenant",
				Object:    *u.TenantID,
				Relation:  "members",
				Subject:   "User:" + u.ID,
				Action:    domain.KetoOutboxActionCreate,
			})
		}

		// Roles
		role := domain.NormalizeRole(u.Role)
		if role == domain.RoleSuperAdmin {
			_ = outbox.Create(ctx, &domain.KetoOutbox{
				Namespace: "System",
				Object:    "global",
				Relation:  "super_admins",
				Subject:   "User:" + u.ID,
				Action:    domain.KetoOutboxActionCreate,
			})
		}
	}

	slog.Info("✅ Keto ReBAC synchronization items added to Outbox.")
	return nil
}
