package disks

import (
	"context"
	"fmt"

	"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/disks"
	"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
	"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)

func resourceDiskSnapshotCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
	log.Debugf("resourceDiskSnapshotCreate: call for disk_id %d, label %s",
		d.Get("disk_id").(int),
		d.Get("label").(string))

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

	diskId := uint64(d.Get("disk_id").(int))
	label := d.Get("label").(string)
	d.SetId(fmt.Sprintf("%d#%s", diskId, label))

	if rollback := d.Get("rollback").(bool); rollback {
		err := resourceDiskSnapshotChangeRollback(ctx, d, m)
		if err != nil {
			return diag.FromErr(err)
		}
	}
	return resourceDiskSnapshotRead(ctx, d, m)
}

func resourceDiskSnapshotRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
	log.Debugf("resourceDiskSnapshotRead: snapshot id %s", d.Id())

	snapshot, err := utilityDiskSnapshotCheckPresence(ctx, d, m)
	if err != nil {
		d.SetId("")
		return diag.FromErr(err)
	}

	flattenDiskSnapshot(d, snapshot)

	return nil
}

func resourceDiskSnapshotUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
	log.Debugf("resourceDiskSnapshotUpdate: snapshot id %s", d.Id())

	_, err := utilityDiskSnapshotCheckPresence(ctx, d, m)
	if err != nil {
		d.SetId("")
		return diag.FromErr(err)
	}

	if d.HasChange("rollback") {
		err := resourceDiskSnapshotChangeRollback(ctx, d, m)
		if err != nil {
			return diag.FromErr(err)
		}
	}

	return resourceDiskSnapshotRead(ctx, d, m)
}

func resourceDiskSnapshotDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
	log.Debugf("resourceDiskSnapshotDelete: snapshot id %s", d.Id())

	_, err := utilityDiskSnapshotCheckPresence(ctx, d, m)
	if err != nil {
		d.SetId("")
		return diag.FromErr(err)
	}

	c := m.(*controller.ControllerCfg)

	req := disks.SnapshotDeleteRequest{
		DiskID: uint64(d.Get("disk_id").(int)),
		Label:  d.Get("label").(string),
	}

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

	d.SetId("")

	return nil
}

func resourceDiskSnapshotChangeRollback(ctx context.Context, d *schema.ResourceData, m interface{}) error {
	c := m.(*controller.ControllerCfg)

	rollback := d.Get("rollback").(bool)

	if rollback {
		label := d.Get("label").(string)
		timestamp := uint64(d.Get("timestamp").(int))
		diskId := uint64(d.Get("disk_id").(int))

		req := disks.SnapshotRollbackRequest{
			DiskID:    diskId,
			Label:     label,
			TimeStamp: timestamp,
		}

		log.Debugf("resourceDiskUpdate: Snapshot rollback with label %s", label)
		if _, err := c.CloudBroker().Disks().SnapshotRollback(ctx, req); err != nil {
			return err
		}
	}

	return nil
}

func ResourceDiskSnapshot() *schema.Resource {
	return &schema.Resource{
		SchemaVersion: 1,

		CreateContext: resourceDiskSnapshotCreate,
		ReadContext:   resourceDiskSnapshotRead,
		UpdateContext: resourceDiskSnapshotUpdate,
		DeleteContext: resourceDiskSnapshotDelete,

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

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

		Schema: resourceDiskSnapshotSchemaMake(),
	}
}
