package users

import (
	"context"
	"errors"
	"fmt"

	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/pgxpool"

	"github.com/ultisuite/ulti-backend/internal/auth"
	"github.com/ultisuite/ulti-backend/internal/permission"
)

var ErrLastPlatformAdmin = errors.New("cannot remove the last platform admin")

// AccountState is the persisted user lifecycle used for auth and admin APIs.
type AccountState struct {
	Status        string
	PlatformAdmin bool
}

// GetAccountState loads status and platform_admin for an external_id.
func GetAccountState(ctx context.Context, db *pgxpool.Pool, externalID string) (AccountState, error) {
	if db == nil || externalID == "" {
		return AccountState{Status: "active"}, nil
	}
	var state AccountState
	err := db.QueryRow(ctx, `
		SELECT status, platform_admin FROM users WHERE external_id = $1
	`, externalID).Scan(&state.Status, &state.PlatformAdmin)
	if errors.Is(err, pgx.ErrNoRows) {
		return AccountState{Status: "active"}, nil
	}
	if err != nil {
		return AccountState{}, err
	}
	return state, nil
}

// ApplyAccountGroups adjusts OIDC groups from the persisted account role.
func ApplyAccountGroups(ctx context.Context, db *pgxpool.Pool, claims *auth.Claims) error {
	if claims == nil || db == nil {
		return nil
	}
	state, err := GetAccountState(ctx, db, claims.Sub)
	if err != nil {
		return err
	}
	switch permission.DeriveAccountRole(state.PlatformAdmin, state.Status) {
	case permission.AccountRoleGuest:
		claims.Groups = permission.WithGuestAccess(claims.Groups)
	case permission.AccountRoleSuspended:
		// Auth middleware rejects disabled accounts before handlers run.
	default:
		claims.Groups = permission.WithSuiteDefaults(claims.Groups)
	}
	if state.PlatformAdmin {
		claims.Groups = permission.WithPlatformAdmin(claims.Groups)
	}
	return nil
}

// CountPlatformAdmins returns active platform admins.
func CountPlatformAdmins(ctx context.Context, db *pgxpool.Pool) (int64, error) {
	if db == nil {
		return 0, fmt.Errorf("database not configured")
	}
	var count int64
	err := db.QueryRow(ctx, `
		SELECT COUNT(*) FROM users
		WHERE platform_admin = true AND status = 'active'
	`).Scan(&count)
	return count, err
}

// RevokePlatformAdmin clears platform_admin for external_id.
func RevokePlatformAdmin(ctx context.Context, db *pgxpool.Pool, externalID string) error {
	if db == nil {
		return fmt.Errorf("database not configured")
	}
	if externalID == "" {
		return fmt.Errorf("missing external id")
	}
	tag, err := db.Exec(ctx, `
		UPDATE users SET platform_admin = false, updated_at = NOW()
		WHERE external_id = $1
	`, externalID)
	if err != nil {
		return err
	}
	if tag.RowsAffected() == 0 {
		return pgx.ErrNoRows
	}
	return nil
}
