package external

import (
	"errors"
	"fmt"
	"log"
	"strconv"
	"strings"
	"ticket-pimp/internal/domain"
	"ticket-pimp/internal/helpers"
	"time"
)

type Cloud struct {
	*CommonClient
	Config domain.CloudConfig
}

func NewCloud(conf domain.CloudConfig) *Cloud {

	client := NewClient().
		SetTimeout(5*time.Second).
		SetCommonBasicAuth(conf.User, conf.Pass).
		SetBaseURL(conf.BaseUrl)

	return &Cloud{
		CommonClient: &CommonClient{
			client,
		},
		Config: conf,
	}
}

func (c *Cloud) CreateFolder(name string) domain.Response {
	var R domain.Response

	rootDir := c.Config.RootDir
	user := c.Config.User

	davPath := "/remote.php/dav/files/"
	parentPath := "/apps/files/?dir="

	name = helpers.Cut(name)

	R.Folder = &domain.Folder{
		Title:      name,
		PrivateURL: "",
	}

	// cloud := domain.Folder{
	// 	Title:      name,
	// 	PrivateURL: "",
	// }

	requestPath := davPath + user + rootDir + name

	R.Folder.PathTo = parentPath + rootDir + name

	var errMessage helpers.ErrorMessage

	resp, err := c.R().
		SetErrorResult(&errMessage).
		Send("MKCOL", requestPath)

	if err != nil { // Error handling.
		log.Println("error:", err)

		// Херовая обработка ошибки:
		// error while cloud folder creation: bad response, raw content:
		// 	<?xml version="1.0" encoding="utf-8"?>
		// 	<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
		// 	<s:exception>Sabre\DAV\Exception\MethodNotAllowed</s:exception>
		// 	<s:message>The resource you tried to create already exists</s:message>
		// 	</d:error>
		if strings.Contains(err.Error(), "already exists") {
			R.Folder.PrivateURL = c.BaseURL + R.Folder.PathTo
			R.ErrMessage = errors.New("guess, that folder already exists")
			// Try to set short URL to the d entity
			if err := c.setPrivateURL(requestPath, R.Folder); err != nil {
				R.ErrMessage = err
				return R
			}
			return R
		}
		return R
	}

	if resp.IsSuccessState() {
		// Set stupid URL to the d entity
		R.Folder.PrivateURL = c.BaseURL + R.Folder.PathTo

		// Try to set short URL to the d entity
		if err := c.setPrivateURL(requestPath, R.Folder); err != nil {
			return R
		}
	}

	return R
}

func (c *Cloud) setPrivateURL(requestPath string, cloud *domain.Folder) error {

	payload := []byte(`<?xml version="1.0"?><a:propfind xmlns:a="DAV:" xmlns:oc="http://owncloud.org/ns"><a:prop><oc:fileid/></a:prop></a:propfind>`)

	// Deprecated: Read XML file
	/*
		xmlFile, err := ioutil.ReadFile("./fileid.xml") // moved into this method as a string..

		if err != nil {
			return fmt.Errorf("request xml file error: %v", err)
		}
	*/

	resp, _ := c.R().
		SetBody(payload).
		Send("PROPFIND", requestPath)

	if resp.Err != nil {
		return resp.Err
	}

	id := helpers.GetFileIDFromRespBody(resp.Bytes())

	if id == 0 {
		return fmt.Errorf("unable to get fileid")
	}

	cloud.PrivateURL = c.BaseURL + "/f/" + strconv.Itoa(id)

	return nil
}
