package service

import (
	"bytes"
	"context"
	"strings"
	"time"

	beforeflightinspection "wucher/internal/domain/before_flight_inspection"
	"wucher/internal/domain/flight"
	flightinspection "wucher/internal/domain/flight_inspection"
	flightinspectionfilechecklist "wucher/internal/domain/flight_inspection_file_checklist"
	flightprepcheck "wucher/internal/domain/flight_prep_check"
	helicopterfile "wucher/internal/domain/helicopter_file"
	reserveac "wucher/internal/domain/reserve_ac"
	"wucher/internal/shared/pkg/uuidv7"
	requestdto "wucher/internal/transport/http/dto/request"
)

// ReserveAcUpdateError carries structured validation/update failures from the
// application service layer back to the HTTP handler.
type ReserveAcUpdateError struct {
	Status  int
	Title   string
	Detail  string
	Pointer string
}

func (e *ReserveAcUpdateError) Error() string {
	if e == nil {
		return ""
	}
	return e.Detail
}

type ReserveAcUpdateInput struct {
	ID            []byte
	ActorUserID   []byte
	AircraftID    *string
	FlightID      *string
	Inspection    *requestdto.ReserveAcInspectionUpdateAttributes
	Flight        reserveAcFlightService
	Inspect       flightinspection.FlightInspectionService
	Before        beforeflightinspection.Service
	Prep          flightprepcheck.Service
	HeliFile      helicopterfile.Service
	FileChecklist flightinspectionfilechecklist.Service
}

type reserveAcFlightService interface {
	GetByID(ctx context.Context, id []byte) (*flight.Flight, error)
	GetByReserveAcID(ctx context.Context, reserveAcID []byte) (*flight.Flight, error)
	Update(ctx context.Context, row *flight.Flight) error
}

type ReserveAcCreateInput struct {
	HelicopterID   []byte
	FlightID       []byte
	InspectionDate time.Time
	Before         *requestdto.ReserveAcBeforeInspectionAttributes
	Prepare        *requestdto.ReserveAcPrepareInspectionAttributes
	ActorUserID    []byte
	Flight         reserveAcFlightService
	Inspect        flightinspection.FlightInspectionService
	BeforeSvc      beforeflightinspection.Service
	Prep           flightprepcheck.Service
	HeliFile       helicopterfile.Service
	FileChecklist  flightinspectionfilechecklist.Service
}

