package godo

import (
	"encoding/json"
	"fmt"
	"net/http"
	"reflect"
	"testing"
)

func TestStoragesActions_Attach(t *testing.T) {
	setup()
	defer teardown()
	const (
		volumeID  = "98d414c6-295e-4e3a-ac58-eb9456c1e1d1"
		dropletID = 12345
	)

	attachRequest := &ActionRequest{
		"type":       "attach",
		"droplet_id": float64(dropletID), // encoding/json decodes numbers as floats
	}

	mux.HandleFunc("/v2/volumes/"+volumeID+"/actions", func(w http.ResponseWriter, r *http.Request) {
		v := new(ActionRequest)
		err := json.NewDecoder(r.Body).Decode(v)
		if err != nil {
			t.Fatalf("decode json: %v", err)
		}

		testMethod(t, r, http.MethodPost)
		if !reflect.DeepEqual(v, attachRequest) {
			t.Errorf("want=%#v", attachRequest)
			t.Errorf("got=%#v", v)
		}
		fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
	})

	_, _, err := client.StorageActions.Attach(ctx, volumeID, dropletID)
	if err != nil {
		t.Errorf("StoragesActions.Attach returned error: %v", err)
	}
}

func TestStoragesActions_DetachByDropletID(t *testing.T) {
	setup()
	defer teardown()
	volumeID := "98d414c6-295e-4e3a-ac58-eb9456c1e1d1"
	dropletID := 123456

	detachByDropletIDRequest := &ActionRequest{
		"type":       "detach",
		"droplet_id": float64(dropletID), // encoding/json decodes numbers as floats
	}

	mux.HandleFunc("/v2/volumes/"+volumeID+"/actions", func(w http.ResponseWriter, r *http.Request) {
		v := new(ActionRequest)
		err := json.NewDecoder(r.Body).Decode(v)
		if err != nil {
			t.Fatalf("decode json: %v", err)
		}

		testMethod(t, r, http.MethodPost)
		if !reflect.DeepEqual(v, detachByDropletIDRequest) {
			t.Errorf("want=%#v", detachByDropletIDRequest)
			t.Errorf("got=%#v", v)
		}
		fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
	})

	_, _, err := client.StorageActions.DetachByDropletID(ctx, volumeID, dropletID)
	if err != nil {
		t.Errorf("StoragesActions.DetachByDropletID returned error: %v", err)
	}
}

func TestStorageActions_Get(t *testing.T) {
	setup()
	defer teardown()
	volumeID := "98d414c6-295e-4e3a-ac58-eb9456c1e1d1"

	mux.HandleFunc("/v2/volumes/"+volumeID+"/actions/456", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
	})

	action, _, err := client.StorageActions.Get(ctx, volumeID, 456)
	if err != nil {
		t.Errorf("StorageActions.Get returned error: %v", err)
	}

	expected := &Action{Status: "in-progress"}
	if !reflect.DeepEqual(action, expected) {
		t.Errorf("StorageActions.Get returned %+v, expected %+v", action, expected)
	}
}

func TestStorageActions_List(t *testing.T) {
	setup()
	defer teardown()
	volumeID := "98d414c6-295e-4e3a-ac58-eb9456c1e1d1"

	mux.HandleFunc("/v2/volumes/"+volumeID+"/actions", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		fmt.Fprintf(w, `{
			"actions": [
				{
					"status": "in-progress"
				}
			],
			"meta": {
				"total": 1
			}
		}`)
	})

	actions, resp, err := client.StorageActions.List(ctx, volumeID, nil)
	if err != nil {
		t.Errorf("StorageActions.List returned error: %v", err)
	}

	expectedActions := []Action{{Status: "in-progress"}}
	if !reflect.DeepEqual(actions, expectedActions) {
		t.Errorf("StorageActions.List returned actions %+v, expected %+v", actions, expectedActions)
	}

	expectedMeta := &Meta{Total: 1}
	if !reflect.DeepEqual(resp.Meta, expectedMeta) {
		t.Errorf("StorageActions.List returned meta %+v, expected %+v", resp.Meta, expectedMeta)
	}
}

func TestStoragesActions_Resize(t *testing.T) {
	setup()
	defer teardown()
	volumeID := "98d414c6-295e-4e3a-ac58-eb9456c1e1d1"

	resizeRequest := &ActionRequest{
		"type":           "resize",
		"size_gigabytes": float64(500),
		"region":         "nyc1",
	}

	mux.HandleFunc("/v2/volumes/"+volumeID+"/actions", func(w http.ResponseWriter, r *http.Request) {
		v := new(ActionRequest)
		err := json.NewDecoder(r.Body).Decode(v)
		if err != nil {
			t.Fatalf("decode json: %v", err)
		}

		testMethod(t, r, http.MethodPost)
		if !reflect.DeepEqual(v, resizeRequest) {
			t.Errorf("want=%#v", resizeRequest)
			t.Errorf("got=%#v", v)
		}
		fmt.Fprintf(w, `{"action":{"status":"in-progress"}}`)
	})

	_, _, err := client.StorageActions.Resize(ctx, volumeID, 500, "nyc1")
	if err != nil {
		t.Errorf("StoragesActions.Resize returned error: %v", err)
	}
}
