package persistence

import (
	"context"
	"database/sql"
	"errors"
	"time"

	apperrors "github.com/nexuscrm/kernel/pkg/errors"
	"github.com/nexuscrm/kernel/pkg/ports"
	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/permissionstatev1"
)

var _ ports.EffectivePermissionSnapshotRepository = (*PermissionRepository)(nil)

// LoadCurrentEffectivePermissionSnapshot observes the current subject,
// Permission State version, and both bounded effective-permission families in
// one database statement. Grant paths are set-valued: the statement collapses
// the same permission reached through profile, direct, or group grants into one
// effective identifier. A stale subject or malformed final aggregate returns
// no partial permission result.
func (r *PermissionRepository) LoadCurrentEffectivePermissionSnapshot(
	ctx context.Context,
	subject permissionstatev1.Subject,
) (permissionstatev1.EffectiveSnapshot, error) {
	if r == nil || r.db == nil {
		return permissionstatev1.EffectiveSnapshot{}, errors.New("effective permission snapshot: repository is unavailable")
	}
	if ctx == nil {
		return permissionstatev1.EffectiveSnapshot{}, errors.New("effective permission snapshot: context is required")
	}
	if err := subject.Validate(); err != nil {
		return permissionstatev1.EffectiveSnapshot{}, errors.New("effective permission snapshot: subject is invalid")
	}

	rows, err := r.getExecutor(ctx).QueryContext(
		ctx,
		loadCurrentEffectivePermissionSnapshotSQL,
		subject.UserID(),
		subject.ProfileID(),
		subject.ProfileID(),
		subject.UserID(),
		subject.UserID(),
		subject.ProfileID(),
		subject.UserID(),
		subject.UserID(),
	)
	if err != nil {
		return permissionstatev1.EffectiveSnapshot{}, apperrors.NewInternalError(
			"failed to load effective permission snapshot",
			err,
		)
	}
	defer rows.Close()

	var (
		version           permissionstatev1.Version
		enforcementMode   PermissionStateEnforcementMode
		systemPermissions []string
		customPermissions []string
		sawAuthority      bool
		sawEmptyAggregate bool
	)
	for rows.Next() {
		state, family, permission, err := scanEffectivePermissionSnapshotRow(rows)
		if err != nil {
			return permissionstatev1.EffectiveSnapshot{}, err
		}
		if !sawAuthority {
			version = state.Version
			enforcementMode = state.EnforcementMode
			sawAuthority = true
		} else {
			comparison, compareErr := version.Compare(state.Version)
			if compareErr != nil || comparison != 0 || enforcementMode != state.EnforcementMode {
				return permissionstatev1.EffectiveSnapshot{}, errors.New(
					"effective permission snapshot: authority changed within aggregate",
				)
			}
		}
		if sawEmptyAggregate {
			return permissionstatev1.EffectiveSnapshot{}, errors.New(
				"effective permission snapshot: aggregate contains rows after empty result",
			)
		}
		switch family {
		case "":
			if permission != "" || len(systemPermissions) != 0 || len(customPermissions) != 0 {
				return permissionstatev1.EffectiveSnapshot{}, errors.New(
					"effective permission snapshot: permission family is missing",
				)
			}
			sawEmptyAggregate = true
		case "system":
			if len(systemPermissions) == permissionstatev1.MaxPermissionsPerFamily {
				return permissionstatev1.EffectiveSnapshot{}, errors.New(
					"effective permission snapshot: system permission capacity exceeded",
				)
			}
			systemPermissions = append(systemPermissions, permission)
		case "custom":
			if len(customPermissions) == permissionstatev1.MaxPermissionsPerFamily {
				return permissionstatev1.EffectiveSnapshot{}, errors.New(
					"effective permission snapshot: custom permission capacity exceeded",
				)
			}
			customPermissions = append(customPermissions, permission)
		default:
			return permissionstatev1.EffectiveSnapshot{}, errors.New(
				"effective permission snapshot: permission family is invalid",
			)
		}
	}
	if err := rows.Err(); err != nil {
		return permissionstatev1.EffectiveSnapshot{}, apperrors.NewInternalError(
			"failed to iterate effective permission snapshot",
			err,
		)
	}
	if !sawAuthority {
		return permissionstatev1.EffectiveSnapshot{}, errors.New(
			"effective permission snapshot: current authority is unavailable",
		)
	}
	snapshot, err := permissionstatev1.NewEffectiveSnapshot(
		version,
		systemPermissions,
		customPermissions,
	)
	if err != nil {
		return permissionstatev1.EffectiveSnapshot{}, errors.New(
			"effective permission snapshot: aggregate is invalid",
		)
	}
	return snapshot, nil
}

