package user

import (
	"context"

	"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	log "github.com/sirupsen/logrus"
	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/user"
	"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
	"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)

func resourceUserCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {

	log.Debugf("resourceUserCreate: called with username %s, emailaddress %v", d.Get("username").(string), d.Get("emailaddress").([]interface{}))

	c := m.(*controller.ControllerCfg)

	username := d.Get("username").(string)

	email := d.Get("emailaddress").(string)

	createReq := user.CreateRequest{
		Username:     username,
		EmailAddress: email,
	}

	if passwd, ok := d.GetOk("password"); ok {

		createReq.Password = passwd.(string)
	}

	if provider, ok := d.GetOk("provider_name"); ok {
		createReq.Provider = provider.(string)
	}

	if aa, ok := d.GetOk("apiaccess"); ok {

		apiaccess := aa.(*schema.Set)

		for _, v := range apiaccess.List() {

			createReq.APIAccess = append(createReq.APIAccess, uint64(v.(int)))
		}
	}

	_, err := c.CloudBroker().User().Create(ctx, createReq)
	if err != nil {
		return diag.FromErr(err)
	}

	d.SetId(username)

	return resourceUserRead(ctx, d, m)
}

func resourceUserRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {

	log.Debugf("resourceUserRead: called with username %s", d.Get("username").(string))

	user, err := utilityUserCheckPresence(ctx, d, m)
	if err != nil {

		d.SetId("")

		return diag.FromErr(err)
	}
	flattenUserResource(d, user)

	return nil
}

func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {

	log.Debugf("resourceUserUpdate: called with username %s", d.Get("username").(string))

	if d.HasChange("apiaccess") {

		err := utilityUserAPIAccessGroupsConfigure(ctx, d, m)
		if err != nil {
			return diag.FromErr(err)
		}
	}

	c := m.(*controller.ControllerCfg)

	if d.HasChange("blocked") {
		blocked := d.Get("blocked").(bool)
		if blocked {
			req := user.BlockRequest{
				UserID: d.Id(),
			}

			if _, err := c.CloudBroker().User().Block(ctx, req); err != nil {
				return diag.FromErr(err)
			}
		} else {
			req := user.UnblockRequest{
				UserID: d.Id(),
			}

			if _, err := c.CloudBroker().User().Unblock(ctx, req); err != nil {
				return diag.FromErr(err)
			}
		}
	}

	return resourceUserRead(ctx, d, m)
}

func resourceUserDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {

	log.Debugf("resourceUserDelete: called with username %s", d.Get("username").(string))

	usr, err := utilityUserCheckPresence(ctx, d, m)
	if err != nil {

		d.SetId("")
		return diag.FromErr(err)
	}

	c := m.(*controller.ControllerCfg)

	req := user.DeleteRequest{
		Username: usr.ID,
	}

	_, err = c.CloudBroker().User().Delete(ctx, req)
	if err != nil {
		return diag.FromErr(err)
	}

	d.SetId("")
	return nil
}

func ResourceUser() *schema.Resource {
	return &schema.Resource{
		SchemaVersion: 2,

		CreateContext: resourceUserCreate,
		ReadContext:   resourceUserRead,
		UpdateContext: resourceUserUpdate,
		DeleteContext: resourceUserDelete,

		Importer: &schema.ResourceImporter{
			StateContext: schema.ImportStatePassthroughContext,
		},

		Timeouts: &schema.ResourceTimeout{
			Create:  &constants.Timeout600s,
			Read:    &constants.Timeout600s,
			Update:  &constants.Timeout600s,
			Delete:  &constants.Timeout600s,
			Default: &constants.Timeout600s,
		},

		StateUpgraders: []schema.StateUpgrader{
			{
				Version: 1,
				Type:    resourceUserV1().CoreConfigSchema().ImpliedType(),
				Upgrade: resourceUserUpgradeV1,
			},
		},

		Schema: resourceUserSchemaMake(),
	}
}
