package core

import (
	"context"
	"strings"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/schrodinger/pkg/types"
)

// CreateAPP creates app
func (mgr *Manager) CreateAPP(cfg *types.APPConfig) error {
	app := &types.APPProcess{
		Name:      cfg.Name,
		Namespace: cfg.Namespace,
		Config:    cfg,
		Report:    &types.TestReport{},
		Status:    types.TestStateCreating,
	}
	app.UpdateReport()

	if err := mgr.storage.CreateAPPProcess(app); err != nil {
		log.Errorf("store app process %+v failed, error: %v", app, err)
		return errors.Trace(err)
	}

	var finalState types.TestState

	defer func() {
		app.Status = finalState
		app.UpdateReport()
		if err := mgr.storage.UpdateAPPProcess(app); err != nil {
			log.Errorf("update app %+v failed, error: %v", app, err)
		}
	}()

	if err := mgr.operator.CreateAPP(context.Background(), cfg); err != nil {
		log.Errorf("create app %+v failed, error: %v", cfg, err)
		finalState = types.TestStateFailed
		return errors.Trace(err)
	}

	finalState = types.TestStateRunning

	return nil
}

// DeleteAPP deletes app
func (mgr *Manager) DeleteAPP(namespace string, name string) error {
	var err error

	if err = mgr.operator.DeleteAPP(nil, namespace, name); err != nil {
		log.Errorf("delete app %s %s failed, error: %v", namespace, name, err)
	}

	app, ok := mgr.storage.GetAPPProcessByNamespaceAndName(namespace, name)
	if !ok {
		if strings.Contains(err.Error(), "not found") {
			return nil
		}
		return errors.Trace(err)
	}

	app.Status = types.TestStateDestroyed
	if err != nil && !strings.Contains(err.Error(), "not found") {
		app.Status = types.TestStateFailed
	}

	app.UpdateReport()
	if err := mgr.storage.UpdateAPPProcess(app); err != nil {
		log.Errorf("update app %+v failed, error: %v", app, err)
		return errors.Trace(err)
	}

	return nil
}
