// Copyright (c) 2025 Aiven, Helsinki, Finland. https://aiven.io/
// Code generated by user config generator. DO NOT EDIT.

package applicationuser

import (
	"context"
	"fmt"
	"path/filepath"
	"strings"

	"github.com/hashicorp/terraform-plugin-framework/diag"
	"github.com/hashicorp/terraform-plugin-framework/types"

	"github.com/aiven/terraform-provider-aiven/internal/plugin/util"
)

const aivenName = "aiven_organization_application_user"

type tfModel struct {
	ID             types.String `tfsdk:"id"`
	Email          types.String `tfsdk:"email"`
	IsSuperAdmin   types.Bool   `tfsdk:"is_super_admin"`
	Name           types.String `tfsdk:"name"`
	OrganizationID types.String `tfsdk:"organization_id"`
	UserID         types.String `tfsdk:"user_id"`
}

func (tf *tfModel) SetID(vOrganizationID string, vUserID string) {
	tf.OrganizationID = types.StringValue(vOrganizationID)
	tf.UserID = types.StringValue(vUserID)
	tf.ID = types.StringValue(filepath.Join(vOrganizationID, vUserID))
}

type apiModel struct {
	Email          *string `json:"user_email,omitempty"`
	IsSuperAdmin   *bool   `json:"is_super_admin,omitempty"`
	Name           *string `json:"name,omitempty"`
	OrganizationID *string `json:"organization_id,omitempty"`
	UserID         *string `json:"user_id,omitempty"`
}

// composeID the ID attribute fields, i.e.:
// terraform import aiven_organization_application_user.foo ORGANIZATION_ID/USER_ID
func composeID() []string {
	return []string{"organization_id", "user_id"}
}

// expandData turns TF object into Request
func expandData[R any](ctx context.Context, plan, state *tfModel, req *R, modifiers ...util.MapModifier[apiModel]) diag.Diagnostics {
	api := new(apiModel)
	if !plan.IsSuperAdmin.IsNull() && !plan.IsSuperAdmin.IsUnknown() {
		vIsSuperAdmin := plan.IsSuperAdmin.ValueBool()
		api.IsSuperAdmin = &vIsSuperAdmin
	}
	if !plan.Name.IsNull() || state != nil && !state.Name.IsNull() {
		vName := plan.Name.ValueString()
		api.Name = &vName
	}
	if !plan.OrganizationID.IsNull() || state != nil && !state.OrganizationID.IsNull() {
		vOrganizationID := plan.OrganizationID.ValueString()
		api.OrganizationID = &vOrganizationID
	}
	err := util.Unmarshal(api, req, modifiers...)
	if err != nil {
		var diags diag.Diagnostics
		diags.AddError("Unmarshal error", fmt.Sprintf("Failed to unmarshal dtoModel to Request: %s", err.Error()))
		return diags
	}
	return nil
}

// flattenData turns Response into TF object
func flattenData[R any](ctx context.Context, state *tfModel, rsp *R, modifiers ...util.MapModifier[R]) diag.Diagnostics {
	api := new(apiModel)
	err := util.Unmarshal(rsp, api, modifiers...)
	if err != nil {
		var diags diag.Diagnostics
		diags.AddError("Unmarshal error", fmt.Sprintf("Failed to unmarshal Response to dtoModel: %s", err.Error()))
		return diags
	}
	if api.Email != nil && (*api.Email != "" || !state.Email.IsNull()) {
		state.Email = types.StringPointerValue(api.Email)
	}
	if api.IsSuperAdmin != nil {
		state.IsSuperAdmin = types.BoolPointerValue(api.IsSuperAdmin)
	}
	if api.Name != nil && (*api.Name != "" || !state.Name.IsNull()) {
		state.Name = types.StringPointerValue(api.Name)
	}
	if api.OrganizationID != nil && (*api.OrganizationID != "" || !state.OrganizationID.IsNull()) {
		state.OrganizationID = types.StringPointerValue(api.OrganizationID)
	}
	if api.UserID != nil && (*api.UserID != "" || !state.UserID.IsNull()) {
		state.UserID = types.StringPointerValue(api.UserID)
	}
	// Response may not contain ID fields.
	// In that case, `terraform import` won't be able to set them. Gets values from the ID.
	if state.ID.ValueString() != "" {
		var parts [2]string
		for i, v := range strings.SplitN(state.ID.ValueString(), "/", 2) {
			parts[i] = v
		}
		if state.OrganizationID.ValueString() == "" {
			state.OrganizationID = types.StringValue(parts[0])
		}
		if state.UserID.ValueString() == "" {
			state.UserID = types.StringValue(parts[1])
		}
	}
	state.SetID(state.OrganizationID.ValueString(), state.UserID.ValueString())
	return nil
}