func (r *PermissionRepository) loadCurrentEffectivePermissionMaps(
	ctx context.Context,
	userID string,
	profileID string,
) (map[string]bool, map[string]bool, error) {
	subject, err := permissionstatev1.NewSubject(userID, profileID)
	if err != nil {
		return nil, nil, err
	}
	snapshot, err := r.LoadCurrentEffectivePermissionSnapshot(ctx, subject)
	if err != nil {
		return nil, nil, err
	}
	systemPermissions := make(map[string]bool, len(snapshot.SystemPermissions()))
	for _, permission := range snapshot.SystemPermissions() {
		systemPermissions[permission] = true
	}
	customPermissions := make(map[string]bool, len(snapshot.CustomPermissions()))
	for _, permission := range snapshot.CustomPermissions() {
		customPermissions[permission] = true
	}
	return systemPermissions, customPermissions, nil
}

func scanEffectivePermissionSnapshotRow(
	row interface{ Scan(...any) error },
) (PermissionState, string, string, error) {
	var (
		singletonKey int64
		lineageBytes []byte
		revision     string
		mode         string
		created      time.Time
		modified     time.Time
		family       sql.NullString
		permission   sql.NullString
	)
	if err := row.Scan(
		&singletonKey,
		&lineageBytes,
		&revision,
		&mode,
		&created,
		&modified,
		&family,
		&permission,
	); err != nil {
		return PermissionState{}, "", "", apperrors.NewInternalError(
			"failed to scan effective permission snapshot",
			err,
		)
	}
	if singletonKey != 1 ||
		(!family.Valid && permission.Valid) ||
		(family.Valid && (!permission.Valid || family.String == "" || permission.String == "")) {
		return PermissionState{}, "", "", errors.New(
			"effective permission snapshot: aggregate row is invalid",
		)
	}
	state, err := permissionStateFromDurableValues(
		singletonKey,
		lineageBytes,
		revision,
		mode,
		created,
		modified,
	)
	if err != nil {
		return PermissionState{}, "", "", errors.New(
			"effective permission snapshot: authority is invalid",
		)
	}
	return state, family.String, permission.String, nil
}