func (s *ReserveAcService) UpdateDetailed(ctx context.Context, in ReserveAcUpdateInput) (*reserveac.ReserveAc, error) {
	if s == nil || s.repo == nil {
		return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "reserve ac service is not configured"}
	}
	if len(in.ID) != 16 {
		return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "id is invalid UUID", Pointer: "/data/id"}
	}

	existing, err := s.repo.GetByID(ctx, in.ID)
	if err != nil {
		return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: err.Error()}
	}
	if existing == nil {
		return nil, &ReserveAcUpdateError{Status: 404, Title: "Not found", Detail: "reserve_ac not found"}
	}

	if in.FlightID != nil {
		if in.Flight == nil {
			return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "flight service is not configured"}
		}
		flightValue := strings.TrimSpace(*in.FlightID)
		flightID, parseErr := uuidv7.ParseString(flightValue)
		if parseErr != nil {
			return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "flight_id is invalid UUID", Pointer: "/data/attributes/flight_id"}
		}

		targetFlight, flightErr := in.Flight.GetByID(ctx, flightID)
		if flightErr != nil {
			return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: flightErr.Error()}
		}
		if targetFlight == nil {
			return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "flight_id does not exist", Pointer: "/data/attributes/flight_id"}
		}
		if len(targetFlight.ReserveAcID) == 16 && !bytes.Equal(targetFlight.ReserveAcID, existing.ID) {
			return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "flight already has reserve_ac assigned", Pointer: "/data/attributes/flight_id"}
		}

		currentFlight, currentErr := in.Flight.GetByReserveAcID(ctx, existing.ID)
		if currentErr != nil {
			return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: currentErr.Error()}
		}
		if currentFlight != nil && !bytes.Equal(currentFlight.ID, targetFlight.ID) {
			currentFlight.ReserveAcID = nil
			currentFlight.UpdatedBy = in.ActorUserID
			if updateErr := in.Flight.Update(ctx, currentFlight); updateErr != nil {
				return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: updateErr.Error()}
			}
		}

		if len(targetFlight.ReserveAcID) != 16 || !bytes.Equal(targetFlight.ReserveAcID, existing.ID) {
			targetFlight.ReserveAcID = append([]byte(nil), existing.ID...)
			targetFlight.UpdatedBy = in.ActorUserID
			if updateErr := in.Flight.Update(ctx, targetFlight); updateErr != nil {
				return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: updateErr.Error()}
			}
		}
	}

	if in.AircraftID != nil && strings.TrimSpace(*in.AircraftID) != "" {
		helicopterValue := strings.TrimSpace(*in.AircraftID)
		helicopterID, parseErr := uuidv7.ParseString(helicopterValue)
		if parseErr != nil {
			return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "helicopter_id is invalid UUID", Pointer: "/data/attributes/helicopter_id"}
		}
		exists, existsErr := s.repo.AircraftExists(ctx, helicopterID)
		if existsErr != nil {
			return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: existsErr.Error()}
		}
		if !exists {
			return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "helicopter_id does not exist", Pointer: "/data/attributes/helicopter_id"}
		}
		existing.AircraftID = helicopterID
	}

	if in.Inspection != nil {
		if in.Inspect == nil {
			return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "flight inspection service is not configured"}
		}
		if in.Before == nil {
			return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "before flight inspection service is not configured"}
		}
		if in.Prep == nil {
			return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "flight prep check service is not configured"}
		}
		if in.HeliFile == nil {
			return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "helicopter file service is not configured"}
		}
		if in.FileChecklist == nil {
			return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "flight inspection file checklist service is not configured"}
		}

		inspectionRow, getErr := in.Inspect.GetByID(ctx, existing.InspectionID)
		if getErr != nil {
			return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: getErr.Error()}
		}
		if inspectionRow == nil {
			return nil, &ReserveAcUpdateError{Status: 404, Title: "Not found", Detail: "flight inspection not found"}
		}

		if in.Inspection.InspectionDate != nil {
			inspectionDate, parseErr := time.Parse("2006-01-02", strings.TrimSpace(*in.Inspection.InspectionDate))
			if parseErr != nil {
				return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "inspection.inspection_date must be YYYY-MM-DD", Pointer: "/data/attributes/inspection/inspection_date"}
			}
			inspectionRow.InspectionDate = inspectionDate.UTC()
			inspectionRow.UpdatedBy = in.ActorUserID
			if updateErr := in.Inspect.Update(ctx, inspectionRow); updateErr != nil {
				return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: updateErr.Error()}
			}
		}

		if in.Inspection.Before != nil {
			beforeReq := &beforeflightinspection.UpsertRequest{
				OilEngineNR1Checked:       in.Inspection.Before.OilEngineNR1Checked,
				OilEngineNR2Checked:       in.Inspection.Before.OilEngineNR2Checked,
				HydraulicLHChecked:        in.Inspection.Before.HydraulicLHChecked,
				HydraulicRHChecked:        in.Inspection.Before.HydraulicRHChecked,
				OilTransmissionMGBChecked: in.Inspection.Before.OilTransmissionMGBChecked,
				OilTransmissionIGBChecked: in.Inspection.Before.OilTransmissionIGBChecked,
				OilTransmissionTGBChecked: in.Inspection.Before.OilTransmissionTGBChecked,
				FuelAmount:                in.Inspection.Before.FuelAmount,
				FuelUnit:                  in.Inspection.Before.FuelUnit,
				FuelAddedAmount:           in.Inspection.Before.FuelAddedAmount,
				Note:                      in.Inspection.Before.Note,
			}
			if _, upsertErr := in.Before.Upsert(ctx, existing.InspectionID, beforeReq); upsertErr != nil {
				return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: upsertErr.Error()}
			}
			if in.Inspection.Before.FileChecklist != nil {
				if err := s.upsertInspectionFileChecklistSection(ctx, in, existing.InspectionID, existing.AircraftID, helicopterfile.SectionBeforeFirstFlightInspection, in.Inspection.Before.FileChecklist, "/data/attributes/inspection/before/file_checklist", existing.ID); err != nil {
					return nil, err
				}
			}
		}

		if in.Inspection.Prepare != nil {
			if _, upsertErr := in.Prep.UpsertByFlightInspection(ctx, existing.InspectionID, &flightprepcheck.UpsertRequest{
				NOTAMBriefing:         in.Inspection.Prepare.NotamBriefing,
				WeatherBriefing:       in.Inspection.Prepare.WeatherBriefing,
				OperationalFlightPlan: in.Inspection.Prepare.OperationalFlightPlan,
			}); upsertErr != nil {
				return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: upsertErr.Error()}
			}
			if in.Inspection.Prepare.FileChecklist != nil {
				if err := s.upsertInspectionFileChecklistSection(ctx, in, existing.InspectionID, existing.AircraftID, helicopterfile.SectionFlightPreparationAndWB, in.Inspection.Prepare.FileChecklist, "/data/attributes/inspection/prepare/file_checklist", existing.ID); err != nil {
					return nil, err
				}
			}
		}
	}

	existing.UpdatedBy = in.ActorUserID
	existing.Status = s.calculateReserveAcStatus(ctx, in, existing.InspectionID, existing.AircraftID)
	if err := s.Update(ctx, existing); err != nil {
		return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: err.Error()}
	}

	return existing, nil
}

