package handlers

import (
	"errors"
	"fmt"
	"github.com/Pena-Co-Ltd/amocrm_templategen_back/dal/model"
	"github.com/gorilla/schema"
	"go.uber.org/zap"
	"golang.org/x/oauth2"
	"net/http"
	"time"
)

type ReqYaDiskSaveToken struct {
	AccessToken  string `json:"access_token" schema:"access_token"`
	Code         string `json:"code"`
	ExpiresIn    int64  `json:"expires_in" schema:"expires_in"`
	TokenType    string `json:"token_type" schema:"token_type"`
	RefreshToken string `json:"refresh_token"`
	State        string `json:"state" schema:"state"`
	Scope        string `json:"scope" schema:"scope"`
	Error        string `json:"error" schema:"error"`
}

func (h *Handlers) YaDiskSaveToken(w http.ResponseWriter, r *http.Request) {
	var req ReqYaDiskSaveToken
	err := r.ParseForm()
	if err != nil {
		h.reportError(w, err, http.StatusBadRequest)
		return
	}

	err = schema.NewDecoder().Decode(&req, r.Form)
	if err != nil {
		h.reportError(w, err, 500)
		return
	}

	if req.Error != "" {
		err = errors.New("YaDiskErr:" + req.Error)
		h.reportError(w, err, 500)
		return
	}

	if req.AccessToken == "" && req.Code == "" {
		err = errors.New("YaDiskErr: got empty token")
		h.reportError(w, err, http.StatusBadRequest)
		return
	}

	user := getJwtUser(r)
	if user == nil {
		h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
		return
	}

	token := &oauth2.Token{
		AccessToken:  req.AccessToken,
		TokenType:    req.TokenType,
		RefreshToken: req.RefreshToken,
		Expiry:       time.Now().Add(time.Duration(req.ExpiresIn) * time.Second),
	}

	yaDiskClient, err := h.YaDisk.NewClient(r.Context(), token, req.Code)

	if err != nil {
		h.reportError(w, err, http.StatusForbidden)
		return
	}

	token = yaDiskClient.Token

	yaUser, err := yaDiskClient.GetUser()
	if err != nil {
		h.reportError(w, err, http.StatusInternalServerError)
		return
	}

	fmt.Println("yaUser", yaUser)

	// Insert/Update token in DB
	_, err = h.dal.YaDisk.InsertOrUpdate(r.Context(), &model.YaDisk{
		UserID:         user.UserID,
		UID:            yaUser.Uid,
		Login:          yaUser.Login,
		DisplayName:    yaUser.DisplayName,
		AccessToken:    token.AccessToken,
		RefreshToken:   token.RefreshToken,
		ExpiresIn:      token.Expiry,
		TokenType:      token.TokenType,
		TemplateFolder: "disk:/templategen/templates",
		SaveFolder:     "disk:/templategen/saved",
	})

	if err != nil {
		h.reportError(w, err, 500)
		return
	}

	// Make default directories in YandexDisk
	err = yaDiskClient.PutResources("disk:/templategen")
	if err != nil {
		h.logger.Error("ErrorHandler", zap.Error(err))
	}

	err = yaDiskClient.PutResources("disk:/templategen/templates")
	if err != nil {
		h.logger.Error("ErrorHandler", zap.Error(err))
	}

	err = yaDiskClient.PutResources("disk:/templategen/saved")
	if err != nil {
		h.logger.Error("ErrorHandler", zap.Error(err))
	}

	// Может отправлять access token, чтобы на фронте сами могли обращаться к Я.диску?
	err = sendResponse(w, 200, map[string]string{"accessToken": req.AccessToken})
	if err != nil {
		h.reportError(w, err, 500)
	}
}

type ReqYaDiskSetFolders struct {
	TemplateFolder string `json:"template_folder"`
	SaveFolder     string `json:"save_folder"`
}

func (h *Handlers) YaDiskSetFolders(w http.ResponseWriter, r *http.Request) {
	var req ReqYaDiskSetFolders

	user := getJwtUser(r)
	if user == nil {
		h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
		return
	}

	err := decodePost(&req, r)
	if err != nil {
		h.reportError(w, err, http.StatusBadRequest)
		return
	}

	err = h.dal.YaDisk.Update(r.Context(), &model.YaDisk{
		TemplateFolder: req.TemplateFolder,
		SaveFolder:     req.SaveFolder},
	)

	if err != nil {
		h.reportError(w, err, http.StatusInternalServerError)
		return
	}

	sendResponse(w, 200, nil)
}

// YaDiskGetList - возвращает список хранилищ Yandex закрепленных за пользователем по его UserID из JWT
func (h *Handlers) YaDiskGetList(w http.ResponseWriter, r *http.Request) {
	amoData := getAmoByJwt(r)
	user := getJwtUser(r)

	if amoData == nil && user == nil {
		h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
		return
	}

	var userID string
	if user != nil {
		userID = user.UserID
	} else {
		userID = amoData.UserID
	}

	yadiskInfo, err := h.dal.YaDisk.GetListByUserID(r.Context(), userID)
	if err != nil {
		h.reportError(w, err, http.StatusInternalServerError)
		return
	}

	sendResponse(w, http.StatusOK, yadiskInfo)
}