const loadCurrentEffectivePermissionSnapshotSQL = `
WITH current_authority AS (
	SELECT
		state.SingletonKey,
		state.Lineage,
		CAST(state.Revision AS CHAR) AS Revision,
		state.EnforcementMode,
		state.CreatedDate,
		state.LastModifiedDate
	FROM _System_PermissionStateVersion state
	INNER JOIN ` + "`User`" + ` subject_user
		ON subject_user.Id = ?
		AND subject_user.ProfileId = ?
		AND subject_user.IsActive = 1
		AND subject_user.IsDeleted = 0
	WHERE state.SingletonKey = 1
		AND (
			SELECT COUNT(*)
			FROM _System_PermissionStateVersion
		) = 1
),
effective_permissions AS (
	-- Effective permissions are a set. DISTINCT UNION intentionally collapses
	-- the same identifier reached through multiple valid grant paths.
	SELECT 'system' AS Family, grants.PermissionApiName AS Permission
	FROM _System_PermissionSetPermission grants
	INNER JOIN _System_Permission permission_definition
		ON permission_definition.ApiName = grants.PermissionApiName
		AND permission_definition.IsActive = 1
	INNER JOIN PermissionSet permission_set
		ON permission_set.Id = grants.PermissionSetId
		AND permission_set.IsDeleted = 0
	WHERE grants.IsEnabled = 1
		AND (
			(permission_set.ProfileId = ? AND permission_set.IsOwnedByProfile = 1)
			OR EXISTS (
				SELECT 1
				FROM PermissionSetAssignment direct_assignment
				WHERE direct_assignment.PermissionSetId = permission_set.Id
					AND direct_assignment.AssigneeId = ?
					AND direct_assignment.IsDeleted = 0
			)
		)
	UNION
	SELECT 'system' AS Family, grants.PermissionApiName AS Permission
	FROM _System_PermissionSetPermission grants
	INNER JOIN _System_Permission permission_definition
		ON permission_definition.ApiName = grants.PermissionApiName
		AND permission_definition.IsActive = 1
	INNER JOIN PermissionSetGroupComponent component
		ON component.PermissionSetId = grants.PermissionSetId
	INNER JOIN PermissionSet permission_set
		ON permission_set.Id = component.PermissionSetId
		AND permission_set.IsDeleted = 0
	INNER JOIN PermissionSetGroup permission_group
		ON permission_group.Id = component.GroupId
		AND permission_group.IsActive = 1
		AND permission_group.IsDeleted = 0
	INNER JOIN PermissionSetGroupAssignment group_assignment
		ON group_assignment.GroupId = permission_group.Id
		AND group_assignment.AssigneeId = ?
		AND group_assignment.IsDeleted = 0
	WHERE grants.IsEnabled = 1
		AND NOT EXISTS (
			SELECT 1
			FROM _System_MutingPermissionSetPermission muted
			INNER JOIN MutingPermissionSet muting_set
				ON muting_set.Id = muted.MutingPermissionSetId
			WHERE muting_set.GroupId = permission_group.Id
				AND muted.PermissionApiName = grants.PermissionApiName
		)
	UNION
	SELECT 'custom' AS Family, custom_permission.ApiName AS Permission
	FROM _System_CustomPermission custom_permission
	WHERE custom_permission.IsActive = 1
		AND custom_permission.IsDeleted = 0
		AND (
			EXISTS (
				SELECT 1
				FROM ProfileCustomPermission profile_grant
				INNER JOIN Profile profile ON profile.Id = profile_grant.ProfileId AND profile.IsDeleted = 0
				WHERE profile_grant.CustomPermissionId = custom_permission.Id
					AND profile_grant.ProfileId = ?
			)
			OR EXISTS (
				SELECT 1
				FROM PermissionSetCustomPermission permission_set_grant
				INNER JOIN PermissionSet permission_set
					ON permission_set.Id = permission_set_grant.PermissionSetId
					AND permission_set.IsDeleted = 0
				WHERE permission_set_grant.CustomPermissionId = custom_permission.Id
					AND (
						EXISTS (
							SELECT 1
							FROM PermissionSetAssignment direct_assignment
							WHERE direct_assignment.PermissionSetId = permission_set.Id
								AND direct_assignment.AssigneeId = ?
								AND direct_assignment.IsDeleted = 0
						)
						OR EXISTS (
							SELECT 1
							FROM PermissionSetGroupComponent component
							INNER JOIN PermissionSetGroup permission_group
								ON permission_group.Id = component.GroupId
								AND permission_group.IsActive = 1
								AND permission_group.IsDeleted = 0
							INNER JOIN PermissionSetGroupAssignment group_assignment
								ON group_assignment.GroupId = permission_group.Id
								AND group_assignment.AssigneeId = ?
								AND group_assignment.IsDeleted = 0
							WHERE component.PermissionSetId = permission_set.Id
						)
					)
			)
		)
)
SELECT
	current_authority.SingletonKey,
	current_authority.Lineage,
	current_authority.Revision,
	current_authority.EnforcementMode,
	current_authority.CreatedDate,
	current_authority.LastModifiedDate,
	effective_permissions.Family,
	effective_permissions.Permission
FROM current_authority
LEFT JOIN effective_permissions ON 1 = 1
ORDER BY effective_permissions.Family, effective_permissions.Permission`
