package orm

import (
	"fmt"
	"net/http"
	"time"

	"gogs.carduccidante.edu.it/karmen/core/renderer"
)

type Administrative struct {
	Credential

	Office *Office

	OfficeID uint `schema:"office_id"`

	AllOffices     []*Office
	SelectedOffice map[uint]string `gorm:"-"`
}

func (s *Administrative) GetID() uint    { return s.ID }
func (a *Administrative) String() string { return a.CompleteName() }

func (a *Administrative) Create(args map[string]string, r *http.Request) (interface{}, error) {
	if r.Method == "GET" {
		administrative := new(Administrative)
		if err := DB().Find(&administrative.AllOffices).Error; err != nil {
			return nil, err
		}
		return administrative, nil
	} else {
		administrative := new(Administrative)
		err := renderer.Decode(administrative, r)
		if err != nil {
			return nil, err
		}
		administrative, err = CreateAdministrative(administrative)
		if err != nil {
			return nil, err
		}

		return administrative, nil
	}
}

func (a *Administrative) Read(args map[string]string, r *http.Request) (interface{}, error) {
	var administrative Administrative

	id := args["id"]

	if err := DB().Preload("Office").Where("id = ?", id).Find(&administrative).Error; err != nil {
		return nil, err
	}

	return &administrative, nil
}

func (a *Administrative) ReadAll(args map[string]string, r *http.Request) (interface{}, error) {
	var administratives []*Administrative

	if err := DB().Preload("Office").Order("surname,name").Find(&administratives).Error; err != nil {
		return nil, err
	}

	return administratives, nil
}

func (a *Administrative) Update(args map[string]string, r *http.Request) (interface{}, error) {
	if r.Method == "GET" {
		result, err := a.Read(args, r)
		if err != nil {
			return nil, err
		}

		administrative := result.(*Administrative)

		if err := DB().Find(&administrative.AllOffices).Error; err != nil {
			return nil, err
		}

		administrative.SelectedOffice = make(map[uint]string)
		administrative.SelectedOffice[administrative.OfficeID] = "selected"

		return administrative, nil
	} else {
		administrative, err := a.Read(args, r)
		if err != nil {
			return nil, err
		}

		// FIXME: Should not be hard set.
		administrative.(*Administrative).Regenerate = false

		// FIXME: Should not be hard set.
		administrative.(*Administrative).Exclude = false

		// FIXME: Should not be hard set.
		administrative.(*Administrative).NotInvited = false

		if len(args["DateFrom"]) == 0 {
			// FIXME: Should not be hard set.
			administrative.(*Administrative).DateFrom = time.Time{}
		}

		if len(args["DateTo"]) == 0 {
			// FIXME: Should not be hard set.
			administrative.(*Administrative).DateTo = time.Time{}
		}

		err = renderer.Decode(administrative, r)
		if err != nil {
			return nil, err
		}
		_, err = SaveAdministrative(administrative)
		if err != nil {
			return nil, err
		}
		administrative, err = a.Read(args, r)
		if err != nil {
			return nil, err
		}

		return administrative.(*Administrative), nil
	}
}

func (a *Administrative) Delete(args map[string]string, r *http.Request) (interface{}, error) {
	administrative, err := a.Read(args, r)
	if err != nil {
		return nil, err
	}
	if err := DB().Unscoped().Delete(administrative.(*Administrative)).Error; err != nil {
		return nil, err
	}
	return administrative.(*Administrative), nil
}

func SaveAdministrative(administrative interface{}) (interface{}, error) {
	if err := DB().Omit("Office").Save(administrative).Error; err != nil {
		return nil, err
	}
	return administrative, nil
}

func CreateAdministrative(administrative *Administrative) (*Administrative, error) {
	if err := DB().Create(administrative).Error; err != nil {
		return nil, err
	}
	return administrative, nil
}

func (s *Administrative) CompleteName() string {
	return fmt.Sprintf("%s %s", s.Name, s.Surname)
}

func (t *Administrative) RestAPIPath() string {
	return "administratives"
}