func (s *ReserveAcService) CreateDetailed(ctx context.Context, in ReserveAcCreateInput) (*reserveac.ReserveAc, error) {
	if s == nil || s.repo == nil {
		return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "reserve ac service is not configured"}
	}
	if len(in.HelicopterID) != 16 {
		return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "helicopter_id is invalid UUID", Pointer: "/data/attributes/helicopter_id"}
	}
	if len(in.FlightID) != 16 {
		return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "flight_id is invalid UUID", Pointer: "/data/attributes/flight_id"}
	}
	if in.Before == nil {
		return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "inspection.before is required", Pointer: "/data/attributes/inspection/before"}
	}
	if in.Prepare == nil {
		return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "inspection.prepare is required", Pointer: "/data/attributes/inspection/prepare"}
	}
	if in.Flight == nil {
		return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "flight service is not configured"}
	}
	if in.Inspect == nil {
		return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "flight inspection service is not configured"}
	}
	if in.BeforeSvc == nil {
		return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "before flight inspection service is not configured"}
	}
	if in.Prep == nil {
		return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "flight prep check service is not configured"}
	}
	if in.HeliFile == nil {
		return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "helicopter file service is not configured"}
	}
	if in.FileChecklist == nil {
		return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "flight inspection file checklist service is not configured"}
	}

	flightRow, err := in.Flight.GetByID(ctx, in.FlightID)
	if err != nil {
		return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
	}
	if flightRow == nil {
		return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "flight_id does not exist", Pointer: "/data/attributes/flight_id"}
	}
	if len(flightRow.ReserveAcID) == 16 {
		return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "flight already has reserve_ac assigned", Pointer: "/data/attributes/flight_id"}
	}

	exists, err := s.repo.AircraftExists(ctx, in.HelicopterID)
	if err != nil {
		return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
	}
	if !exists {
		return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "helicopter_id does not exist", Pointer: "/data/attributes/helicopter_id"}
	}

	inspection := &flightinspection.FlightInspection{
		InspectionDate: in.InspectionDate.UTC(),
		CreatedBy:      in.ActorUserID,
		UpdatedBy:      in.ActorUserID,
	}
	if err := in.Inspect.CreateDraft(ctx, inspection); err != nil {
		return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
	}

	row := &reserveac.ReserveAc{
		Status:       reserveac.StatusPending,
		AircraftID:   append([]byte(nil), in.HelicopterID...),
		InspectionID: append([]byte(nil), inspection.ID...),
		CreatedBy:    in.ActorUserID,
		UpdatedBy:    in.ActorUserID,
	}
	if err := s.Create(ctx, row); err != nil {
		return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
	}

	beforeReq := &beforeflightinspection.UpsertRequest{
		OilEngineNR1Checked:       in.Before.OilEngineNR1Checked,
		OilEngineNR2Checked:       in.Before.OilEngineNR2Checked,
		HydraulicLHChecked:        in.Before.HydraulicLHChecked,
		HydraulicRHChecked:        in.Before.HydraulicRHChecked,
		OilTransmissionMGBChecked: in.Before.OilTransmissionMGBChecked,
		OilTransmissionIGBChecked: in.Before.OilTransmissionIGBChecked,
		OilTransmissionTGBChecked: in.Before.OilTransmissionTGBChecked,
		FuelAmount:                in.Before.FuelAmount,
		FuelUnit:                  in.Before.FuelUnit,
		FuelAddedAmount:           in.Before.FuelAddedAmount,
		Note:                      in.Before.Note,
	}
	if _, err := in.BeforeSvc.Upsert(ctx, inspection.ID, beforeReq); err != nil {
		_ = s.Delete(ctx, row.ID, in.ActorUserID)
		return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
	}
	if _, err := in.Prep.InitializeChecks(ctx, inspection.ID); err != nil {
		_ = s.Delete(ctx, row.ID, in.ActorUserID)
		return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
	}
	if _, err := in.Prep.UpsertByFlightInspection(ctx, inspection.ID, &flightprepcheck.UpsertRequest{
		NOTAMBriefing:         in.Prepare.NotamBriefing,
		WeatherBriefing:       in.Prepare.WeatherBriefing,
		OperationalFlightPlan: in.Prepare.OperationalFlightPlan,
	}); err != nil {
		_ = s.Delete(ctx, row.ID, in.ActorUserID)
		return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
	}
	if in.Before.FileChecklist != nil {
		if err := s.upsertInspectionFileChecklistSection(ctx, ReserveAcUpdateInput{
			ActorUserID:   in.ActorUserID,
			HeliFile:      in.HeliFile,
			FileChecklist: in.FileChecklist,
		}, inspection.ID, in.HelicopterID, helicopterfile.SectionBeforeFirstFlightInspection, in.Before.FileChecklist, "/data/attributes/inspection/before/file_checklist", row.ID); err != nil {
			return nil, err
		}
	}
	if in.Prepare.FileChecklist != nil {
		if err := s.upsertInspectionFileChecklistSection(ctx, ReserveAcUpdateInput{
			ActorUserID:   in.ActorUserID,
			HeliFile:      in.HeliFile,
			FileChecklist: in.FileChecklist,
		}, inspection.ID, in.HelicopterID, helicopterfile.SectionFlightPreparationAndWB, in.Prepare.FileChecklist, "/data/attributes/inspection/prepare/file_checklist", row.ID); err != nil {
			return nil, err
		}
	}

	flightRow.ReserveAcID = append([]byte(nil), row.ID...)
	flightRow.UpdatedBy = in.ActorUserID
	if err := in.Flight.Update(ctx, flightRow); err != nil {
		_ = s.Delete(ctx, row.ID, in.ActorUserID)
		return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
	}

	row.Status = s.calculateReserveAcStatus(ctx, ReserveAcUpdateInput{
		Inspect:       in.Inspect,
		Before:        in.BeforeSvc,
		Prep:          in.Prep,
		HeliFile:      in.HeliFile,
		FileChecklist: in.FileChecklist,
	}, inspection.ID, in.HelicopterID)
	if err := s.Update(ctx, row); err != nil {
		_ = s.Delete(ctx, row.ID, in.ActorUserID)
		return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
	}

	return row, nil
}

