// This file is part of the happyDomain (R) project.
// Copyright (c) 2020-2025 happyDomain
// Authors: Pierre-Olivier Mercier, et al.
//
// This program is offered under a commercial and under the AGPL license.
// For commercial licensing, contact us at <contact@happydomain.org>.
//
// For AGPL licensing:
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

package zone

import (
	"fmt"

	"git.happydns.org/happyDomain/model"
)

// UpdateZoneUsecase handles the fetch-mutate-save cycle for a Zone.
type UpdateZoneUsecase struct {
	store   ZoneStorage
	getZone *GetZoneUsecase
}

// NewUpdateZoneUsease constructs an UpdateZoneUsecase backed by the given
// storage and zone-retrieval dependencies.
func NewUpdateZoneUsease(store ZoneStorage, getZone *GetZoneUsecase) *UpdateZoneUsecase {
	return &UpdateZoneUsecase{
		store:   store,
		getZone: getZone,
	}
}

// Update fetches the zone identified by zoneID, applies updateFn to it, and
// persists the result. It returns a ValidationError if updateFn changes the
// zone identifier, or an InternalError if the storage write fails.
func (uc *UpdateZoneUsecase) Update(zoneID happydns.Identifier, updateFn func(*happydns.Zone)) error {
	zone, err := uc.getZone.Get(zoneID)
	if err != nil {
		return err
	}

	updateFn(zone)

	if !zone.Id.Equals(zoneID) {
		return happydns.ValidationError{Msg: "you cannot change the zone identifier"}
	}

	err = uc.store.UpdateZone(zone)
	if err != nil {
		return happydns.InternalError{
			Err:         fmt.Errorf("unable to UpdateZone in UpdateZone: %w", err),
			UserMessage: "Sorry, we are currently unable to update your zone. Please retry later.",
		}
	}

	return nil
}
