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

package billinggrouplist

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

	"github.com/hashicorp/terraform-plugin-framework/attr"
	"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_billing_group_list"

type tfModel struct {
	ID             types.String `tfsdk:"id"`
	BillingGroups  types.Set    `tfsdk:"billing_groups"`
	OrganizationID types.String `tfsdk:"organization_id"`
}

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

type tfModelBillingGroups struct {
	BillingAddressID     types.String `tfsdk:"billing_address_id"`
	BillingContactEmails types.Set    `tfsdk:"billing_contact_emails"`
	BillingEmails        types.Set    `tfsdk:"billing_emails"`
	BillingGroupID       types.String `tfsdk:"billing_group_id"`
	BillingGroupName     types.String `tfsdk:"billing_group_name"`
	Currency             types.String `tfsdk:"currency"`
	CustomInvoiceText    types.String `tfsdk:"custom_invoice_text"`
	OrganizationID       types.String `tfsdk:"organization_id"`
	PaymentMethodID      types.String `tfsdk:"payment_method_id"`
	ShippingAddressID    types.String `tfsdk:"shipping_address_id"`
	VatID                types.String `tfsdk:"vat_id"`
}

type apiModel struct {
	BillingGroups  *[]*apiModelBillingGroups `json:"billing_groups,omitempty"`
	OrganizationID *string                   `json:"organization_id,omitempty"`
}

type apiModelBillingGroups struct {
	BillingAddressID     *string   `json:"billing_address_id,omitempty"`
	BillingContactEmails *[]string `json:"billing_contact_emails,omitempty"`
	BillingEmails        *[]string `json:"billing_emails,omitempty"`
	BillingGroupID       *string   `json:"billing_group_id,omitempty"`
	BillingGroupName     *string   `json:"billing_group_name,omitempty"`
	Currency             *string   `json:"currency,omitempty"`
	CustomInvoiceText    *string   `json:"custom_invoice_text,omitempty"`
	OrganizationID       *string   `json:"organization_id,omitempty"`
	PaymentMethodID      *string   `json:"payment_method_id,omitempty"`
	ShippingAddressID    *string   `json:"shipping_address_id,omitempty"`
	VatID                *string   `json:"vat_id,omitempty"`
}

// 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.BillingGroups != nil {
		vBillingGroups, diags := util.FlattenSetNested(ctx, flattenBillingGroups, *api.BillingGroups, attrsBillingGroups())
		if diags.HasError() {
			return diags
		}
		state.BillingGroups = vBillingGroups
	}
	if api.OrganizationID != nil && (*api.OrganizationID != "" || !state.OrganizationID.IsNull()) {
		state.OrganizationID = types.StringPointerValue(api.OrganizationID)
	}
	// 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 [1]string
		for i, v := range strings.SplitN(state.ID.ValueString(), "/", 1) {
			parts[i] = v
		}
		if state.OrganizationID.ValueString() == "" {
			state.OrganizationID = types.StringValue(parts[0])
		}
	}
	state.SetID(state.OrganizationID.ValueString())
	return nil
}

func flattenBillingGroups(ctx context.Context, api *apiModelBillingGroups) (*tfModelBillingGroups, diag.Diagnostics) {
	state := new(tfModelBillingGroups)
	if api.BillingContactEmails != nil {
		vBillingContactEmails, diags := types.SetValueFrom(ctx, types.StringType, api.BillingContactEmails)
		if diags.HasError() {
			return nil, diags
		}
		state.BillingContactEmails = vBillingContactEmails
	}
	if api.BillingEmails != nil {
		vBillingEmails, diags := types.SetValueFrom(ctx, types.StringType, api.BillingEmails)
		if diags.HasError() {
			return nil, diags
		}
		state.BillingEmails = vBillingEmails
	}
	if api.BillingAddressID != nil {
		state.BillingAddressID = types.StringPointerValue(api.BillingAddressID)
	}
	if api.BillingGroupID != nil {
		state.BillingGroupID = types.StringPointerValue(api.BillingGroupID)
	}
	if api.BillingGroupName != nil {
		state.BillingGroupName = types.StringPointerValue(api.BillingGroupName)
	}
	if api.Currency != nil {
		state.Currency = types.StringPointerValue(api.Currency)
	}
	if api.CustomInvoiceText != nil {
		state.CustomInvoiceText = types.StringPointerValue(api.CustomInvoiceText)
	}
	if api.OrganizationID != nil {
		state.OrganizationID = types.StringPointerValue(api.OrganizationID)
	}
	if api.PaymentMethodID != nil {
		state.PaymentMethodID = types.StringPointerValue(api.PaymentMethodID)
	}
	if api.ShippingAddressID != nil {
		state.ShippingAddressID = types.StringPointerValue(api.ShippingAddressID)
	}
	if api.VatID != nil {
		state.VatID = types.StringPointerValue(api.VatID)
	}
	return state, nil
}

func attrsBillingGroups() types.ObjectType {
	return types.ObjectType{AttrTypes: map[string]attr.Type{
		"billing_address_id":     types.StringType,
		"billing_contact_emails": types.SetType{ElemType: types.StringType},
		"billing_emails":         types.SetType{ElemType: types.StringType},
		"billing_group_id":       types.StringType,
		"billing_group_name":     types.StringType,
		"currency":               types.StringType,
		"custom_invoice_text":    types.StringType,
		"organization_id":        types.StringType,
		"payment_method_id":      types.StringType,
		"shipping_address_id":    types.StringType,
		"vat_id":                 types.StringType,
	}}
}
