package flattens

import (
	"context"
	"fmt"

	"github.com/google/uuid"
	"github.com/hashicorp/terraform-plugin-framework/diag"
	"github.com/hashicorp/terraform-plugin-framework/types"
	"github.com/hashicorp/terraform-plugin-log/tflog"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/flattens"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/extnet/models"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/extnet/utilities"
)

// ExtNetDataSource flattens data source for extnet.
// Return error in case data source is not found on the platform.
// Flatten errors are added to tflog.
func ExtNetDataSource(ctx context.Context, state *models.DataSourceExtNetModel, c *client.Client) diag.Diagnostics {
	tflog.Info(ctx, "Start flattens.ExtNetDataSource")

	diags := diag.Diagnostics{}

	netId := uint64(state.NetID.ValueInt64())

	recordExtNet, err := utilities.ExtNetCheckPresence(ctx, netId, c)
	if err != nil {
		diags.AddError(fmt.Sprintf("Cannot get info about extnet with ID %v", netId), err.Error())
		return diags
	}

	tflog.Info(ctx, "flattens.ExtNetDataSource: before flatten", map[string]any{"net_id": netId, "recordExtNet": recordExtNet})

	id := uuid.New()
	*state = models.DataSourceExtNetModel{
		NetID:    state.NetID,
		Timeouts: state.Timeouts,

		Id:      types.StringValue(id.String()),
		CKey:    types.StringValue(recordExtNet.CKey),
		Meta:    flattens.Meta(ctx, recordExtNet.Meta),
		Default: types.BoolValue(recordExtNet.Default),
		DefaultQOS: &models.QOSModel{
			EBurst:  types.Int64Value(int64(recordExtNet.DefaultQOS.EBurst)),
			ERate:   types.Int64Value(int64(recordExtNet.DefaultQOS.ERate)),
			GUID:    types.StringValue(recordExtNet.DefaultQOS.GUID),
			InBurst: types.Int64Value(int64(recordExtNet.DefaultQOS.InBurst)),
			InRate:  types.Int64Value(int64(recordExtNet.DefaultQOS.InRate)),
		},
		Description:        types.StringValue(recordExtNet.Description),
		FreeIPs:            types.Int64Value(int64(recordExtNet.FreeIPs)),
		Gateway:            types.StringValue(recordExtNet.Gateway),
		GID:                types.Int64Value(int64(recordExtNet.GID)),
		GUID:               types.Int64Value(int64(recordExtNet.GUID)),
		IPCIDR:             types.StringValue(recordExtNet.IPCIDR),
		Milestones:         types.Int64Value(int64(recordExtNet.Milestones)),
		NetName:            types.StringValue(recordExtNet.Name),
		Network:            types.StringValue(recordExtNet.Network),
		NetworkID:          types.Int64Value(int64(recordExtNet.NetworkID)),
		NTP:                flattens.FlattenSimpleTypeToList(ctx, types.StringType, recordExtNet.NTP),
		PreReservationsNum: types.Int64Value(int64(recordExtNet.PreReservationsNum)),
		Prefix:             types.Int64Value(int64(recordExtNet.Prefix)),
		PriVNFDevID:        types.Int64Value(int64(recordExtNet.PriVNFDevID)),
		Status:             types.StringValue(recordExtNet.Status),
		VLANID:             types.Int64Value(int64(recordExtNet.VLANID)),
		VNFs: &models.VNFsModel{
			DHCP: types.Int64Value(int64(recordExtNet.VNFs.DHCP)),
		},
	}

	reservations := make([]models.ItemReservationModel, 0, len(recordExtNet.Reservations))
	for _, item := range recordExtNet.Reservations {
		r := models.ItemReservationModel{
			AccountID:   types.Int64Value(int64(item.AccountID)),
			ClientType:  types.StringValue(item.ClientType),
			Description: types.StringValue(item.Description),
			DomainName:  types.StringValue(item.DomainName),
			Hostname:    types.StringValue(item.Hostname),
			IP:          types.StringValue(item.IP),
			MAC:         types.StringValue(item.MAC),
			Type:        types.StringValue(item.Type),
			VMID:        types.Int64Value(int64(item.VMID)),
		}
		reservations = append(reservations, r)
	}
	state.Reservations = reservations

	excluded := make([]models.ExcludedModel, 0, len(recordExtNet.Excluded))
	for _, item := range recordExtNet.Excluded {
		e := models.ExcludedModel{
			ClientType: types.StringValue(item.ClientType),
			DomainName: types.StringValue(item.DomainName),
			HostName:   types.StringValue(item.HostName),
			IP:         types.StringValue(item.IP),
			MAC:        types.StringValue(item.MAC),
			Type:       types.StringValue(item.Type),
			VMID:       types.Int64Value(int64(item.VMID)),
		}
		excluded = append(excluded, e)
	}
	state.Excluded = excluded

	var diagsItem diag.Diagnostics
	state.CheckIPs, diagsItem = types.ListValueFrom(ctx, types.StringType, recordExtNet.CheckIPs)
	if diagsItem.HasError() {
		tflog.Error(ctx, fmt.Sprint("flattens.ExtNetDataSource: cannot flatten recordExtNet.CheckIPs to state.CheckIPs", diags))
	}
	state.DNS, diagsItem = types.ListValueFrom(ctx, types.StringType, recordExtNet.DNS)
	if diagsItem.HasError() {
		tflog.Error(ctx, fmt.Sprint("flattens.ExtNetDataSource: cannot flatten recordExtNet.DNS to state.DNS", diags))
	}
	state.SharedWith, diagsItem = types.ListValueFrom(ctx, types.Int64Type, recordExtNet.SharedWith)
	if diagsItem.HasError() {
		tflog.Error(ctx, fmt.Sprint("flattens.ExtNetDataSource: cannot flatten recordExtNet.SharedWith to state.SharedWith", diags))
	}

	tflog.Info(ctx, "flattens.ExtNetDataSource: after flatten", map[string]any{"net_id": state.Id.ValueString()})

	tflog.Info(ctx, "End flattens.ExtNetDataSource", map[string]any{"net_id": state.Id.ValueString()})
	return nil
}
