package service

import (
	"context"
	"time"

	easarelease "wucher/internal/domain/easa_release"
)

type EASAReleaseService struct{ repo easarelease.Repository }

func NewEASAReleaseService(repo easarelease.Repository) *EASAReleaseService {
	return &EASAReleaseService{repo: repo}
}

func (s *EASAReleaseService) Create(ctx context.Context, row *easarelease.EASARelease) error {
	return s.repo.Create(ctx, row)
}

func (s *EASAReleaseService) Update(ctx context.Context, row *easarelease.EASARelease) error {
	return s.repo.Update(ctx, row)
}

func (s *EASAReleaseService) Delete(ctx context.Context, id []byte, deletedBy []byte) error {
	return s.repo.Delete(ctx, id, deletedBy)
}

func (s *EASAReleaseService) GetByID(ctx context.Context, id []byte) (*easarelease.EASARelease, error) {
	return s.repo.GetByID(ctx, id)
}

// GetByFlightID returns the current (newest non-voided) release for a flight.
func (s *EASAReleaseService) GetByFlightID(ctx context.Context, flightID []byte) (*easarelease.EASARelease, error) {
	return s.repo.GetByFlightID(ctx, flightID)
}

// GetByComplaintID returns the current (newest non-voided) release for a complaint.
func (s *EASAReleaseService) GetByComplaintID(ctx context.Context, complaintID []byte) (*easarelease.EASARelease, error) {
	return s.repo.GetByComplaintID(ctx, complaintID)
}

func (s *EASAReleaseService) ListByHelicopter(ctx context.Context, helicopterID []byte) ([]easarelease.EASARelease, error) {
	return s.repo.ListByHelicopter(ctx, helicopterID)
}

func (s *EASAReleaseService) GetLatestByHelicopter(ctx context.Context, helicopterID []byte) (*easarelease.EASARelease, error) {
	return s.repo.GetLatestByHelicopter(ctx, helicopterID)
}

func (s *EASAReleaseService) GetActiveByHelicopter(ctx context.Context, helicopterID []byte) (*easarelease.EASARelease, error) {
	return s.repo.GetActiveByHelicopter(ctx, helicopterID)
}

// Sign stamps the maintenance release as signed (active). A signed release closes
// the defects of its flight inspection. Re-signing an already-signed release fails.
func (s *EASAReleaseService) Sign(ctx context.Context, id []byte, signerID []byte) error {
	row, err := s.repo.GetByID(ctx, id)
	if err != nil {
		return err
	}
	if row == nil {
		return easarelease.ErrNotFound
	}
	if row.SignedAt != nil {
		return easarelease.ErrAlreadySigned
	}
	if len(row.MissingSignFields()) > 0 {
		return easarelease.ErrIncompleteForSign
	}
	now := time.Now().UTC()
	row.SignedAt = &now
	row.SignedBy = append([]byte(nil), signerID...)
	row.UpdatedBy = append([]byte(nil), signerID...)
	return s.repo.Update(ctx, row)
}

// Amend supersedes the current release: it voids (soft-deletes) the current one and
// creates a fresh unsigned copy for the same flight inspection, returning the new id.
func (s *EASAReleaseService) Amend(ctx context.Context, currentID []byte, reason string, actor []byte) ([]byte, error) {
	cur, err := s.repo.GetByID(ctx, currentID)
	if err != nil {
		return nil, err
	}
	if cur == nil {
		return nil, easarelease.ErrNotFound
	}
	if err := s.repo.VoidByID(ctx, currentID, reason, actor); err != nil {
		return nil, err
	}
	next := &easarelease.EASARelease{
		HelicopterID:               append([]byte(nil), cur.HelicopterID...),
		FlightID:                   append([]byte(nil), cur.FlightID...),
		ComplaintID:                append([]byte(nil), cur.ComplaintID...),
		EASADate:                   cur.EASADate,
		EASAACHours:                cur.EASAACHours,
		EASALocation:               cur.EASALocation,
		EASAWONo:                   cur.EASAWONo,
		EASAMaintManualRevAirframe: cur.EASAMaintManualRevAirframe,
		EASAMaintManualRevEngine:   cur.EASAMaintManualRevEngine,
		EASASignerID:               cur.EASASignerID,
		EASAPermitNo:               cur.EASAPermitNo,
		CreatedBy:                  append([]byte(nil), actor...),
		UpdatedBy:                  append([]byte(nil), actor...),
	}
	if err := s.repo.Create(ctx, next); err != nil {
		return nil, err
	}
	return next.ID, nil
}
