package orm

import (
	"fmt"
	"net/http"

	"gogs.carducci-dante.gov.it/karmen/core/renderer"
)

type Administrative struct {
	Credential

	Office *Office

	OfficeID uint `schema:"office_id"`
}

type AdministrativeForUpdate struct {
	Administrative Administrative
	AllOffices     []*Office

	SelectedOffice map[uint]string
}

type AdministrativeForAdd struct {
	AllOffices []*Office
}

func (s *Administrative) GetID() uint { return s.ID }

func GetAdministrative(args map[string]string) (interface{}, error) {
	var administrative Administrative
	if err := DB().First(&administrative, args["id"]).Error; err != nil {
		return nil, err
	}
	return &administrative, nil
}

func GetAdministrativeAll(args map[string]string) (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 GetAdministratives(args map[string]string) (interface{}, error) {
	var administratives []*Administrative
	if err := DB().Order("surname,name").Find(&administratives).Error; err != nil {
		return nil, err
	}
	return administratives, nil
}

func GetAdministrativesAll(args map[string]string) (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 SaveAdministrative(administrative interface{}) (interface{}, error) {
	if err := DB().Omit("Office").Save(administrative).Error; err != nil {
		return nil, err
	}
	return administrative, nil
}

func UpdateAdministrative(args map[string]string, r *http.Request) (IDer, error) {
	administrative, err := GetAdministrative(args)
	if err != nil {
		return nil, err
	}

	err = renderer.Decode(administrative, r)
	if err != nil {
		return nil, err
	}

	_, err = SaveAdministrative(administrative)
	if err != nil {
		return nil, err
	}
	administrative, err = GetAdministrative(args)
	if err != nil {
		return nil, err
	}
	return administrative.(*Administrative), nil
}

func AddAdministrative(args map[string]string, r *http.Request) (IDer, error) {
	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 CreateAdministrative(administrative *Administrative) (*Administrative, error) {
	if err := DB().Create(administrative).Error; err != nil {
		return nil, err
	}
	return administrative, nil
}

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

func GetAdministrativeForUpdate(args map[string]string) (interface{}, error) {
	var data AdministrativeForUpdate

	id := args["id"]

	if err := DB().Preload("Office").First(&data.Administrative, id).Error; err != nil {
		return nil, err
	}

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

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

	return data, nil
}

func GetAdministrativeForAdd(args map[string]string) (interface{}, error) {
	var data AdministrativeForAdd

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

	return data, nil
}

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

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