package dialectsfcrm

import (
	"context"
	"errors"
	"net/http"

	"github.com/nexuscrm/dialect-sf-crm/wire"
	"github.com/nexuscrm/shared/pkg/contract"
	"github.com/nexuscrm/shared/pkg/dialect"
	"github.com/nexuscrm/shared/pkg/fieldpermissions"
)

// EffectivePermissionsNeutralHandler is an enforcement/effective read, not an
// authoring surface. Permission authoring moved as one aggregate to the sfcrm
// AppService and runtime.permissions.authoring.v1; no segmented writer remains
// in this transitional dialect.
func EffectivePermissionsNeutralHandler(ctx context.Context, req *dialect.Request, deps dialect.Deps) (*dialect.Response, error) {
	admin, resp := permissionAdminFromDeps(deps)
	if resp != nil {
		return resp, nil
	}
	target := firstQuery(req, "userId")
	result, err := admin.EffectivePermissions(ctx, req.User, target)
	if err != nil {
		return permissionAdminErrorResponse(err), nil
	}
	objRecords := make([]map[string]any, len(result.ObjectPermissions))
	for i, p := range result.ObjectPermissions {
		objRecords[i] = objectPermissionWire(p)
	}
	fieldRecords := make([]map[string]any, len(result.FieldPermissions))
	for i, p := range result.FieldPermissions {
		fieldRecords[i] = map[string]any{
			"SobjectType":     p.ResourceType,
			"Field":           fieldpermissions.QualifiedField(p.ResourceType, p.FieldName),
			"PermissionsRead": p.CanRead,
			"PermissionsEdit": p.CanEdit,
		}
	}
	return jsonResponse(http.StatusOK, map[string]any{
		"systemPermissions": result.SystemPermissions,
		"customPermissions": result.CustomPermissions,
		"objectPermissions": objRecords,
		"fieldPermissions":  fieldRecords,
	}), nil
}

func permissionAdminFromDeps(deps dialect.Deps) (contract.PermissionAdmin, *dialect.Response) {
	if deps.Contracts.PermissionAdmin == nil {
		return nil, &dialect.Response{
			Status: http.StatusInternalServerError,
			Body:   wire.SFErrorResponse(wire.SFCodeServerError, "permission admin service is not configured"),
		}
	}
	return deps.Contracts.PermissionAdmin, nil
}

func permissionAdminErrorResponse(err error) *dialect.Response {
	var adminErr *contract.PermissionAdminError
	if errors.As(err, &adminErr) {
		switch adminErr.Kind {
		case contract.PermissionAdminErrorNotFound:
			return &dialect.Response{Status: http.StatusNotFound, Body: wire.SFErrorResponse(wire.SFCodeNotFound, adminErr.Message)}
		case contract.PermissionAdminErrorForbidden:
			return &dialect.Response{Status: http.StatusForbidden, Body: wire.SFErrorResponse(wire.SFCodeForbidden, adminErr.Message)}
		case contract.PermissionAdminErrorInvalidField:
			return &dialect.Response{Status: http.StatusBadRequest, Body: wire.SFErrorResponse(wire.SFCodeInvalidField, adminErr.Message)}
		case contract.PermissionAdminErrorSanitizedInternal:
			return &dialect.Response{Status: http.StatusInternalServerError, Body: wire.SFErrorResponse(wire.SFCodeInternalError, adminErr.Message)}
		case contract.PermissionAdminErrorServer:
			return &dialect.Response{Status: http.StatusInternalServerError, Body: wire.SFErrorResponse(wire.SFCodeServerError, adminErr.Message)}
		}
	}
	return &dialect.Response{Status: http.StatusInternalServerError, Body: wire.SFErrorResponse(wire.SFCodeServerError, err.Error())}
}

func successResponse() *dialect.Response {
	return jsonResponse(http.StatusOK, map[string]any{"success": true})
}

func jsonResponse(status int, body any) *dialect.Response {
	return &dialect.Response{Status: status, Body: body}
}

func firstQuery(req *dialect.Request, key string) string {
	if req == nil || req.Query == nil {
		return ""
	}
	values := req.Query[key]
	if len(values) == 0 {
		return ""
	}
	return values[0]
}

// objectPermissionWire maps a neutral ObjectAccessProjection back into the
// frozen SF object-permission wire record. The neutral Can* fields carry the
// same booleans the engine emitted; only the wire keys are SF-shaped and live
// here, in the dialect.
func objectPermissionWire(p contract.ObjectAccessProjection) map[string]any {
	return map[string]any{
		"SobjectType":                 p.ResourceType,
		"PermissionsRead":             p.CanRead,
		"PermissionsCreate":           p.CanCreate,
		"PermissionsEdit":             p.CanEdit,
		"PermissionsDelete":           p.CanDelete,
		"PermissionsViewAllRecords":   p.CanViewAll,
		"PermissionsModifyAllRecords": p.CanModifyAll,
	}
}