func (s *ReserveAcService) calculateReserveAcStatus(ctx context.Context, in ReserveAcUpdateInput, inspectionID []byte, helicopterID []byte) string {
	if len(inspectionID) != 16 || len(helicopterID) != 16 {
		return reserveac.StatusPending
	}
	if in.Inspect == nil || in.Before == nil || in.Prep == nil || in.HeliFile == nil || in.FileChecklist == nil {
		return reserveac.StatusPending
	}

	inspectionRow, err := in.Inspect.GetByID(ctx, inspectionID)
	if err != nil || inspectionRow == nil {
		return reserveac.StatusPending
	}
	ckRows, err := in.FileChecklist.ListByInspectionID(ctx, inspectionID)
	if err != nil {
		return reserveac.StatusPending
	}
	isDoneByHeliFileID := make(map[string]bool, len(ckRows))
	for i := range ckRows {
		isDoneByHeliFileID[string(ckRows[i].HelicopterFileID)] = ckRows[i].IsDone
	}

	beforeRows, err := in.HeliFile.ListByHelicopterAndSection(ctx, helicopterID, helicopterfile.SectionBeforeFirstFlightInspection)
	if err != nil {
		return reserveac.StatusPending
	}
	prepareRows, err := in.HeliFile.ListByHelicopterAndSection(ctx, helicopterID, helicopterfile.SectionFlightPreparationAndWB)
	if err != nil {
		return reserveac.StatusPending
	}
	beforeData, _ := in.Before.GetByFlightInspectionID(ctx, inspectionID)
	prepareData, _ := in.Prep.GetByFlightInspection(ctx, inspectionID)

	beforeDone := countCompletedChecklist(beforeRows, isDoneByHeliFileID)
	prepareDone := countCompletedChecklist(prepareRows, isDoneByHeliFileID)
	totalChecklist := len(beforeRows) + len(prepareRows)
	doneChecklist := beforeDone + prepareDone
	if totalChecklist > 0 {
		if doneChecklist == 0 {
			return reserveac.StatusPending
		}
		if doneChecklist < totalChecklist {
			return reserveac.StatusOnProgress
		}
		return reserveac.StatusApproved
	}
	if beforeData != nil || prepareData != nil {
		return reserveac.StatusOnProgress
	}
	return reserveac.StatusPending
}

