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

package billinggroup

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_billing_group"

type tfModel struct {
	ID                   types.String `tfsdk:"id"`
	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"`
}

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

type apiModel 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"`
}

// composeID the ID attribute fields, i.e.:
// terraform import aiven_organization_billing_group.foo ORGANIZATION_ID/BILLING_GROUP_ID
func composeID() []string {
	return []string{"organization_id", "billing_group_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.BillingContactEmails.IsNull() || state != nil && !state.BillingContactEmails.IsNull() {
		vBillingContactEmails := make([]string, 0)
		diags := plan.BillingContactEmails.ElementsAs(ctx, &vBillingContactEmails, false)
		if diags.HasError() {
			return diags
		}
		api.BillingContactEmails = &vBillingContactEmails
	}
	if !plan.BillingEmails.IsNull() || state != nil && !state.BillingEmails.IsNull() {
		vBillingEmails := make([]string, 0)
		diags := plan.BillingEmails.ElementsAs(ctx, &vBillingEmails, false)
		if diags.HasError() {
			return diags
		}
		api.BillingEmails = &vBillingEmails
	}
	if !plan.BillingAddressID.IsNull() || state != nil && !state.BillingAddressID.IsNull() {
		vBillingAddressID := plan.BillingAddressID.ValueString()
		api.BillingAddressID = &vBillingAddressID
	}
	if !plan.BillingGroupName.IsNull() || state != nil && !state.BillingGroupName.IsNull() {
		vBillingGroupName := plan.BillingGroupName.ValueString()
		api.BillingGroupName = &vBillingGroupName
	}
	if !plan.Currency.IsNull() || state != nil && !state.Currency.IsNull() {
		vCurrency := plan.Currency.ValueString()
		api.Currency = &vCurrency
	}
	if !plan.CustomInvoiceText.IsNull() || state != nil && !state.CustomInvoiceText.IsNull() {
		vCustomInvoiceText := plan.CustomInvoiceText.ValueString()
		api.CustomInvoiceText = &vCustomInvoiceText
	}
	if !plan.OrganizationID.IsNull() || state != nil && !state.OrganizationID.IsNull() {
		vOrganizationID := plan.OrganizationID.ValueString()
		api.OrganizationID = &vOrganizationID
	}
	if !plan.PaymentMethodID.IsNull() || state != nil && !state.PaymentMethodID.IsNull() {
		vPaymentMethodID := plan.PaymentMethodID.ValueString()
		api.PaymentMethodID = &vPaymentMethodID
	}
	if !plan.ShippingAddressID.IsNull() || state != nil && !state.ShippingAddressID.IsNull() {
		vShippingAddressID := plan.ShippingAddressID.ValueString()
		api.ShippingAddressID = &vShippingAddressID
	}
	if !plan.VatID.IsNull() || state != nil && !state.VatID.IsNull() {
		vVatID := plan.VatID.ValueString()
		api.VatID = &vVatID
	}
	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.BillingContactEmails != nil && (len(*api.BillingContactEmails) > 0 || !state.BillingContactEmails.IsNull()) {
		vBillingContactEmails, diags := types.SetValueFrom(ctx, types.StringType, api.BillingContactEmails)
		if diags.HasError() {
			return diags
		}
		state.BillingContactEmails = vBillingContactEmails
	}
	if api.BillingEmails != nil && (len(*api.BillingEmails) > 0 || !state.BillingEmails.IsNull()) {
		vBillingEmails, diags := types.SetValueFrom(ctx, types.StringType, api.BillingEmails)
		if diags.HasError() {
			return diags
		}
		state.BillingEmails = vBillingEmails
	}
	if api.BillingAddressID != nil && (*api.BillingAddressID != "" || !state.BillingAddressID.IsNull()) {
		state.BillingAddressID = types.StringPointerValue(api.BillingAddressID)
	}
	if api.BillingGroupID != nil && (*api.BillingGroupID != "" || !state.BillingGroupID.IsNull()) {
		state.BillingGroupID = types.StringPointerValue(api.BillingGroupID)
	}
	if api.BillingGroupName != nil && (*api.BillingGroupName != "" || !state.BillingGroupName.IsNull()) {
		state.BillingGroupName = types.StringPointerValue(api.BillingGroupName)
	}
	if api.Currency != nil && (*api.Currency != "" || !state.Currency.IsNull()) {
		state.Currency = types.StringPointerValue(api.Currency)
	}
	if api.CustomInvoiceText != nil && (*api.CustomInvoiceText != "" || !state.CustomInvoiceText.IsNull()) {
		state.CustomInvoiceText = types.StringPointerValue(api.CustomInvoiceText)
	}
	if api.OrganizationID != nil && (*api.OrganizationID != "" || !state.OrganizationID.IsNull()) {
		state.OrganizationID = types.StringPointerValue(api.OrganizationID)
	}
	if api.PaymentMethodID != nil && (*api.PaymentMethodID != "" || !state.PaymentMethodID.IsNull()) {
		state.PaymentMethodID = types.StringPointerValue(api.PaymentMethodID)
	}
	if api.ShippingAddressID != nil && (*api.ShippingAddressID != "" || !state.ShippingAddressID.IsNull()) {
		state.ShippingAddressID = types.StringPointerValue(api.ShippingAddressID)
	}
	if api.VatID != nil && (*api.VatID != "" || !state.VatID.IsNull()) {
		state.VatID = types.StringPointerValue(api.VatID)
	}
	// 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.BillingGroupID.ValueString() == "" {
			state.BillingGroupID = types.StringValue(parts[1])
		}
	}
	state.SetID(state.OrganizationID.ValueString(), state.BillingGroupID.ValueString())
	return nil
}