func countCompletedChecklist(files []helicopterfile.HelicopterFile, doneByID map[string]bool) int {
	if len(files) == 0 {
		return 0
	}
	completed := 0
	for i := range files {
		if doneByID[string(files[i].ID)] {
			completed++
		}
	}
	return completed
}

func (s *ReserveAcService) upsertInspectionFileChecklistSection(
	ctx context.Context,
	in ReserveAcUpdateInput,
	inspectionID []byte,
	helicopterID []byte,
	section string,
	payload []requestdto.ReserveAcFileChecklistItem,
	payloadPointer string,
	reserveAcID []byte,
) error {
	templateFiles, err := in.HeliFile.ListByHelicopterAndSection(ctx, helicopterID, section)
	if err != nil {
		if len(reserveAcID) == 16 {
			_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
		}
		return &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
	}

	type requestedChecklist struct {
		fileID []byte
		isDone bool
	}
	requested := make([]requestedChecklist, 0, len(payload))
	for i := range payload {
		fileID, parseErr := uuidv7.ParseString(strings.TrimSpace(payload[i].HelicopterFileID))
		if parseErr != nil {
			if len(reserveAcID) == 16 {
				_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
			}
			return &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "helicopter_file_id is invalid UUID", Pointer: payloadPointer}
		}
		requested = append(requested, requestedChecklist{
			fileID: fileID,
			isDone: payload[i].IsDone,
		})
	}
	requestedByFileID := make(map[string]bool, len(requested))
	for i := range requested {
		requestedByFileID[string(requested[i].fileID)] = requested[i].isDone
	}

	existingRows, err := in.FileChecklist.ListByInspectionID(ctx, inspectionID)
	if err != nil {
		if len(reserveAcID) == 16 {
			_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
		}
		return &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
	}
	existingByFileID := make(map[string]*flightinspectionfilechecklist.FlightInspectionFileChecklist, len(existingRows))
	for i := range existingRows {
		fileID := string(existingRows[i].HelicopterFileID)
		existingByFileID[fileID] = &existingRows[i]
	}

	templateSet := make(map[string]struct{}, len(templateFiles))
	for i := range templateFiles {
		fileKey := string(templateFiles[i].ID)
		templateSet[fileKey] = struct{}{}

		current := existingByFileID[fileKey]
		targetDone, hasOverride := requestedByFileID[fileKey]

		if templateFiles[i].IsMandatory && !targetDone {
			if len(reserveAcID) == 16 {
				_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
			}
			return &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "file_checklist must be fully checked", Pointer: payloadPointer}
		}

		if current == nil {
			if !hasOverride {
				targetDone = false
			}
			newRow := &flightinspectionfilechecklist.FlightInspectionFileChecklist{
				FlightInspectionID: inspectionID,
				HelicopterFileID:   templateFiles[i].ID,
				IsDone:             targetDone,
				CreatedBy:          in.ActorUserID,
				UpdatedBy:          in.ActorUserID,
			}
			if err := in.FileChecklist.Create(ctx, newRow); err != nil {
				if len(reserveAcID) == 16 {
					_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
				}
				return &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
			}
			continue
		}

		if !hasOverride {
			targetDone = current.IsDone
		}

		if current.IsDone != targetDone {
			current.IsDone = targetDone
			current.UpdatedBy = in.ActorUserID
			if err := in.FileChecklist.Update(ctx, current); err != nil {
				if len(reserveAcID) == 16 {
					_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
				}
				return &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
			}
		}
	}

	for i := range requested {
		if _, ok := templateSet[string(requested[i].fileID)]; ok {
			continue
		}
		if len(reserveAcID) == 16 {
			_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
		}
		return &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "helicopter_file_id does not belong to selected helicopter/section", Pointer: payloadPointer}
	}

	return nil
}
