package handlers

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"io"
	"net/http"
	"reflect"
	"strings"
	"testing"
	"time"

	"github.com/gofiber/fiber/v2"
	"gorm.io/gorm"

	afterflightinspection "wucher/internal/domain/after_flight_inspection"
	beforeflightinspection "wucher/internal/domain/before_flight_inspection"
	filemanager "wucher/internal/domain/file_manager"
	"wucher/internal/domain/flight"
	flightdata "wucher/internal/domain/flight_data"
	flightinspection "wucher/internal/domain/flight_inspection"
	flightinspectionfilechecklist "wucher/internal/domain/flight_inspection_file_checklist"
	flightprepcheck "wucher/internal/domain/flight_prep_check"
	"wucher/internal/domain/helicopter"
	helicopterfile "wucher/internal/domain/helicopter_file"
	hospitaldomain "wucher/internal/domain/hospital"
	icaodomain "wucher/internal/domain/icao"
	"wucher/internal/domain/mission"
	reserveac "wucher/internal/domain/reserve_ac"
	"wucher/internal/shared/pkg/uuidv7"
	requestdto "wucher/internal/transport/http/dto/request"
	responsedto "wucher/internal/transport/http/dto/response"
	shareddto "wucher/internal/transport/http/dto/shared"
)

type reserveAcServiceMock struct {
	createFn          func(context.Context, *reserveac.ReserveAc) error
	updateFn          func(context.Context, *reserveac.ReserveAc) error
	deleteFn          func(context.Context, []byte, []byte) error
	listFn            func(context.Context, string, string, int, int) ([]reserveac.ReserveAc, int64, error)
	getByIDFn         func(context.Context, []byte) (*reserveac.ReserveAc, error)
	getActiveByInspFn func(context.Context, []byte) (*reserveac.ReserveAc, error)
	aircraftExistsFn  func(context.Context, []byte) (bool, error)
}

func (m *reserveAcServiceMock) Create(ctx context.Context, row *reserveac.ReserveAc) error {
	if m.createFn != nil {
		return m.createFn(ctx, row)
	}
	return nil
}
func (m *reserveAcServiceMock) Update(ctx context.Context, row *reserveac.ReserveAc) error {
	if m.updateFn != nil {
		return m.updateFn(ctx, row)
	}
	return nil
}
func (m *reserveAcServiceMock) Delete(ctx context.Context, id []byte, deletedBy []byte) error {
	if m.deleteFn != nil {
		return m.deleteFn(ctx, id, deletedBy)
	}
	return nil
}
func (m *reserveAcServiceMock) GetByID(ctx context.Context, id []byte) (*reserveac.ReserveAc, error) {
	if m.getByIDFn != nil {
		return m.getByIDFn(ctx, id)
	}
	return nil, nil
}
func (m *reserveAcServiceMock) GetActiveByInspectionID(ctx context.Context, inspectionID []byte) (*reserveac.ReserveAc, error) {
	if m.getActiveByInspFn != nil {
		return m.getActiveByInspFn(ctx, inspectionID)
	}
	return nil, nil
}
func (m *reserveAcServiceMock) List(ctx context.Context, filter string, sort string, limit, offset int) ([]reserveac.ReserveAc, int64, error) {
	if m.listFn != nil {
		return m.listFn(ctx, filter, sort, limit, offset)
	}
	return nil, 0, nil
}
func (m *reserveAcServiceMock) AircraftExists(ctx context.Context, helicopterID []byte) (bool, error) {
	if m.aircraftExistsFn != nil {
		return m.aircraftExistsFn(ctx, helicopterID)
	}
	return true, nil
}
func (m *reserveAcServiceMock) FlightInspectionExists(context.Context, []byte) (bool, error) {
	return true, nil
}
func (m *reserveAcServiceMock) ExistsActiveByInspectionID(context.Context, []byte, []byte) (bool, error) {
	return false, nil
}
func (m *reserveAcServiceMock) GetLastDailyInspectionByHelicopterID(context.Context, []byte) (*shareddto.LastDailyInspection, error) {
	return nil, nil
}

type fileStorageMock struct{}

func (fileStorageMock) PresignGetObject(_ context.Context, objectKey string, _ time.Duration) (string, error) {
	return "https://example.com/" + objectKey, nil
}

func TestReserveAcHandler_BasicHelpers(t *testing.T) {
	svc := &reserveAcServiceMock{}
	h := NewReserveAcHandler(svc)
	if h == nil || h.validate == nil {
		t.Fatal("handler not initialized")
	}

	if got := h.WithFileStorage(fileStorageMock{}); got != h {
		t.Fatal("expected fluent API to return same handler")
	}

	if !hasReserveAcBeforePayload(requestdto.ReserveAcBeforeInspectionAttributes{FuelAmount: ptrFloat(1)}) {
		t.Fatal("expected before payload detected")
	}
	if hasReserveAcBeforePayload(requestdto.ReserveAcBeforeInspectionAttributes{}) {
		t.Fatal("expected empty before payload false")
	}
	if !hasReserveAcPreparePayload(requestdto.ReserveAcPrepareInspectionAttributes{NotamBriefing: ptrBool(true)}) {
		t.Fatal("expected prepare payload detected")
	}
	if hasReserveAcPreparePayload(requestdto.ReserveAcPrepareInspectionAttributes{}) {
		t.Fatal("expected empty prepare payload false")
	}

	flightID := " abc "
	gotID, ptr, ok := reserveAcUpdateFlightInput(requestdto.ReserveAcUpdateAttributes{FlightID: &flightID})
	if !ok || gotID != "abc" || ptr != "/data/attributes/flight_id" {
		t.Fatalf("unexpected update flight result: %q %q %v", gotID, ptr, ok)
	}
	_, _, ok = reserveAcUpdateFlightInput(requestdto.ReserveAcUpdateAttributes{})
	if ok {
		t.Fatal("expected no flight update")
	}
}

func TestReserveAcHandler_ResourceAndStatusHelpers(t *testing.T) {
	row := &reserveac.ReserveAc{
		ID:         uuidv7.MustBytes(),
		AircraftID: uuidv7.MustBytes(),
		Status:     reserveac.StatusPending,
		CreatedAt:  time.Now().UTC(),
		UpdatedAt:  time.Now().UTC(),
	}
	res := reserveAcResource(row, reserveAcResourceOptions{})
	if res.Type != "reserve_ac" {
		t.Fatalf("unexpected type %q", res.Type)
	}

	nilDaily := reserveAcLastDailyInfo(nil)
	if nilDaily == nil || nilDaily.Name != "" {
		t.Fatal("unexpected nil last daily conversion")
	}
	nonNil := reserveAcLastDailyInfo(&shareddto.LastDailyInspection{Name: " Test ", ShortName: " D ", At: time.Date(2026, 5, 6, 9, 30, 0, 0, time.UTC)})
	if nonNil.Name != "Test" || nonNil.ShortName != "D" {
		t.Fatal("unexpected trim result")
	}

	items := toAfterFlightChecklistItems([]shareddto.ReserveAcFileChecklistItemDTO{{HelicopterFileID: "x", FileName: "f", DownloadURL: "u", IsDone: true}})
	if len(items) != 1 || !items[0].IsDone {
		t.Fatal("unexpected checklist map")
	}
	empty := toAfterFlightChecklistItems(nil)
	if len(empty) != 0 {
		t.Fatal("expected empty array")
	}

	payload := afterFlightInspectionPayload(uuidv7.MustBytes(), &flightinspection.FlightInspection{ID: uuidv7.MustBytes()}, &responsedto.HelicopterResource{Type: "helicopter", ID: "heli-1"}, &afterflightinspection.AfterFlightInspection{
		ID:        uuidv7.MustBytes(),
		CreatedAt: time.Now().UTC(),
		UpdatedAt: time.Now().UTC(),
	}, reserveAcChecklistSectionCommon{Total: 1, Completed: 1}, &afterFlightInspectionSummary{MissionCode: "M-123", TotalFlight: 4, FlightDataCount: 2})
	if payload.Data.Type != "after_flight_inspection" {
		t.Fatal("unexpected payload type")
	}
	if payload.Data.Attributes.MissionCode != "M-123" || payload.Data.Attributes.TotalFlight != 4 || payload.Data.Attributes.FlightDataCount != 2 {
		t.Fatal("unexpected flight summary payload")
	}
	if payload.Data.Attributes.Helicopter == nil || payload.Data.Attributes.Helicopter.ID != "heli-1" {
		t.Fatal("unexpected helicopter payload")
	}

	h := NewReserveAcHandler(&reserveAcServiceMock{})
	if got := h.calculateReserveAcStatus(nil); got != reserveac.StatusPending {
		t.Fatalf("expected pending, got %s", got)
	}
	if got := h.calculateReserveAcStatus(&shareddto.ReserveAcInspectionSummary{
		Before:  shareddto.ReserveAcBeforeSectionDTO{Total: 2, Completed: 1},
		Prepare: shareddto.ReserveAcPrepareSectionDTO{Total: 0, Completed: 0},
	}); got != reserveac.StatusOnProgress {
		t.Fatalf("expected on_progress, got %s", got)
	}
}

func TestReserveAcHandler_BuildAfterFlightInspectionSummaryRoute(t *testing.T) {
	reserveAcID := uuidv7.MustBytes()
	flightID := uuidv7.MustBytes()
	flightDataOneID := uuidv7.MustBytes()
	flightDataTwoID := uuidv7.MustBytes()
	missionCode := "M-060326-001"

	h := NewReserveAcHandler(&reserveAcServiceMock{})
	h.flight = &reserveFlightServiceMock{
		getByReserveAcFn: func(context.Context, []byte) (*flight.Flight, error) {
			return &flight.Flight{ID: flightID, MissionCode: &missionCode}, nil
		},
	}
	h.mission = reserveMissionServiceMock{
		listByFlightIDFn: func(_ context.Context, _ []byte) ([]mission.Mission, error) {
			return []mission.Mission{
				{ID: uuidv7.MustBytes(), FlightID: flightID, FlightDataID: flightDataOneID, Type: "HEMS"},
				{ID: uuidv7.MustBytes(), FlightID: flightID, FlightDataID: flightDataTwoID, Type: "HEMS"},
			}, nil
		},
	}
	h.flightData = reserveFlightDataServiceMock{
		getByIDFn: func(_ context.Context, id []byte) (*flightdata.FlightData, error) {
			switch string(id) {
			case string(flightDataOneID):
				takeoff := time.Date(2026, 6, 8, 8, 0, 0, 0, time.UTC)
				landing := takeoff.Add(10 * time.Minute)
				return &flightdata.FlightData{
					ID:            flightDataOneID,
					FromHospital:  &hospitaldomain.Hospital{ID: uuidv7.MustBytes(), Name: "A"},
					ToICAO:        &icaodomain.ICAO{ID: uuidv7.MustBytes(), ICAOCode: "B"},
					FlightTakeOff: takeoff,
					FlightLanding: landing,
				}, nil
			case string(flightDataTwoID):
				takeoff := time.Date(2026, 6, 8, 8, 20, 0, 0, time.UTC)
				landing := takeoff.Add(15 * time.Minute)
				return &flightdata.FlightData{
					ID:            flightDataTwoID,
					FromICAO:      &icaodomain.ICAO{ID: uuidv7.MustBytes(), ICAOCode: "B"},
					ToHospital:    &hospitaldomain.Hospital{ID: uuidv7.MustBytes(), Name: "C"},
					FlightTakeOff: takeoff,
					FlightLanding: landing,
				}, nil
			default:
				return nil, nil
			}
		},
	}

	summary := h.buildAfterFlightInspectionSummary(context.Background(), &reserveac.ReserveAc{ID: reserveAcID})
	if summary == nil {
		t.Fatal("expected summary")
	}
	if summary.MissionCode != missionCode {
		t.Fatalf("unexpected mission code: %q", summary.MissionCode)
	}
	if summary.FlightDataCount != 2 {
		t.Fatalf("expected flight data count 2, got %d", summary.FlightDataCount)
	}
	if summary.FlightTimeSeconds != int64(25*time.Minute/time.Second) {
		t.Fatalf("unexpected flight time seconds: got %d", summary.FlightTimeSeconds)
	}
	if !reflect.DeepEqual(summary.MissionType, []string{"HEMS"}) {
		t.Fatalf("unexpected mission types: got %#v", summary.MissionType)
	}
	wantRoute := []string{"A", "B", "C"}
	if !reflect.DeepEqual(summary.Route, wantRoute) {
		t.Fatalf("unexpected route: got %#v want %#v", summary.Route, wantRoute)
	}

	payload := afterFlightInspectionPayload(reserveAcID, nil, nil, nil, reserveAcChecklistSectionCommon{}, summary)
	if !reflect.DeepEqual(payload.Data.Attributes.MissionType, []string{"HEMS"}) {
		t.Fatalf("unexpected payload mission types: got %#v", payload.Data.Attributes.MissionType)
	}
	if payload.Data.Attributes.FlightTimeSeconds != int64(25*time.Minute/time.Second) {
		t.Fatalf("unexpected payload flight time seconds: got %d", payload.Data.Attributes.FlightTimeSeconds)
	}
	if !reflect.DeepEqual(payload.Data.Attributes.Route, wantRoute) {
		t.Fatalf("unexpected payload route: got %#v want %#v", payload.Data.Attributes.Route, wantRoute)
	}
}

func TestReserveAcHandler_DeleteAndListValidation(t *testing.T) {
	svc := &reserveAcServiceMock{
		listFn: func(_ context.Context, _, _ string, _, _ int) ([]reserveac.ReserveAc, int64, error) {
			return []reserveac.ReserveAc{{ID: uuidv7.MustBytes(), AircraftID: uuidv7.MustBytes(), Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}}, 1, nil
		},
	}
	h := NewReserveAcHandler(svc)
	app := fiber.New()
	app.Delete("/reserve/:id", h.Delete)
	app.Get("/reserve", h.List)

	req, _ := http.NewRequest(http.MethodDelete, "/reserve/bad", nil)
	res, err := app.Test(req)
	if err != nil {
		t.Fatal(err)
	}
	if res.StatusCode != http.StatusBadRequest {
		t.Fatalf("expected 400, got %d", res.StatusCode)
	}

	u := uuidv7.MustNew()
	id, _ := uuidv7.String(u)
	req, _ = http.NewRequest(http.MethodDelete, "/reserve/"+id, nil)
	res, err = app.Test(req)
	if err != nil {
		t.Fatal(err)
	}
	if res.StatusCode != http.StatusBadRequest {
		t.Fatalf("expected 400, got %d", res.StatusCode)
	}

	req, _ = http.NewRequest(http.MethodGet, "/reserve?page[number]=2&page[size]=5&sort=created_at&filter[search]=x", nil)
	res, err = app.Test(req)
	if err != nil {
		t.Fatal(err)
	}
	if res.StatusCode != http.StatusUnauthorized {
		t.Fatalf("expected 401, got %d", res.StatusCode)
	}
}

func TestReserveAcHandler_ChecklistBuilderHelpers(t *testing.T) {
	h := NewReserveAcHandler(&reserveAcServiceMock{})

	fileID := uuidv7.MustBytes()
	attachmentID := uuidv7.MustBytes()
	files := []helicopterfile.HelicopterFile{{ID: fileID}, {ID: attachmentID}}

	out := h.buildChecklistSectionSummary(&fiber.Ctx{}, files, map[string]bool{idString(fileID): true})
	if out.Total != 2 || out.Completed != 1 || len(out.DoneFiles) != 1 {
		t.Fatal("unexpected checklist summary")
	}

	_ = flightinspectionfilechecklist.FlightInspectionFileChecklist{}
}

func TestReserveAcHandler_ChecklistBuilderHidesTemplateDerivedFiles(t *testing.T) {
	h := NewReserveAcHandler(&reserveAcServiceMock{})

	visibleID := uuidv7.MustBytes()
	derivedID := uuidv7.MustBytes()
	files := []helicopterfile.HelicopterFile{
		{ID: visibleID},
		{
			ID: derivedID,
			SourceFile: &filemanager.File{
				TemplateUUID: uuidv7.MustBytes(),
			},
		},
	}

	out := h.buildChecklistSectionSummary(&fiber.Ctx{}, files, map[string]bool{idString(visibleID): true, idString(derivedID): true})
	if out.Total != 1 || out.Completed != 1 || len(out.FileChecklist) != 1 || len(out.DoneFiles) != 1 {
		t.Fatalf("unexpected filtered checklist summary: %#v", out)
	}
	if out.FileChecklist[0].HelicopterFileID != idString(visibleID) {
		t.Fatalf("expected only visible file in checklist, got %#v", out.FileChecklist[0])
	}
}

func ptrBool(v bool) *bool        { return &v }
func ptrFloat(v float64) *float64 { return &v }

type reserveFlightServiceMock struct {
	getByIDFn        func(context.Context, []byte) (*flight.Flight, error)
	getByReserveAcFn func(context.Context, []byte) (*flight.Flight, error)
	updateFn         func(context.Context, *flight.Flight) error
}

func (m *reserveFlightServiceMock) Create(context.Context, *flight.Flight) error { return nil }
func (m *reserveFlightServiceMock) Update(ctx context.Context, row *flight.Flight) error {
	if m.updateFn != nil {
		return m.updateFn(ctx, row)
	}
	return nil
}
func (m *reserveFlightServiceMock) Delete(context.Context, []byte, []byte) error { return nil }
func (m *reserveFlightServiceMock) GetByID(ctx context.Context, id []byte) (*flight.Flight, error) {
	if m.getByIDFn != nil {
		return m.getByIDFn(ctx, id)
	}
	return nil, nil
}
func (m *reserveFlightServiceMock) ListByUserID(context.Context, []byte, int, int) ([]flight.Flight, int64, error) {
	return nil, 0, nil
}
func (m *reserveFlightServiceMock) ListByCreatedBy(context.Context, []byte, string, string, string, int, int) ([]flight.Flight, int64, error) {
	return nil, 0, nil
}
func (m *reserveFlightServiceMock) GetByReserveAcID(ctx context.Context, reserveAcID []byte) (*flight.Flight, error) {
	if m.getByReserveAcFn != nil {
		return m.getByReserveAcFn(ctx, reserveAcID)
	}
	return nil, nil
}
func (m *reserveFlightServiceMock) ListByReserveAcID(context.Context, []byte) ([]flight.Flight, error) {
	return nil, nil
}
func (m *reserveFlightServiceMock) GetByTakeoverAcID(context.Context, []byte) (*flight.Flight, error) {
	return nil, nil
}
func (m *reserveFlightServiceMock) ListByTakeoverAcIDs(context.Context, [][]byte) ([]flight.Flight, error) {
	return nil, nil
}
func (m *reserveFlightServiceMock) GetByDutyRosterID(context.Context, []byte) (*flight.Flight, error) {
	return nil, nil
}
func (m *reserveFlightServiceMock) ListByDutyRosterIDs(context.Context, [][]byte) ([]flight.Flight, error) {
	return nil, nil
}
func (m *reserveFlightServiceMock) List(context.Context, string, string, string, int, int) ([]flight.Flight, int64, error) {
	return nil, 0, nil
}

type reserveMissionServiceMock struct {
	listByFlightIDFn  func(context.Context, []byte) ([]mission.Mission, error)
	listByFlightIDsFn func(context.Context, [][]byte) ([]mission.Mission, error)
}

func (reserveMissionServiceMock) Create(context.Context, *mission.Mission) error { return nil }
func (reserveMissionServiceMock) CreateType(context.Context, *mission.MissionCategory) error {
	return nil
}
func (reserveMissionServiceMock) UpdateByID(context.Context, []byte, string, []byte, string, []byte) error {
	return nil
}
func (reserveMissionServiceMock) DeleteByID(context.Context, []byte, []byte) error       { return nil }
func (reserveMissionServiceMock) DeleteByFlightID(context.Context, []byte, []byte) error { return nil }
func (reserveMissionServiceMock) AttachFile(context.Context, []byte, []byte) error       { return nil }
func (reserveMissionServiceMock) DetachFile(context.Context, []byte, []byte) error       { return nil }
func (m reserveMissionServiceMock) ListByFlightID(ctx context.Context, flightID []byte) ([]mission.Mission, error) {
	if m.listByFlightIDFn != nil {
		return m.listByFlightIDFn(ctx, flightID)
	}
	return nil, nil
}
func (m reserveMissionServiceMock) ListByFlightIDs(ctx context.Context, flightIDs [][]byte) ([]mission.Mission, error) {
	if m.listByFlightIDsFn != nil {
		return m.listByFlightIDsFn(ctx, flightIDs)
	}
	return nil, nil
}
func (reserveMissionServiceMock) GetByID(context.Context, []byte) (*mission.Mission, error) {
	return nil, nil
}
func (reserveMissionServiceMock) GetByFlightID(context.Context, []byte) (*mission.Mission, error) {
	return nil, nil
}
func (reserveMissionServiceMock) List(context.Context, string, string, []byte, string, int, int) ([]mission.Mission, int64, error) {
	return nil, 0, nil
}
func (reserveMissionServiceMock) ListDatatable(context.Context, mission.ListFilter, int, int) ([]mission.Mission, int64, int64, error) {
	return nil, 0, 0, nil
}
func (reserveMissionServiceMock) ListTypes(context.Context) ([]mission.MissionCategory, error) {
	return nil, nil
}

type reserveFlightDataServiceMock struct {
	getByIDFn        func(context.Context, []byte) (*flightdata.FlightData, error)
	getByMissionIDFn func(context.Context, []byte) (*flightdata.FlightData, error)
}

func (reserveFlightDataServiceMock) Create(context.Context, *flightdata.FlightData) error {
	return nil
}
func (reserveFlightDataServiceMock) CreatePlaceholder(context.Context, *flightdata.FlightData) error {
	return nil
}
func (reserveFlightDataServiceMock) Update(context.Context, *flightdata.FlightData) error {
	return nil
}
func (reserveFlightDataServiceMock) Delete(context.Context, []byte, []byte) error { return nil }
func (m reserveFlightDataServiceMock) GetByID(ctx context.Context, id []byte) (*flightdata.FlightData, error) {
	if m.getByIDFn != nil {
		return m.getByIDFn(ctx, id)
	}
	return nil, nil
}
func (reserveFlightDataServiceMock) GetByFlightID(context.Context, []byte) (*flightdata.FlightData, error) {
	return nil, nil
}
func (m reserveFlightDataServiceMock) GetByMissionID(ctx context.Context, id []byte) (*flightdata.FlightData, error) {
	if m.getByMissionIDFn != nil {
		return m.getByMissionIDFn(ctx, id)
	}
	return nil, nil
}
func (reserveFlightDataServiceMock) ListByMissionID(context.Context, []byte) ([]flightdata.FlightData, error) {
	return nil, nil
}
func (reserveFlightDataServiceMock) List(context.Context, string, []byte, []byte, int, int) ([]flightdata.FlightData, int64, error) {
	return nil, 0, nil
}
func (reserveFlightDataServiceMock) GetSPODetailsByFlightDataID(context.Context, []byte) (*flightdata.SPODetails, error) {
	return nil, nil
}
func (reserveFlightDataServiceMock) UpsertSPODetails(context.Context, []byte, *flightdata.SPOUpsertData) error {
	return nil
}

type inspectionServiceMock struct {
	createDraftFn func(context.Context, *flightinspection.FlightInspection) error
	updateFn      func(context.Context, *flightinspection.FlightInspection) error
	getByIDFn     func(context.Context, []byte) (*flightinspection.FlightInspection, error)
}

func (m *inspectionServiceMock) CreateDraft(ctx context.Context, row *flightinspection.FlightInspection) error {
	if m.createDraftFn != nil {
		return m.createDraftFn(ctx, row)
	}
	row.ID = uuidv7.MustBytes()
	return nil
}
func (m *inspectionServiceMock) Update(ctx context.Context, row *flightinspection.FlightInspection) error {
	if m.updateFn != nil {
		return m.updateFn(ctx, row)
	}
	return nil
}
func (m *inspectionServiceMock) GetByID(ctx context.Context, id []byte) (*flightinspection.FlightInspection, error) {
	if m.getByIDFn != nil {
		return m.getByIDFn(ctx, id)
	}
	return nil, nil
}
func (m *inspectionServiceMock) List(context.Context, string, int, int) ([]flightinspection.FlightInspection, int64, error) {
	return nil, 0, nil
}

type beforeServiceMock struct{}

func (beforeServiceMock) Upsert(context.Context, []byte, *beforeflightinspection.UpsertRequest) (*beforeflightinspection.BeforeFlightInspection, error) {
	return &beforeflightinspection.BeforeFlightInspection{}, nil
}
func (beforeServiceMock) GetByFlightInspectionID(context.Context, []byte) (*beforeflightinspection.BeforeFlightInspection, error) {
	return nil, nil
}

type beforeServiceFnMock struct {
	upsertFn func(context.Context, []byte, *beforeflightinspection.UpsertRequest) (*beforeflightinspection.BeforeFlightInspection, error)
}

func (m beforeServiceFnMock) Upsert(ctx context.Context, id []byte, req *beforeflightinspection.UpsertRequest) (*beforeflightinspection.BeforeFlightInspection, error) {
	if m.upsertFn != nil {
		return m.upsertFn(ctx, id, req)
	}
	return &beforeflightinspection.BeforeFlightInspection{}, nil
}
func (beforeServiceFnMock) GetByFlightInspectionID(context.Context, []byte) (*beforeflightinspection.BeforeFlightInspection, error) {
	return nil, nil
}

type prepServiceMock struct{}

func (prepServiceMock) InitializeChecks(context.Context, []byte) (int, error) { return 0, nil }
func (prepServiceMock) GetByFlightInspection(context.Context, []byte) (*flightprepcheck.FlightPrepCheck, error) {
	return nil, nil
}
func (prepServiceMock) UpdateCheck(context.Context, []byte, *flightprepcheck.UpsertRequest) (*flightprepcheck.FlightPrepCheck, error) {
	return nil, nil
}
func (prepServiceMock) UpsertByFlightInspection(context.Context, []byte, *flightprepcheck.UpsertRequest) (*flightprepcheck.FlightPrepCheck, error) {
	return &flightprepcheck.FlightPrepCheck{}, nil
}

type prepServiceFnMock struct {
	initFn   func(context.Context, []byte) (int, error)
	upsertFn func(context.Context, []byte, *flightprepcheck.UpsertRequest) (*flightprepcheck.FlightPrepCheck, error)
}

func (m prepServiceFnMock) InitializeChecks(ctx context.Context, id []byte) (int, error) {
	if m.initFn != nil {
		return m.initFn(ctx, id)
	}
	return 0, nil
}
func (prepServiceFnMock) GetByFlightInspection(context.Context, []byte) (*flightprepcheck.FlightPrepCheck, error) {
	return nil, nil
}
func (prepServiceFnMock) UpdateCheck(context.Context, []byte, *flightprepcheck.UpsertRequest) (*flightprepcheck.FlightPrepCheck, error) {
	return nil, nil
}
func (m prepServiceFnMock) UpsertByFlightInspection(ctx context.Context, id []byte, req *flightprepcheck.UpsertRequest) (*flightprepcheck.FlightPrepCheck, error) {
	if m.upsertFn != nil {
		return m.upsertFn(ctx, id, req)
	}
	return &flightprepcheck.FlightPrepCheck{}, nil
}

type afterServiceMock struct {
	getFn    func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error)
	upsertFn func(context.Context, []byte, *afterflightinspection.UpsertRequest) (*afterflightinspection.AfterFlightInspection, error)
	delFn    func(context.Context, []byte) error
}

func (m *afterServiceMock) Upsert(ctx context.Context, id []byte, req *afterflightinspection.UpsertRequest) (*afterflightinspection.AfterFlightInspection, error) {
	if m.upsertFn != nil {
		return m.upsertFn(ctx, id, req)
	}
	return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
}
func (m *afterServiceMock) GetByFlightInspectionID(ctx context.Context, id []byte) (*afterflightinspection.AfterFlightInspection, error) {
	if m.getFn != nil {
		return m.getFn(ctx, id)
	}
	return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
}
func (m *afterServiceMock) DeleteByFlightInspectionID(ctx context.Context, id []byte) error {
	if m.delFn != nil {
		return m.delFn(ctx, id)
	}
	return nil
}

type heliFileServiceMock struct {
	listBySectionFn func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error)
}

func (heliFileServiceMock) Create(context.Context, *helicopterfile.HelicopterFile) error { return nil }
func (heliFileServiceMock) Update(context.Context, *helicopterfile.HelicopterFile) error { return nil }
func (heliFileServiceMock) Delete(context.Context, []byte) error                         { return nil }
func (heliFileServiceMock) GetByID(context.Context, []byte) (*helicopterfile.HelicopterFile, error) {
	return nil, nil
}
func (heliFileServiceMock) List(context.Context, string, string, int, int) ([]helicopterfile.HelicopterFile, int64, error) {
	return nil, 0, nil
}
func (heliFileServiceMock) ListByHelicopter(context.Context, []byte) ([]helicopterfile.HelicopterFile, error) {
	return nil, nil
}
func (m heliFileServiceMock) ListByHelicopterAndSection(ctx context.Context, id []byte, section string) ([]helicopterfile.HelicopterFile, error) {
	if m.listBySectionFn != nil {
		return m.listBySectionFn(ctx, id, section)
	}
	return nil, nil
}
func (heliFileServiceMock) HelicopterExists(context.Context, []byte) (bool, error) { return true, nil }
func (heliFileServiceMock) AttachmentExists(context.Context, []byte) (bool, error) { return true, nil }
func (heliFileServiceMock) RequestUploadIntentsBulk(context.Context, []helicopterfile.UploadIntentBulkInput, []byte) []helicopterfile.UploadIntentBulkItemResult {
	return nil
}
func (heliFileServiceMock) CreateFromUploadIntentsBulk(context.Context, []helicopterfile.CreateBulkInput, []byte) []helicopterfile.CreateBulkItemResult {
	return nil
}

type fileChecklistServiceMock struct {
	listByInspectionFn func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error)
	createFn           func(context.Context, *flightinspectionfilechecklist.FlightInspectionFileChecklist) error
	updateFn           func(context.Context, *flightinspectionfilechecklist.FlightInspectionFileChecklist) error
	deleteFn           func(context.Context, []byte) error
}

func (m fileChecklistServiceMock) Create(ctx context.Context, row *flightinspectionfilechecklist.FlightInspectionFileChecklist) error {
	if m.createFn != nil {
		return m.createFn(ctx, row)
	}
	return nil
}
func (m fileChecklistServiceMock) Update(ctx context.Context, row *flightinspectionfilechecklist.FlightInspectionFileChecklist) error {
	if m.updateFn != nil {
		return m.updateFn(ctx, row)
	}
	return nil
}
func (m fileChecklistServiceMock) Delete(ctx context.Context, id []byte) error {
	if m.deleteFn != nil {
		return m.deleteFn(ctx, id)
	}
	return nil
}
func (fileChecklistServiceMock) GetByID(context.Context, []byte) (*flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
	return nil, nil
}
func (fileChecklistServiceMock) List(context.Context, string, string, int, int) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, int64, error) {
	return nil, 0, nil
}
func (m fileChecklistServiceMock) ListByInspectionID(ctx context.Context, id []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
	if m.listByInspectionFn != nil {
		return m.listByInspectionFn(ctx, id)
	}
	return nil, nil
}
func (fileChecklistServiceMock) FlightInspectionExists(context.Context, []byte) (bool, error) {
	return true, nil
}
func (fileChecklistServiceMock) HelicopterFileExists(context.Context, []byte) (bool, error) {
	return true, nil
}

type reserveAcHelicopterServiceMock struct{}

func (reserveAcHelicopterServiceMock) Create(context.Context, *helicopter.Helicopter) error {
	return nil
}
func (reserveAcHelicopterServiceMock) Update(context.Context, *helicopter.Helicopter) error {
	return nil
}
func (reserveAcHelicopterServiceMock) ExistsByIdentifier(context.Context, string, []byte) (bool, error) {
	return false, nil
}
func (reserveAcHelicopterServiceMock) ApplySortKeyPatch(*helicopter.Helicopter, helicopter.SortKeyPatch) {
}
func (reserveAcHelicopterServiceMock) Delete(context.Context, []byte) error { return nil }
func (reserveAcHelicopterServiceMock) GetByID(context.Context, []byte) (*helicopter.Helicopter, error) {
	return nil, nil
}
func (reserveAcHelicopterServiceMock) List(context.Context, string, []string, string, int, int, [][]byte) ([]helicopter.Helicopter, int64, error) {
	return nil, 0, nil
}
func (reserveAcHelicopterServiceMock) NextReportNumber(context.Context, []byte) (string, int, error) {
	return "", 0, nil
}
func (reserveAcHelicopterServiceMock) IsInUse(context.Context, []byte) (bool, error) {
	return false, nil
}
func (reserveAcHelicopterServiceMock) InUseByAircraftIDs(context.Context, [][]byte) (map[string]bool, error) {
	return map[string]bool{}, nil
}
func (reserveAcHelicopterServiceMock) ActiveFlightIDByAircraftIDs(context.Context, [][]byte) (map[string][]byte, error) {
	return map[string][]byte{}, nil
}

type reserveAcHelicopterServiceWithGet struct {
	getFn func(context.Context, []byte) (*helicopter.Helicopter, error)
}

func (reserveAcHelicopterServiceWithGet) Create(context.Context, *helicopter.Helicopter) error {
	return nil
}
func (reserveAcHelicopterServiceWithGet) Update(context.Context, *helicopter.Helicopter) error {
	return nil
}
func (reserveAcHelicopterServiceWithGet) ExistsByIdentifier(context.Context, string, []byte) (bool, error) {
	return false, nil
}
func (reserveAcHelicopterServiceWithGet) ApplySortKeyPatch(*helicopter.Helicopter, helicopter.SortKeyPatch) {
}
func (reserveAcHelicopterServiceWithGet) Delete(context.Context, []byte) error { return nil }
func (m reserveAcHelicopterServiceWithGet) GetByID(ctx context.Context, id []byte) (*helicopter.Helicopter, error) {
	if m.getFn != nil {
		return m.getFn(ctx, id)
	}
	return nil, nil
}
func (reserveAcHelicopterServiceWithGet) List(context.Context, string, []string, string, int, int, [][]byte) ([]helicopter.Helicopter, int64, error) {
	return nil, 0, nil
}
func (reserveAcHelicopterServiceWithGet) NextReportNumber(context.Context, []byte) (string, int, error) {
	return "", 0, nil
}
func (reserveAcHelicopterServiceWithGet) IsInUse(context.Context, []byte) (bool, error) {
	return false, nil
}
func (reserveAcHelicopterServiceWithGet) InUseByAircraftIDs(context.Context, [][]byte) (map[string]bool, error) {
	return map[string]bool{}, nil
}
func (reserveAcHelicopterServiceWithGet) ActiveFlightIDByAircraftIDs(context.Context, [][]byte) (map[string][]byte, error) {
	return map[string][]byte{}, nil
}

func TestReserveAcHandler_MethodValidationAndGuards(t *testing.T) {
	svc := &reserveAcServiceMock{}
	h := NewReserveAcHandler(svc)
	app := fiber.New()
	app.Post("/create", h.Create)
	app.Get("/get/:id", h.Get)
	app.Get("/get-after/:inspection_id", h.GetAfterFlightInspection)
	app.Post("/upsert-after/:inspection_id", h.UpsertAfterFlightInspection)
	app.Get("/last", h.GetLastFlightsInspection)
	app.Post("/last", h.CreateLastFlightsInspection)
	app.Patch("/last", h.UpdateLastFlightsInspection)
	app.Delete("/last", h.DeleteLastFlightsInspection)
	app.Patch("/update/:id", h.Update)

	cases := []struct {
		method, path, body string
		want               int
	}{
		{http.MethodPost, "/create", "{bad", 400},
		{http.MethodGet, "/get/bad", "", 422},
		{http.MethodGet, "/get-after/bad", "", 422},
		{http.MethodPost, "/upsert-after/bad", `{}`, 422},
		{http.MethodGet, "/last?inspection_id=bad", "", 422},
		{http.MethodPost, "/last", "{bad", 500},
		{http.MethodPatch, "/last", "{bad", 500},
		{http.MethodDelete, "/last", "{bad", 400},
		{http.MethodPatch, "/update/bad", `{"data":{"type":"reserve_ac_update","id":"bad","attributes":{"helicopter_id":"x"}}}`, 422},
	}
	for _, tc := range cases {
		req, _ := http.NewRequest(tc.method, tc.path, strings.NewReader(tc.body))
		req.Header.Set("Content-Type", "application/json")
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		if res.StatusCode != tc.want {
			t.Fatalf("%s %s expected %d got %d", tc.method, tc.path, tc.want, res.StatusCode)
		}
	}

	id := uuidv7.MustBytes()
	idStr, _ := uuidv7.BytesToString(id)
	createBody := `{"data":{"type":"reserve_ac_create","attributes":{"helicopter_id":"` + idStr + `","flight_id":"` + idStr + `","inspection":{"inspection_date":"2026-05-06","before":{"fuel_amount":1},"prepare":{"notam_briefing":true}}}}}`
	req, _ := http.NewRequest(http.MethodPost, "/create", strings.NewReader(createBody))
	req.Header.Set("Content-Type", "application/json")
	res, _ := app.Test(req)
	if res.StatusCode != 500 {
		t.Fatalf("expected 500 when service not configured, got %d", res.StatusCode)
	}

	h.after = &afterServiceMock{}
	req, _ = http.NewRequest(http.MethodPatch, "/last", strings.NewReader(`{"data":{"type":"last_flights_inspection_update","attributes":{"flight_inspection_id":"`+idStr+`"}}}`))
	req.Header.Set("Content-Type", "application/json")
	_, _ = app.Test(req)
}

func TestReserveAcHandler_WithMethodsAndErrorBranches(t *testing.T) {
	h := NewReserveAcHandler(&reserveAcServiceMock{})
	h.WithFlightService(&reserveFlightServiceMock{}).
		WithHelicopterService(reserveAcHelicopterServiceMock{}).
		WithFlightInspectionService(&inspectionServiceMock{}).
		WithBeforeFlightInspectionService(beforeServiceMock{}).
		WithFlightPrepCheckService(prepServiceMock{}).
		WithAfterFlightInspectionService(&afterServiceMock{}).
		WithHelicopterFileService(heliFileServiceMock{}).
		WithFlightInspectionFileChecklistService(fileChecklistServiceMock{})

	app := fiber.New()
	app.Get("/after/:inspection_id", h.GetAfterFlightInspection)
	app.Post("/after/:inspection_id", h.UpsertAfterFlightInspection)

	id := uuidv7.MustBytes()
	idStr, _ := uuidv7.BytesToString(id)
	req, _ := http.NewRequest(http.MethodGet, "/after/"+idStr, nil)
	res, _ := app.Test(req)
	if res.StatusCode != 404 {
		t.Fatalf("expected 404, got %d", res.StatusCode)
	}

	h.svc = &reserveAcServiceMock{
		getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
			return nil, errors.New("boom")
		},
	}
	req, _ = http.NewRequest(http.MethodGet, "/after/"+idStr, nil)
	res, _ = app.Test(req)
	if res.StatusCode != 400 {
		t.Fatalf("expected 400, got %d", res.StatusCode)
	}
}

func TestReserveAcHandler_InternalHelpers(t *testing.T) {
	inspectionID := uuidv7.MustBytes()
	heliID := uuidv7.MustBytes()
	fileID := uuidv7.MustBytes()
	h := NewReserveAcHandler(&reserveAcServiceMock{})
	h.inspect = &inspectionServiceMock{
		getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
			return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Date(2026, 5, 6, 0, 0, 0, 0, time.UTC)}, nil
		},
	}
	h.heliFile = heliFileServiceMock{
		listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
			return []helicopterfile.HelicopterFile{{ID: fileID}}, nil
		},
	}
	h.fileCk = fileChecklistServiceMock{
		listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return []flightinspectionfilechecklist.FlightInspectionFileChecklist{{HelicopterFileID: fileID, IsDone: true}}, nil
		},
	}
	h.before = beforeServiceMock{}
	h.prep = prepServiceMock{}

	app := fiber.New()
	app.Get("/x", func(c *fiber.Ctx) error {
		_, err := h.buildCreateInspectionSummary(c, inspectionID, heliID)
		if err != nil {
			return err
		}
		_, err = h.buildInspectionChecklistSection(c, inspectionID, heliID, helicopterfile.SectionBeforeFirstFlightInspection)
		if err != nil {
			return err
		}
		if v := boolPtr(true); v == nil || !*v {
			t.Fatal("boolPtr failed")
		}
		return c.SendStatus(200)
	})
	req, _ := http.NewRequest(http.MethodGet, "/x", nil)
	res, err := app.Test(req)
	if err != nil || res.StatusCode != 200 {
		t.Fatalf("expected 200, got %v %d", err, res.StatusCode)
	}
}

func TestReserveAcHandler_FileChecklistUpsertAndDelete(t *testing.T) {
	inspectionID := uuidv7.MustBytes()
	heliID := uuidv7.MustBytes()
	fileID := uuidv7.MustBytes()
	h := NewReserveAcHandler(&reserveAcServiceMock{})
	h.heliFile = heliFileServiceMock{
		listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
			return []helicopterfile.HelicopterFile{{ID: fileID}}, nil
		},
	}
	created := 0
	deleted := 0
	h.fileCk = fileChecklistServiceMock{
		listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return []flightinspectionfilechecklist.FlightInspectionFileChecklist{{ID: uuidv7.MustBytes(), HelicopterFileID: fileID, IsDone: false}}, nil
		},
		createFn: func(context.Context, *flightinspectionfilechecklist.FlightInspectionFileChecklist) error {
			created++
			return nil
		},
		updateFn: func(context.Context, *flightinspectionfilechecklist.FlightInspectionFileChecklist) error { return nil },
		deleteFn: func(context.Context, []byte) error { deleted++; return nil },
	}

	fileIDStr, _ := uuidv7.BytesToString(fileID)
	app := fiber.New()
	app.Post("/u", func(c *fiber.Ctx) error {
		if ok, err := h.upsertInspectionFileChecklistSection(c, inspectionID, heliID, helicopterfile.SectionBeforeFirstFlightInspection, []requestdto.ReserveAcFileChecklistItem{
			{HelicopterFileID: fileIDStr, IsDone: true},
		}, "/ptr", nil); err != nil {
			return err
		} else if !ok {
			return nil
		}
		if err := h.deleteInspectionFileChecklistSection(c, inspectionID, heliID, helicopterfile.SectionBeforeFirstFlightInspection); err != nil {
			return err
		}
		return c.SendStatus(200)
	})
	req, _ := http.NewRequest(http.MethodPost, "/u", strings.NewReader(`{}`))
	res, err := app.Test(req)
	if err != nil || res.StatusCode != 200 {
		t.Fatalf("expected 200, got %v %d", err, res.StatusCode)
	}
	if created < 0 || deleted == 0 {
		t.Fatalf("unexpected counters: created=%d deleted=%d", created, deleted)
	}
}

func TestReserveAcHandler_StatusAndAircraftSummaryBranches(t *testing.T) {
	h := NewReserveAcHandler(&reserveAcServiceMock{})
	if !hasReserveAcBeforePayload(requestdto.ReserveAcBeforeInspectionAttributes{FuelUnit: reserveStrPtr("L")}) {
		t.Fatal("expected before payload true for fuel unit")
	}
	if !hasReserveAcBeforePayload(requestdto.ReserveAcBeforeInspectionAttributes{Note: reserveStrPtr("n")}) {
		t.Fatal("expected before payload true for note")
	}

	if got := h.calculateReserveAcStatus(&shareddto.ReserveAcInspectionSummary{
		Before:  shareddto.ReserveAcBeforeSectionDTO{Total: 1, Completed: 0},
		Prepare: shareddto.ReserveAcPrepareSectionDTO{Total: 0, Completed: 0},
	}); got != reserveac.StatusPending {
		t.Fatalf("expected pending, got %s", got)
	}
	if got := h.calculateReserveAcStatus(&shareddto.ReserveAcInspectionSummary{
		Before:  shareddto.ReserveAcBeforeSectionDTO{Total: 1, Completed: 1},
		Prepare: shareddto.ReserveAcPrepareSectionDTO{Total: 1, Completed: 1},
	}); got != reserveac.StatusApproved {
		t.Fatalf("expected approved, got %s", got)
	}
	if got := h.calculateReserveAcStatus(&shareddto.ReserveAcInspectionSummary{
		Before: shareddto.ReserveAcBeforeSectionDTO{
			Fields: &shareddto.ReserveAcBeforeInspectionFields{},
		},
	}); got != reserveac.StatusOnProgress {
		t.Fatalf("expected on_progress, got %s", got)
	}

	aircraftID := uuidv7.MustBytes()
	app := fiber.New()
	app.Get("/x", func(c *fiber.Ctx) error {
		// nil aircraft service
		sum, err := h.buildAircraftSummary(c, aircraftID)
		if err != nil || sum != nil {
			t.Fatalf("expected nil summary, got err=%v sum=%v", err, sum)
		}
		h.aircraft = reserveAcHelicopterServiceWithGet{
			getFn: func(context.Context, []byte) (*helicopter.Helicopter, error) { return nil, errors.New("boom") },
		}
		_, err = h.buildAircraftSummary(c, aircraftID)
		if err == nil {
			t.Fatal("expected error")
		}
		h.aircraft = reserveAcHelicopterServiceWithGet{
			getFn: func(context.Context, []byte) (*helicopter.Helicopter, error) {
				return &helicopter.Helicopter{
					ID:          aircraftID,
					Designation: "D",
					Identifier:  "I",
					Type:        "T",
					AirOnGround: true,
					IsActive:    true,
				}, nil
			},
		}
		sum, err = h.buildAircraftSummary(c, aircraftID)
		if err != nil || sum == nil || sum.ID == "" {
			t.Fatalf("expected aircraft summary, err=%v sum=%+v", err, sum)
		}
		return c.SendStatus(200)
	})
	req, _ := http.NewRequest(http.MethodGet, "/x", nil)
	res, err := app.Test(req)
	if err != nil || res.StatusCode != 200 {
		t.Fatalf("expected 200, got err=%v code=%d", err, res.StatusCode)
	}
}

func reserveStrPtr(v string) *string { return &v }

func TestReserveAcHandler_CreateAndUpdateValidationMatrix(t *testing.T) {
	h := NewReserveAcHandler(&reserveAcServiceMock{})
	app := fiber.New()
	app.Post("/create", h.Create)
	app.Patch("/update/:id", h.Update)

	validUUID := uuidv7.MustBytes()
	validUUIDStr, _ := uuidv7.BytesToString(validUUID)

	createCases := []struct {
		name, body string
		want       int
	}{
		{"bad helicopter uuid", `{"data":{"type":"reserve_ac_create","attributes":{"helicopter_id":"bad","flight_id":"` + validUUIDStr + `","inspection":{"inspection_date":"2026-05-06","before":{"fuel_amount":1},"prepare":{"notam_briefing":true}}}}}`, 422},
		{"bad inspection date", `{"data":{"type":"reserve_ac_create","attributes":{"helicopter_id":"` + validUUIDStr + `","flight_id":"` + validUUIDStr + `","inspection":{"inspection_date":"x","before":{"fuel_amount":1},"prepare":{"notam_briefing":true}}}}}`, 422},
		{"missing before payload", `{"data":{"type":"reserve_ac_create","attributes":{"helicopter_id":"` + validUUIDStr + `","flight_id":"` + validUUIDStr + `","inspection":{"inspection_date":"2026-05-06","before":{},"prepare":{"notam_briefing":true}}}}}`, 422},
		{"missing prepare payload", `{"data":{"type":"reserve_ac_create","attributes":{"helicopter_id":"` + validUUIDStr + `","flight_id":"` + validUUIDStr + `","inspection":{"inspection_date":"2026-05-06","before":{"fuel_amount":1},"prepare":{}}}}}`, 422},
		{"bad flight uuid", `{"data":{"type":"reserve_ac_create","attributes":{"helicopter_id":"` + validUUIDStr + `","flight_id":"bad","inspection":{"inspection_date":"2026-05-06","before":{"fuel_amount":1},"prepare":{"notam_briefing":true}}}}}`, 422},
	}
	for _, tc := range createCases {
		req, _ := http.NewRequest(http.MethodPost, "/create", strings.NewReader(tc.body))
		req.Header.Set("Content-Type", "application/json")
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		if res.StatusCode != tc.want {
			t.Fatalf("%s expected %d got %d", tc.name, tc.want, res.StatusCode)
		}
	}

	updateCases := []struct {
		name, path, body string
		want             int
	}{
		{"id required", "/update/", `{"data":{"type":"reserve_ac_update","attributes":{"helicopter_id":"` + validUUIDStr + `"}}}`, 404},
		{"path-body mismatch", "/update/" + validUUIDStr, `{"data":{"type":"reserve_ac_update","id":"` + mustNewUUIDForReserve(t) + `","attributes":{"helicopter_id":"` + validUUIDStr + `"}}}`, 422},
		{"at least one attr", "/update/" + validUUIDStr, `{"data":{"type":"reserve_ac_update","id":"` + validUUIDStr + `","attributes":{}}}`, 422},
	}
	for _, tc := range updateCases {
		req, _ := http.NewRequest(http.MethodPatch, tc.path, strings.NewReader(tc.body))
		req.Header.Set("Content-Type", "application/json")
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		if res.StatusCode != tc.want {
			t.Fatalf("%s expected %d got %d", tc.name, tc.want, res.StatusCode)
		}
	}
}

func TestReserveAcHandler_UpsertChecklistErrorBranches(t *testing.T) {
	inspectionID := uuidv7.MustBytes()
	heliID := uuidv7.MustBytes()
	fileID := uuidv7.MustBytes()
	fileIDStr, _ := uuidv7.BytesToString(fileID)

	base := NewReserveAcHandler(&reserveAcServiceMock{})
	base.heliFile = heliFileServiceMock{
		listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
			return []helicopterfile.HelicopterFile{{ID: fileID}}, nil
		},
	}
	base.fileCk = fileChecklistServiceMock{
		listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return []flightinspectionfilechecklist.FlightInspectionFileChecklist{}, nil
		},
	}

	app := fiber.New()
	app.Post("/bad-uuid", func(c *fiber.Ctx) error {
		if ok, err := base.upsertInspectionFileChecklistSection(c, inspectionID, heliID, helicopterfile.SectionBeforeFirstFlightInspection, []requestdto.ReserveAcFileChecklistItem{
			{HelicopterFileID: "bad", IsDone: true},
		}, "/p", nil); err != nil {
			return err
		} else if !ok {
			return nil
		}
		return nil
	})
	app.Post("/not-in-template", func(c *fiber.Ctx) error {
		other := uuidv7.MustBytes()
		otherStr, _ := uuidv7.BytesToString(other)
		if ok, err := base.upsertInspectionFileChecklistSection(c, inspectionID, heliID, helicopterfile.SectionBeforeFirstFlightInspection, []requestdto.ReserveAcFileChecklistItem{
			{HelicopterFileID: otherStr, IsDone: true},
		}, "/p", nil); err != nil {
			return err
		} else if !ok {
			return nil
		}
		return nil
	})
	app.Post("/create-failed", func(c *fiber.Ctx) error {
		base.fileCk = fileChecklistServiceMock{
			listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
				return nil, nil
			},
			createFn: func(context.Context, *flightinspectionfilechecklist.FlightInspectionFileChecklist) error {
				return errors.New("boom")
			},
		}
		if ok, err := base.upsertInspectionFileChecklistSection(c, inspectionID, heliID, helicopterfile.SectionBeforeFirstFlightInspection, []requestdto.ReserveAcFileChecklistItem{
			{HelicopterFileID: fileIDStr, IsDone: true},
		}, "/p", nil); err != nil {
			return err
		} else if !ok {
			return nil
		}
		return nil
	})

	for _, path := range []string{"/bad-uuid", "/not-in-template", "/create-failed"} {
		req, _ := http.NewRequest(http.MethodPost, path, strings.NewReader(`{}`))
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		if res.StatusCode != 422 && res.StatusCode != 400 {
			t.Fatalf("%s expected 422/400 got %d", path, res.StatusCode)
		}
	}
}

func mustNewUUIDForReserve(t *testing.T) string {
	t.Helper()
	u := uuidv7.MustNew()
	s, err := uuidv7.String(u)
	if err != nil {
		t.Fatal(err)
	}
	return s
}

func validReserveCreateBody(heliID, flightID string) string {
	return `{"data":{"type":"reserve_ac_create","attributes":{"helicopter_id":"` + heliID + `","flight_id":"` + flightID + `","inspection":{"inspection_date":"2026-05-06","before":{"fuel_amount":1},"prepare":{"notam_briefing":true}}}}}`
}

func TestReserveAcHandler_CreateStepErrors(t *testing.T) {
	heliID := uuidv7.MustBytes()
	flightID := uuidv7.MustBytes()
	heliStr, _ := uuidv7.BytesToString(heliID)
	flightStr, _ := uuidv7.BytesToString(flightID)
	baseFlight := &flight.Flight{ID: flightID}

	newHandler := func() *ReserveAcHandler {
		h := NewReserveAcHandler(&reserveAcServiceMock{
			aircraftExistsFn: func(context.Context, []byte) (bool, error) { return true, nil },
			getByIDFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
				return &reserveac.ReserveAc{ID: uuidv7.MustBytes(), AircraftID: heliID, InspectionID: uuidv7.MustBytes(), Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
			updateFn: func(context.Context, *reserveac.ReserveAc) error { return nil },
		})
		h.flight = &reserveFlightServiceMock{
			getByIDFn: func(context.Context, []byte) (*flight.Flight, error) { return baseFlight, nil },
			updateFn:  func(context.Context, *flight.Flight) error { return nil },
		}
		h.inspect = &inspectionServiceMock{
			createDraftFn: func(_ context.Context, row *flightinspection.FlightInspection) error {
				row.ID = uuidv7.MustBytes()
				return nil
			},
			getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
				return &flightinspection.FlightInspection{ID: uuidv7.MustBytes(), InspectionDate: time.Now().UTC()}, nil
			},
		}
		h.before = beforeServiceMock{}
		h.prep = prepServiceMock{}
		h.heliFile = heliFileServiceMock{listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) { return nil, nil }}
		h.fileCk = fileChecklistServiceMock{listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return nil, nil
		}}
		return h
	}

	cases := []struct {
		name string
		mut  func(*ReserveAcHandler)
		want int
	}{
		{"flight get error", func(h *ReserveAcHandler) {
			h.flight = &reserveFlightServiceMock{getByIDFn: func(context.Context, []byte) (*flight.Flight, error) { return nil, errors.New("x") }}
		}, 400},
		{"flight nil", func(h *ReserveAcHandler) {
			h.flight = &reserveFlightServiceMock{getByIDFn: func(context.Context, []byte) (*flight.Flight, error) { return nil, nil }}
		}, 422},
		{"aircraft exists error", func(h *ReserveAcHandler) {
			h.svc = &reserveAcServiceMock{aircraftExistsFn: func(context.Context, []byte) (bool, error) { return false, errors.New("x") }}
			h.flight = &reserveFlightServiceMock{getByIDFn: func(context.Context, []byte) (*flight.Flight, error) { return baseFlight, nil }}
		}, 400},
		{"aircraft not exists", func(h *ReserveAcHandler) {
			h.svc = &reserveAcServiceMock{aircraftExistsFn: func(context.Context, []byte) (bool, error) { return false, nil }}
			h.flight = &reserveFlightServiceMock{getByIDFn: func(context.Context, []byte) (*flight.Flight, error) { return baseFlight, nil }}
		}, 422},
		{"draft error", func(h *ReserveAcHandler) {
			h.inspect = &inspectionServiceMock{createDraftFn: func(context.Context, *flightinspection.FlightInspection) error { return errors.New("x") }}
		}, 400},
		{"svc create error", func(h *ReserveAcHandler) {
			h.svc = &reserveAcServiceMock{
				aircraftExistsFn: func(context.Context, []byte) (bool, error) { return true, nil },
				createFn:         func(context.Context, *reserveac.ReserveAc) error { return errors.New("x") },
			}
		}, 400},
		{"before upsert error", func(h *ReserveAcHandler) {
			h.before = beforeServiceFnMock{upsertFn: func(context.Context, []byte, *beforeflightinspection.UpsertRequest) (*beforeflightinspection.BeforeFlightInspection, error) {
				return nil, errors.New("x")
			}}
		}, 400},
		{"prep init error", func(h *ReserveAcHandler) {
			h.prep = prepServiceFnMock{initFn: func(context.Context, []byte) (int, error) { return 0, errors.New("x") }}
		}, 400},
		{"prep upsert error", func(h *ReserveAcHandler) {
			h.prep = prepServiceFnMock{upsertFn: func(context.Context, []byte, *flightprepcheck.UpsertRequest) (*flightprepcheck.FlightPrepCheck, error) {
				return nil, errors.New("x")
			}}
		}, 400},
		{"flight update error", func(h *ReserveAcHandler) {
			h.flight = &reserveFlightServiceMock{
				getByIDFn: func(context.Context, []byte) (*flight.Flight, error) { return baseFlight, nil },
				updateFn:  func(context.Context, *flight.Flight) error { return errors.New("x") },
			}
		}, 400},
	}

	for _, tc := range cases {
		h := newHandler()
		tc.mut(h)
		app := fiber.New()
		app.Post("/create", h.Create)
		req, _ := http.NewRequest(http.MethodPost, "/create", strings.NewReader(validReserveCreateBody(heliStr, flightStr)))
		req.Header.Set("Content-Type", "application/json")
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		if res.StatusCode != tc.want {
			t.Fatalf("%s expected %d got %d", tc.name, tc.want, res.StatusCode)
		}
	}
}

func TestReserveAcHandler_UpdateBranchMatrix(t *testing.T) {
	id := uuidv7.MustBytes()
	idStr, _ := uuidv7.BytesToString(id)
	inspectionID := uuidv7.MustBytes()
	aircraftID := uuidv7.MustBytes()
	flightID := uuidv7.MustBytes()
	flightIDStr, _ := uuidv7.BytesToString(flightID)

	newHandler := func() *ReserveAcHandler {
		svc := &reserveAcServiceMock{
			getByIDFn: func(_ context.Context, q []byte) (*reserveac.ReserveAc, error) {
				if string(q) == string(id) {
					return &reserveac.ReserveAc{
						ID:           id,
						AircraftID:   aircraftID,
						InspectionID: inspectionID,
						Status:       reserveac.StatusPending,
						CreatedAt:    time.Now().UTC(),
						UpdatedAt:    time.Now().UTC(),
					}, nil
				}
				return nil, nil
			},
			updateFn:         func(context.Context, *reserveac.ReserveAc) error { return nil },
			aircraftExistsFn: func(context.Context, []byte) (bool, error) { return true, nil },
		}
		h := NewReserveAcHandler(svc)
		h.flight = &reserveFlightServiceMock{
			getByIDFn: func(_ context.Context, q []byte) (*flight.Flight, error) {
				return &flight.Flight{ID: q}, nil
			},
			getByReserveAcFn: func(context.Context, []byte) (*flight.Flight, error) { return nil, nil },
			updateFn:         func(context.Context, *flight.Flight) error { return nil },
		}
		h.inspect = &inspectionServiceMock{
			getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
				return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Now().UTC()}, nil
			},
			updateFn: func(context.Context, *flightinspection.FlightInspection) error { return nil },
		}
		h.before = beforeServiceMock{}
		h.prep = prepServiceMock{}
		h.heliFile = heliFileServiceMock{
			listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) { return nil, nil },
		}
		h.fileCk = fileChecklistServiceMock{
			listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
				return nil, nil
			},
		}
		return h
	}

	run := func(h *ReserveAcHandler, body string) int {
		app := fiber.New()
		app.Patch("/u/:id", h.Update)
		req, _ := http.NewRequest(http.MethodPatch, "/u/"+idStr, strings.NewReader(body))
		req.Header.Set("Content-Type", "application/json")
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		return res.StatusCode
	}

	if got := run(newHandler(), "{bad"); got != 400 {
		t.Fatalf("invalid json expected 400 got %d", got)
	}
	if got := run(newHandler(), `{"data":{"type":"bad_type","id":"`+idStr+`","attributes":{"flight_id":"`+flightIDStr+`"}}}`); got != 422 {
		t.Fatalf("validator expected 422 got %d", got)
	}
	if got := run(newHandler(), `{"data":{"type":"reserve_ac_update","id":"bad","attributes":{"flight_id":"`+flightIDStr+`"}}}`); got != 422 {
		t.Fatalf("id invalid expected 422 got %d", got)
	}
	if got := run(newHandler(), `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{}}}`); got != 422 {
		t.Fatalf("attrs empty expected 422 got %d", got)
	}

	// hasFlight branch coverage
	{
		h := newHandler()
		h.svc = &reserveAcServiceMock{getByIDFn: h.svc.(*reserveAcServiceMock).getByIDFn}
		h.flight = nil
		if got := run(h, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"flight_id":"`+flightIDStr+`"}}}`); got != 500 {
			t.Fatalf("flight nil expected 500 got %d", got)
		}
	}
	{
		h := newHandler()
		h.flight = &reserveFlightServiceMock{getByIDFn: func(context.Context, []byte) (*flight.Flight, error) { return nil, errors.New("x") }}
		if got := run(h, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"flight_id":"`+flightIDStr+`"}}}`); got != 400 {
			t.Fatalf("flight get err expected 400 got %d", got)
		}
	}
	{
		h := newHandler()
		h.flight = &reserveFlightServiceMock{getByIDFn: func(context.Context, []byte) (*flight.Flight, error) { return nil, nil }}
		if got := run(h, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"flight_id":"`+flightIDStr+`"}}}`); got != 422 {
			t.Fatalf("flight nil expected 422 got %d", got)
		}
	}
	{
		h := newHandler()
		h.flight = &reserveFlightServiceMock{
			getByIDFn: func(context.Context, []byte) (*flight.Flight, error) {
				return &flight.Flight{ID: flightID, ReserveAcID: uuidv7.MustBytes()}, nil
			},
		}
		if got := run(h, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"flight_id":"`+flightIDStr+`"}}}`); got != 422 {
			t.Fatalf("flight already has reserve expected 422 got %d", got)
		}
	}
	{
		h := newHandler()
		h.flight = &reserveFlightServiceMock{
			getByIDFn:        func(context.Context, []byte) (*flight.Flight, error) { return &flight.Flight{ID: flightID}, nil },
			getByReserveAcFn: func(context.Context, []byte) (*flight.Flight, error) { return nil, errors.New("x") },
		}
		if got := run(h, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"flight_id":"`+flightIDStr+`"}}}`); got != 400 {
			t.Fatalf("current flight err expected 400 got %d", got)
		}
	}

	// aircraft branch coverage
	{
		h := newHandler()
		if got := run(h, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"helicopter_id":"bad"}}}`); got != 422 {
			t.Fatalf("aircraft parse expected 422 got %d", got)
		}
	}
	{
		h := newHandler()
		h.svc.(*reserveAcServiceMock).aircraftExistsFn = func(context.Context, []byte) (bool, error) { return false, errors.New("x") }
		if got := run(h, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"helicopter_id":"`+idStr+`"}}}`); got != 400 {
			t.Fatalf("aircraft exists err expected 400 got %d", got)
		}
	}
	{
		h := newHandler()
		h.svc.(*reserveAcServiceMock).aircraftExistsFn = func(context.Context, []byte) (bool, error) { return false, nil }
		if got := run(h, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"helicopter_id":"`+idStr+`"}}}`); got != 422 {
			t.Fatalf("aircraft not exists expected 422 got %d", got)
		}
	}

	// inspection branch coverage
	{
		h := newHandler()
		h.inspect = &inspectionServiceMock{getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) { return nil, errors.New("x") }}
		if got := run(h, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"inspection":{"inspection_date":"2026-05-06"}}}}`); got != 400 {
			t.Fatalf("inspection get err expected 400 got %d", got)
		}
	}
	{
		h := newHandler()
		h.inspect = &inspectionServiceMock{getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) { return nil, nil }}
		if got := run(h, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"inspection":{"inspection_date":"2026-05-06"}}}}`); got != 404 {
			t.Fatalf("inspection nil expected 404 got %d", got)
		}
	}
	{
		h := newHandler()
		if got := run(h, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"inspection":{"inspection_date":"bad"}}}}`); got != 422 {
			t.Fatalf("inspection date parse expected 422 got %d", got)
		}
	}
}

func TestReserveAcHandler_UpdateDeepBranches(t *testing.T) {
	id := uuidv7.MustBytes()
	idStr, _ := uuidv7.BytesToString(id)
	inspectionID := uuidv7.MustBytes()
	aircraftID := uuidv7.MustBytes()
	targetFlightID := uuidv7.MustBytes()
	targetFlightStr, _ := uuidv7.BytesToString(targetFlightID)

	makeHandler := func() *ReserveAcHandler {
		h := NewReserveAcHandler(&reserveAcServiceMock{
			getByIDFn: func(_ context.Context, q []byte) (*reserveac.ReserveAc, error) {
				if len(q) == 16 {
					return &reserveac.ReserveAc{ID: id, AircraftID: aircraftID, InspectionID: inspectionID, Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
				}
				return nil, nil
			},
			aircraftExistsFn: func(context.Context, []byte) (bool, error) { return true, nil },
			updateFn:         func(context.Context, *reserveac.ReserveAc) error { return nil },
		})
		h.flight = &reserveFlightServiceMock{
			getByIDFn: func(_ context.Context, q []byte) (*flight.Flight, error) { return &flight.Flight{ID: q}, nil },
			getByReserveAcFn: func(context.Context, []byte) (*flight.Flight, error) {
				return &flight.Flight{ID: uuidv7.MustBytes(), ReserveAcID: id}, nil
			},
			updateFn: func(context.Context, *flight.Flight) error { return nil },
		}
		h.inspect = &inspectionServiceMock{
			getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
				return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Now().UTC()}, nil
			},
			updateFn: func(context.Context, *flightinspection.FlightInspection) error { return nil },
		}
		h.before = beforeServiceMock{}
		h.prep = prepServiceMock{}
		h.heliFile = heliFileServiceMock{listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) { return nil, nil }}
		h.fileCk = fileChecklistServiceMock{listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return nil, nil
		}}
		return h
	}

	run := func(app *fiber.App, path, body string) int {
		req, _ := http.NewRequest(http.MethodPatch, path, strings.NewReader(body))
		req.Header.Set("Content-Type", "application/json")
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		return res.StatusCode
	}

	// pathID empty -> use uuid param
	{
		h := makeHandler()
		app := fiber.New()
		app.Patch("/u/:uuid", h.Update)
		status := run(app, "/u/"+idStr, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"flight_id":"`+targetFlightStr+`"}}}`)
		if status != 200 {
			t.Fatalf("uuid param path expected 200 got %d", status)
		}
	}

	// id required when no path param and no body id
	{
		h := makeHandler()
		app := fiber.New()
		app.Patch("/u", h.Update)
		status := run(app, "/u", `{"data":{"type":"reserve_ac_update","attributes":{"flight_id":"`+targetFlightStr+`"}}}`)
		if status != 422 {
			t.Fatalf("id required expected 422 got %d", status)
		}
	}

	// not found path
	{
		h := makeHandler()
		h.svc = &reserveAcServiceMock{getByIDFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) { return nil, nil }}
		app := fiber.New()
		app.Patch("/u/:id", h.Update)
		status := run(app, "/u/"+idStr, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"flight_id":"`+targetFlightStr+`"}}}`)
		if status != 404 {
			t.Fatalf("not found expected 404 got %d", status)
		}
	}

	// current flight update error branch
	{
		h := makeHandler()
		h.flight = &reserveFlightServiceMock{
			getByIDFn: func(_ context.Context, q []byte) (*flight.Flight, error) { return &flight.Flight{ID: q}, nil },
			getByReserveAcFn: func(context.Context, []byte) (*flight.Flight, error) {
				return &flight.Flight{ID: uuidv7.MustBytes(), ReserveAcID: id}, nil
			},
			updateFn: func(context.Context, *flight.Flight) error { return errors.New("x") },
		}
		app := fiber.New()
		app.Patch("/u/:id", h.Update)
		status := run(app, "/u/"+idStr, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"flight_id":"`+targetFlightStr+`"}}}`)
		if status != 400 {
			t.Fatalf("current flight update err expected 400 got %d", status)
		}
	}

	// inspection update error + before/prepare errors
	{
		h := makeHandler()
		h.inspect = &inspectionServiceMock{
			getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
				return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Now().UTC()}, nil
			},
			updateFn: func(context.Context, *flightinspection.FlightInspection) error { return errors.New("x") },
		}
		app := fiber.New()
		app.Patch("/u/:id", h.Update)
		status := run(app, "/u/"+idStr, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"inspection":{"inspection_date":"2026-05-06"}}}}`)
		if status != 400 {
			t.Fatalf("inspection update err expected 400 got %d", status)
		}
	}
	{
		h := makeHandler()
		h.before = beforeServiceFnMock{upsertFn: func(context.Context, []byte, *beforeflightinspection.UpsertRequest) (*beforeflightinspection.BeforeFlightInspection, error) {
			return nil, errors.New("x")
		}}
		app := fiber.New()
		app.Patch("/u/:id", h.Update)
		status := run(app, "/u/"+idStr, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"inspection":{"before":{"fuel_amount":1}}}}}`)
		if status != 400 {
			t.Fatalf("before upsert err expected 400 got %d", status)
		}
	}
	{
		h := makeHandler()
		h.prep = prepServiceFnMock{upsertFn: func(context.Context, []byte, *flightprepcheck.UpsertRequest) (*flightprepcheck.FlightPrepCheck, error) {
			return nil, errors.New("x")
		}}
		app := fiber.New()
		app.Patch("/u/:id", h.Update)
		status := run(app, "/u/"+idStr, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"inspection":{"prepare":{"notam_briefing":true}}}}}`)
		if status != 400 {
			t.Fatalf("prepare upsert err expected 400 got %d", status)
		}
	}

	// final update error and final fallback response
	{
		h := makeHandler()
		h.svc.(*reserveAcServiceMock).updateFn = func(context.Context, *reserveac.ReserveAc) error { return errors.New("x") }
		app := fiber.New()
		app.Patch("/u/:id", h.Update)
		status := run(app, "/u/"+idStr, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"helicopter_id":"`+idStr+`"}}}`)
		if status != 400 {
			t.Fatalf("svc update err expected 400 got %d", status)
		}
	}
	{
		h := makeHandler()
		calls := 0
		h.svc.(*reserveAcServiceMock).getByIDFn = func(context.Context, []byte) (*reserveac.ReserveAc, error) {
			calls++
			if calls == 1 {
				return &reserveac.ReserveAc{ID: id, AircraftID: aircraftID, InspectionID: inspectionID, Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			}
			return nil, errors.New("fallback")
		}
		app := fiber.New()
		app.Patch("/u/:id", h.Update)
		status := run(app, "/u/"+idStr, `{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"helicopter_id":"`+idStr+`"}}}`)
		if status != 200 {
			t.Fatalf("fallback response expected 200 got %d", status)
		}
	}
}

func TestReserveAcHandler_GetFallbackByFlightID(t *testing.T) {
	reserveID := uuidv7.MustBytes()
	flightID := uuidv7.MustBytes()
	flightIDStr, _ := uuidv7.BytesToString(flightID)
	h := NewReserveAcHandler(&reserveAcServiceMock{
		getByIDFn: func(_ context.Context, id []byte) (*reserveac.ReserveAc, error) {
			if string(id) == string(reserveID) {
				return &reserveac.ReserveAc{ID: reserveID, AircraftID: uuidv7.MustBytes(), InspectionID: uuidv7.MustBytes(), Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			}
			return nil, errors.New("not found")
		},
	})
	h.flight = &reserveFlightServiceMock{
		getByIDFn: func(_ context.Context, id []byte) (*flight.Flight, error) {
			if string(id) == string(flightID) {
				return &flight.Flight{ID: id, ReserveAcID: reserveID}, nil
			}
			return nil, nil
		},
	}
	h.inspect = &inspectionServiceMock{
		getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
			return &flightinspection.FlightInspection{ID: uuidv7.MustBytes(), InspectionDate: time.Now().UTC()}, nil
		},
	}
	h.before = beforeServiceMock{}
	h.prep = prepServiceMock{}
	h.heliFile = heliFileServiceMock{
		listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) { return nil, nil },
	}
	h.fileCk = fileChecklistServiceMock{
		listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return nil, nil
		},
	}
	app := fiber.New()
	app.Get("/get/:id", h.Get)
	req, _ := http.NewRequest(http.MethodGet, "/get/"+flightIDStr, nil)
	res, err := app.Test(req)
	if err != nil {
		t.Fatal(err)
	}
	if res.StatusCode != http.StatusOK {
		t.Fatalf("expected 200, got %d", res.StatusCode)
	}
}

func TestReserveAcHandler_UpdateServiceNilAndBadFlightID(t *testing.T) {
	id := uuidv7.MustBytes()
	idStr, _ := uuidv7.BytesToString(id)
	h := NewReserveAcHandler(&reserveAcServiceMock{
		getByIDFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
			return &reserveac.ReserveAc{ID: id, AircraftID: uuidv7.MustBytes(), InspectionID: uuidv7.MustBytes(), Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
		},
	})
	app := fiber.New()
	app.Patch("/u/:id", h.Update)

	req, _ := http.NewRequest(http.MethodPatch, "/u/"+idStr, strings.NewReader(`{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"flight_id":"`+idStr+`"}}}`))
	req.Header.Set("Content-Type", "application/json")
	res, err := app.Test(req)
	if err != nil {
		t.Fatal(err)
	}
	if res.StatusCode != 500 {
		t.Fatalf("expected 500, got %d", res.StatusCode)
	}

	h.flight = &reserveFlightServiceMock{
		getByIDFn: func(context.Context, []byte) (*flight.Flight, error) { return nil, nil },
	}
	req, _ = http.NewRequest(http.MethodPatch, "/u/"+idStr, strings.NewReader(`{"data":{"type":"reserve_ac_update","id":"`+idStr+`","attributes":{"flight_id":"bad"}}}`))
	req.Header.Set("Content-Type", "application/json")
	res, err = app.Test(req)
	if err != nil {
		t.Fatal(err)
	}
	if res.StatusCode != 422 {
		t.Fatalf("expected 422, got %d", res.StatusCode)
	}
}

func TestReserveAcHandler_AfterFlightEndpointBranches(t *testing.T) {
	inspectionID := uuidv7.MustBytes()
	inspectionIDStr, _ := uuidv7.BytesToString(inspectionID)
	aircraftID := uuidv7.MustBytes()
	fileID := uuidv7.MustBytes()

	t.Run("getAfter service guards", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{})
		app := fiber.New()
		app.Get("/after/:inspection_id", h.GetAfterFlightInspection)

		req, _ := http.NewRequest(http.MethodGet, "/after/"+inspectionIDStr, nil)
		res, _ := app.Test(req)
		if res.StatusCode != 500 {
			t.Fatalf("expected 500, got %d", res.StatusCode)
		}

		h.after = &afterServiceMock{}
		req, _ = http.NewRequest(http.MethodGet, "/after/"+inspectionIDStr, nil)
		res, _ = app.Test(req)
		if res.StatusCode != 500 {
			t.Fatalf("expected 500, got %d", res.StatusCode)
		}
	})

	t.Run("getAfter validation and notfound mapping", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{
			getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
				return &reserveac.ReserveAc{ID: uuidv7.MustBytes(), AircraftID: aircraftID, InspectionID: inspectionID, Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
		})
		h.after = &afterServiceMock{
			getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
				return nil, afterflightinspection.ErrCapabilitiesUnavailable
			},
		}
		h.inspect = &inspectionServiceMock{
			getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
				return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Now().UTC()}, nil
			},
		}
		h.heliFile = heliFileServiceMock{
			listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
				return []helicopterfile.HelicopterFile{{ID: fileID}}, nil
			},
		}
		h.fileCk = fileChecklistServiceMock{
			listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
				return nil, nil
			},
		}
		app := fiber.New()
		app.Get("/after/:inspection_id", h.GetAfterFlightInspection)
		req, _ := http.NewRequest(http.MethodGet, "/after/"+inspectionIDStr, nil)
		res, _ := app.Test(req)
		if res.StatusCode != 422 {
			t.Fatalf("expected 422, got %d", res.StatusCode)
		}
	})

	t.Run("createLast/updateLast/deleteLast branches", func(t *testing.T) {
		fileIDStr, _ := uuidv7.BytesToString(fileID)
		h := NewReserveAcHandler(&reserveAcServiceMock{
			getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
				return &reserveac.ReserveAc{ID: uuidv7.MustBytes(), AircraftID: aircraftID, InspectionID: inspectionID, Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
		})
		h.after = &afterServiceMock{
			getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) { return nil, nil },
			upsertFn: func(context.Context, []byte, *afterflightinspection.UpsertRequest) (*afterflightinspection.AfterFlightInspection, error) {
				return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
			delFn: func(context.Context, []byte) error { return errors.New("del failed") },
		}
		h.inspect = &inspectionServiceMock{
			getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
				return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Now().UTC()}, nil
			},
		}
		h.heliFile = heliFileServiceMock{
			listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
				return []helicopterfile.HelicopterFile{{ID: fileID}}, nil
			},
		}
		h.fileCk = fileChecklistServiceMock{
			listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
				return nil, nil
			},
		}

		app := fiber.New()
		app.Post("/last", h.CreateLastFlightsInspection)
		app.Patch("/last", h.UpdateLastFlightsInspection)
		app.Delete("/last", h.DeleteLastFlightsInspection)

		createBody := `{"data":{"type":"last_flights_inspection_create","attributes":{"flight_inspection_id":"` + inspectionIDStr + `","file_checklist":[{"helicopter_file_id":"` + fileIDStr + `","is_done":true}]}}}`
		req, _ := http.NewRequest(http.MethodPost, "/last", strings.NewReader(createBody))
		req.Header.Set("Content-Type", "application/json")
		res, _ := app.Test(req)
		if res.StatusCode != 200 {
			t.Fatalf("expected 200, got %d", res.StatusCode)
		}

		updateBody := `{"data":{"type":"last_flights_inspection_update","attributes":{"flight_inspection_id":"` + inspectionIDStr + `"}}}`
		req, _ = http.NewRequest(http.MethodPatch, "/last", strings.NewReader(updateBody))
		req.Header.Set("Content-Type", "application/json")
		res, _ = app.Test(req)
		if res.StatusCode != 404 {
			t.Fatalf("expected 404 when existing nil, got %d", res.StatusCode)
		}

		h.after = &afterServiceMock{
			getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
				return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
			delFn: func(context.Context, []byte) error { return errors.New("del failed") },
		}
		deleteBody := `{"data":{"type":"last_flights_inspection_delete","attributes":{"flight_inspection_id":"` + inspectionIDStr + `"}}}`
		req, _ = http.NewRequest(http.MethodDelete, "/last", strings.NewReader(deleteBody))
		req.Header.Set("Content-Type", "application/json")
		res, _ = app.Test(req)
		if res.StatusCode != 400 {
			t.Fatalf("expected 400 delete failure, got %d", res.StatusCode)
		}
	})
}

func TestReserveAcHandler_AfterFlightWrapperValidationBranches(t *testing.T) {
	id := uuidv7.MustBytes()
	idStr, _ := uuidv7.BytesToString(id)

	h := NewReserveAcHandler(&reserveAcServiceMock{
		getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
			return &reserveac.ReserveAc{ID: uuidv7.MustBytes(), AircraftID: uuidv7.MustBytes(), InspectionID: id, Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
		},
	})
	h.after = &afterServiceMock{}
	h.inspect = &inspectionServiceMock{
		getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
			return &flightinspection.FlightInspection{ID: id, InspectionDate: time.Now().UTC()}, nil
		},
	}
	h.heliFile = heliFileServiceMock{listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) { return nil, nil }}
	h.fileCk = fileChecklistServiceMock{listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
		return nil, nil
	}}

	app := fiber.New()
	app.Post("/upsert/:inspection_id", h.UpsertAfterFlightInspection)
	app.Post("/create-last", h.CreateLastFlightsInspection)
	app.Patch("/update-last", h.UpdateLastFlightsInspection)
	app.Delete("/delete-last", h.DeleteLastFlightsInspection)

	// UpsertAfter wrappers
	req, _ := http.NewRequest(http.MethodPost, "/upsert/"+idStr, strings.NewReader("{bad"))
	req.Header.Set("Content-Type", "application/json")
	res, _ := app.Test(req)
	if res.StatusCode != 400 {
		t.Fatalf("expected 400 got %d", res.StatusCode)
	}
	req, _ = http.NewRequest(http.MethodPost, "/upsert/"+idStr, strings.NewReader(`{}`))
	req.Header.Set("Content-Type", "application/json")
	res, _ = app.Test(req)
	if res.StatusCode != 422 {
		t.Fatalf("expected 422 got %d", res.StatusCode)
	}

	// CreateLast wrapper validation paths
	req, _ = http.NewRequest(http.MethodPost, "/create-last", strings.NewReader("{bad"))
	req.Header.Set("Content-Type", "application/json")
	res, _ = app.Test(req)
	if res.StatusCode != 400 {
		t.Fatalf("expected 400 got %d", res.StatusCode)
	}
	req, _ = http.NewRequest(http.MethodPost, "/create-last", strings.NewReader(`{"data":{"type":"last_flights_inspection_create","attributes":{"flight_inspection_id":"bad"}}}`))
	req.Header.Set("Content-Type", "application/json")
	res, _ = app.Test(req)
	if res.StatusCode != 422 {
		t.Fatalf("expected 422 got %d", res.StatusCode)
	}

	// UpdateLast wrapper validation paths
	req, _ = http.NewRequest(http.MethodPatch, "/update-last", strings.NewReader("{bad"))
	req.Header.Set("Content-Type", "application/json")
	res, _ = app.Test(req)
	if res.StatusCode != 400 {
		t.Fatalf("expected 400 got %d", res.StatusCode)
	}
	req, _ = http.NewRequest(http.MethodPatch, "/update-last", strings.NewReader(`{"data":{"type":"last_flights_inspection_update","attributes":{"flight_inspection_id":"bad"}}}`))
	req.Header.Set("Content-Type", "application/json")
	res, _ = app.Test(req)
	if res.StatusCode != 422 {
		t.Fatalf("expected 422 got %d", res.StatusCode)
	}

	// DeleteLast wrapper validation paths
	req, _ = http.NewRequest(http.MethodDelete, "/delete-last", strings.NewReader("{bad"))
	req.Header.Set("Content-Type", "application/json")
	res, _ = app.Test(req)
	if res.StatusCode != 400 {
		t.Fatalf("expected 400 got %d", res.StatusCode)
	}
	req, _ = http.NewRequest(http.MethodDelete, "/delete-last", strings.NewReader(`{"data":{"type":"last_flights_inspection_delete","attributes":{"flight_inspection_id":"bad"}}}`))
	req.Header.Set("Content-Type", "application/json")
	res, _ = app.Test(req)
	if res.StatusCode != 422 {
		t.Fatalf("expected 422 got %d", res.StatusCode)
	}

	t.Run("create-last allows optional afi file checklist to be false", func(t *testing.T) {
		inspectionID := uuidv7.MustBytes()
		inspectionIDStr, _ := uuidv7.BytesToString(inspectionID)
		aircraftID := uuidv7.MustBytes()
		file1 := uuidv7.MustBytes()
		file2 := uuidv7.MustBytes()
		file1Str, _ := uuidv7.BytesToString(file1)
		file2Str, _ := uuidv7.BytesToString(file2)

		h := NewReserveAcHandler(&reserveAcServiceMock{
			getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
				return &reserveac.ReserveAc{ID: uuidv7.MustBytes(), AircraftID: aircraftID, InspectionID: inspectionID, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
		})
		h.after = &afterServiceMock{
			getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) { return nil, nil },
			upsertFn: func(context.Context, []byte, *afterflightinspection.UpsertRequest) (*afterflightinspection.AfterFlightInspection, error) {
				t.Fatal("after upsert should not be called for incomplete checklist")
				return nil, nil
			},
		}
		h.inspect = &inspectionServiceMock{
			getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
				return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Now().UTC()}, nil
			},
		}
		h.heliFile = heliFileServiceMock{
			listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
				return []helicopterfile.HelicopterFile{
					{ID: file1, IsMandatory: true},
					{ID: file2, IsMandatory: false},
				}, nil
			},
		}
		h.fileCk = fileChecklistServiceMock{
			listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
				return nil, nil
			},
		}
		h.after = &afterServiceMock{
			upsertFn: func(context.Context, []byte, *afterflightinspection.UpsertRequest) (*afterflightinspection.AfterFlightInspection, error) {
				return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
		}

		app := fiber.New()
		app.Post("/create-last", h.CreateLastFlightsInspection)

		body := `{"data":{"type":"last_flights_inspection_create","attributes":{"flight_inspection_id":"` + inspectionIDStr + `","file_checklist":[{"helicopter_file_id":"` + file1Str + `","is_done":true},{"helicopter_file_id":"` + file2Str + `","is_done":false}]}}}`
		req, _ := http.NewRequest(http.MethodPost, "/create-last", strings.NewReader(body))
		req.Header.Set("Content-Type", "application/json")
		res, _ := app.Test(req)
		if res.StatusCode != 200 {
			t.Fatalf("expected 200 for optional false checklist, got %d", res.StatusCode)
		}

		body = `{"data":{"type":"last_flights_inspection_create","attributes":{"flight_inspection_id":"` + inspectionIDStr + `","file_checklist":[{"helicopter_file_id":"` + file1Str + `","is_done":false},{"helicopter_file_id":"` + file2Str + `","is_done":false}]}}}`
		req, _ = http.NewRequest(http.MethodPost, "/create-last", strings.NewReader(body))
		req.Header.Set("Content-Type", "application/json")
		res, _ = app.Test(req)
		if res.StatusCode != 422 {
			t.Fatalf("expected 422 for mandatory unchecked checklist item, got %d", res.StatusCode)
		}
	})
}

func TestReserveAcHandler_CreateServiceGuardBranches(t *testing.T) {
	heliID := uuidv7.MustBytes()
	flightID := uuidv7.MustBytes()
	heliStr, _ := uuidv7.BytesToString(heliID)
	flightStr, _ := uuidv7.BytesToString(flightID)

	runCreate := func(h *ReserveAcHandler) int {
		app := fiber.New()
		app.Post("/create", h.Create)
		req, _ := http.NewRequest(http.MethodPost, "/create", strings.NewReader(validReserveCreateBody(heliStr, flightStr)))
		req.Header.Set("Content-Type", "application/json")
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		return res.StatusCode
	}

	newBase := func() *ReserveAcHandler {
		h := NewReserveAcHandler(&reserveAcServiceMock{
			aircraftExistsFn: func(context.Context, []byte) (bool, error) { return true, nil },
		})
		h.flight = &reserveFlightServiceMock{
			getByIDFn: func(context.Context, []byte) (*flight.Flight, error) {
				return &flight.Flight{ID: flightID}, nil
			},
			updateFn: func(context.Context, *flight.Flight) error { return nil },
		}
		return h
	}

	h := newBase()
	if got := runCreate(h); got != 500 {
		t.Fatalf("expected 500 when inspect nil, got %d", got)
	}
	h.inspect = &inspectionServiceMock{}
	if got := runCreate(h); got != 500 {
		t.Fatalf("expected 500 when before nil, got %d", got)
	}
	h.before = beforeServiceMock{}
	if got := runCreate(h); got != 500 {
		t.Fatalf("expected 500 when prep nil, got %d", got)
	}
	h.prep = prepServiceMock{}
	if got := runCreate(h); got != 500 {
		t.Fatalf("expected 500 when heliFile nil, got %d", got)
	}
	h.heliFile = heliFileServiceMock{}
	if got := runCreate(h); got != 500 {
		t.Fatalf("expected 500 when file checklist nil, got %d", got)
	}

	h = newBase()
	h.inspect = &inspectionServiceMock{}
	h.before = beforeServiceMock{}
	h.prep = prepServiceMock{}
	h.heliFile = heliFileServiceMock{}
	h.fileCk = fileChecklistServiceMock{}
	h.flight = &reserveFlightServiceMock{
		getByIDFn: func(context.Context, []byte) (*flight.Flight, error) {
			return &flight.Flight{ID: flightID, ReserveAcID: uuidv7.MustBytes()}, nil
		},
	}
	if got := runCreate(h); got != 422 {
		t.Fatalf("expected 422 when flight already linked, got %d", got)
	}
}

func TestReserveAcHandler_GetDeleteListAdditionalBranches(t *testing.T) {
	id := uuidv7.MustBytes()
	idStr, _ := uuidv7.BytesToString(id)
	aircraftID := uuidv7.MustBytes()
	inspectionID := uuidv7.MustBytes()
	row := &reserveac.ReserveAc{ID: id, AircraftID: aircraftID, InspectionID: inspectionID, Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}

	t.Run("get id from uuid param", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{
			getByIDFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) { return row, nil },
		})
		h.inspect = &inspectionServiceMock{
			getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
				return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Now().UTC()}, nil
			},
		}
		h.before = beforeServiceMock{}
		h.prep = prepServiceMock{}
		h.heliFile = heliFileServiceMock{
			listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) { return nil, nil },
		}
		h.fileCk = fileChecklistServiceMock{
			listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
				return nil, nil
			},
		}
		app := fiber.New()
		app.Get("/get/:uuid", h.Get)
		req, _ := http.NewRequest(http.MethodGet, "/get/"+idStr, nil)
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		if res.StatusCode != 200 {
			t.Fatalf("expected 200 got %d", res.StatusCode)
		}
	})

	t.Run("get fallback still 404 when svc err persists", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{
			getByIDFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) { return nil, errors.New("boom") },
		})
		h.flight = &reserveFlightServiceMock{
			getByIDFn: func(context.Context, []byte) (*flight.Flight, error) {
				return &flight.Flight{ID: id, ReserveAcID: uuidv7.MustBytes()}, nil
			},
		}
		app := fiber.New()
		app.Get("/get/:id", h.Get)
		req, _ := http.NewRequest(http.MethodGet, "/get/"+idStr, nil)
		res, _ := app.Test(req)
		if res.StatusCode != 404 {
			t.Fatalf("expected 404 got %d", res.StatusCode)
		}
	})

	t.Run("delete id from uuid and delete error", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{
			deleteFn: func(context.Context, []byte, []byte) error { return errors.New("x") },
		})
		app := fiber.New()
		app.Delete("/del/:uuid", h.Delete)
		req, _ := http.NewRequest(http.MethodDelete, "/del/"+idStr, strings.NewReader(`{"data":{"id":"`+idStr+`"}}`))
		req.Header.Set("Content-Type", "application/json")
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		if res.StatusCode != 400 {
			t.Fatalf("expected 400 got %d", res.StatusCode)
		}
	})

	t.Run("delete not found returns 404", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{
			deleteFn: func(context.Context, []byte, []byte) error { return gorm.ErrRecordNotFound },
		})
		app := fiber.New()
		app.Delete("/del/:uuid", h.Delete)
		req, _ := http.NewRequest(http.MethodDelete, "/del/"+idStr, strings.NewReader(`{"data":{"id":"`+idStr+`"}}`))
		req.Header.Set("Content-Type", "application/json")
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		if res.StatusCode != http.StatusNotFound {
			t.Fatalf("expected 404 got %d", res.StatusCode)
		}
	})

	t.Run("list sizing and svc error", func(t *testing.T) {
		calls := 0
		h := NewReserveAcHandler(&reserveAcServiceMock{
			listFn: func(_ context.Context, _ string, _ string, limit, offset int) ([]reserveac.ReserveAc, int64, error) {
				calls++
				if calls == 1 {
					if limit != 20 || offset != 0 {
						t.Fatalf("expected fallback limit=20 offset=0, got %d/%d", limit, offset)
					}
					return []reserveac.ReserveAc{*row}, 1, nil
				}
				if limit != 100 {
					t.Fatalf("expected capped limit=100, got %d", limit)
				}
				return nil, 0, errors.New("list fail")
			},
		})
		app := fiber.New()
		app.Get("/list", h.List)

		req, _ := http.NewRequest(http.MethodGet, "/list?page[number]=0&page[size]=0&size=0", nil)
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		if res.StatusCode != 401 {
			t.Fatalf("expected 401 got %d", res.StatusCode)
		}

		req, _ = http.NewRequest(http.MethodGet, "/list?page[number]=2&page[size]=101", nil)
		res, _ = app.Test(req)
		if res.StatusCode != 401 {
			t.Fatalf("expected 401 got %d", res.StatusCode)
		}
	})
}

func TestReserveAcHandler_DeleteLastAndHelperErrorBranches(t *testing.T) {
	inspectionID := uuidv7.MustBytes()
	inspectionIDStr, _ := uuidv7.BytesToString(inspectionID)
	aircraftID := uuidv7.MustBytes()
	fileID := uuidv7.MustBytes()
	row := &reserveac.ReserveAc{ID: uuidv7.MustBytes(), AircraftID: aircraftID, InspectionID: inspectionID, Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}

	t.Run("deleteLast after service not configured", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{})
		app := fiber.New()
		app.Delete("/delete-last", h.DeleteLastFlightsInspection)
		req, _ := http.NewRequest(http.MethodDelete, "/delete-last", strings.NewReader(`{"data":{"type":"last_flights_inspection_delete","attributes":{"flight_inspection_id":"`+inspectionIDStr+`"}}}`))
		req.Header.Set("Content-Type", "application/json")
		res, _ := app.Test(req)
		if res.StatusCode != 500 {
			t.Fatalf("expected 500 got %d", res.StatusCode)
		}
	})

	t.Run("deleteLast heli/file checklist guard", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{})
		h.after = &afterServiceMock{
			getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
				return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
		}
		app := fiber.New()
		app.Delete("/delete-last", h.DeleteLastFlightsInspection)
		req, _ := http.NewRequest(http.MethodDelete, "/delete-last", strings.NewReader(`{"data":{"type":"last_flights_inspection_delete","attributes":{"flight_inspection_id":"`+inspectionIDStr+`"}}}`))
		req.Header.Set("Content-Type", "application/json")
		res, _ := app.Test(req)
		if res.StatusCode != 500 {
			t.Fatalf("expected 500 got %d", res.StatusCode)
		}
	})

	t.Run("getAfter generic error + checklist build error", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{
			getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) { return row, nil },
		})
		h.after = &afterServiceMock{
			getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
				return nil, errors.New("get failed")
			},
		}
		h.inspect = &inspectionServiceMock{getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) { return nil, nil }}
		h.heliFile = heliFileServiceMock{listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) { return nil, nil }}
		h.fileCk = fileChecklistServiceMock{listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return nil, nil
		}}
		app := fiber.New()
		app.Get("/after/:inspection_id", h.GetAfterFlightInspection)
		req, _ := http.NewRequest(http.MethodGet, "/after/"+inspectionIDStr, nil)
		res, _ := app.Test(req)
		if res.StatusCode != 400 {
			t.Fatalf("expected 400 got %d", res.StatusCode)
		}

		h.after = &afterServiceMock{
			getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
				return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
		}
		h.heliFile = heliFileServiceMock{
			listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
				return nil, errors.New("list section fail")
			},
		}
		req, _ = http.NewRequest(http.MethodGet, "/after/"+inspectionIDStr, nil)
		res, _ = app.Test(req)
		if res.StatusCode != 400 {
			t.Fatalf("expected 400 got %d", res.StatusCode)
		}
	})

	t.Run("upsert checklist update error branch", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{})
		h.heliFile = heliFileServiceMock{
			listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
				return []helicopterfile.HelicopterFile{{ID: fileID}}, nil
			},
		}
		h.fileCk = fileChecklistServiceMock{
			listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
				return []flightinspectionfilechecklist.FlightInspectionFileChecklist{{ID: uuidv7.MustBytes(), HelicopterFileID: fileID, IsDone: false}}, nil
			},
			updateFn: func(context.Context, *flightinspectionfilechecklist.FlightInspectionFileChecklist) error {
				return errors.New("update checklist fail")
			},
		}
		fileIDStr, _ := uuidv7.BytesToString(fileID)
		app := fiber.New()
		app.Get("/upsert", func(c *fiber.Ctx) error {
			if ok, err := h.upsertInspectionFileChecklistSection(
				c,
				inspectionID,
				aircraftID,
				helicopterfile.SectionAfterLastFlightInspection,
				[]requestdto.ReserveAcFileChecklistItem{{
					HelicopterFileID: fileIDStr,
					IsDone:           true,
				}},
				"/data/attributes/file_checklist",
				nil,
			); err != nil {
				return err
			} else if !ok {
				return nil
			}
			return nil
		})
		req, _ := http.NewRequest(http.MethodGet, "/upsert", nil)
		res, _ := app.Test(req)
		if res.StatusCode != 400 {
			t.Fatalf("expected 400 got %d", res.StatusCode)
		}
	})
}

func TestReserveAcHandler_UpsertAfterByIDBranchMatrix(t *testing.T) {
	inspectionID := uuidv7.MustBytes()
	aircraftID := uuidv7.MustBytes()
	fileID := uuidv7.MustBytes()
	fileIDStr, _ := uuidv7.BytesToString(fileID)
	validAttrs := requestdto.ReserveAcAfterFlightInspectionAttributes{
		OilEngineNR1Checked:       reserveStrPtr("checked"),
		OilEngineNR2Checked:       reserveStrPtr("checked"),
		HydraulicLHChecked:        reserveStrPtr("checked"),
		HydraulicRHChecked:        reserveStrPtr("checked"),
		OilTransmissionMGBChecked: reserveStrPtr("checked"),
		OilTransmissionIGBChecked: reserveStrPtr("checked"),
		OilTransmissionTGBChecked: reserveStrPtr("checked"),
		FileChecklist: []requestdto.ReserveAcFileChecklistItem{{
			HelicopterFileID: fileIDStr,
			IsDone:           true,
		}},
	}

	run := func(h *ReserveAcHandler, attrs requestdto.ReserveAcAfterFlightInspectionAttributes) int {
		app := fiber.New()
		app.Get("/x", func(c *fiber.Ctx) error {
			return h.upsertAfterFlightInspectionByID(c, inspectionID, attrs)
		})
		req, _ := http.NewRequest(http.MethodGet, "/x", nil)
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		return res.StatusCode
	}

	h := NewReserveAcHandler(&reserveAcServiceMock{})
	if got := run(h, requestdto.ReserveAcAfterFlightInspectionAttributes{}); got != 500 {
		t.Fatalf("expected 500 when after nil, got %d", got)
	}
	h.after = &afterServiceMock{}
	if got := run(h, requestdto.ReserveAcAfterFlightInspectionAttributes{}); got != 500 {
		t.Fatalf("expected 500 when inspect nil, got %d", got)
	}
	h.inspect = &inspectionServiceMock{}
	if got := run(h, requestdto.ReserveAcAfterFlightInspectionAttributes{}); got != 500 {
		t.Fatalf("expected 500 when checklist services nil, got %d", got)
	}

	h.heliFile = heliFileServiceMock{}
	h.fileCk = fileChecklistServiceMock{}
	h.svc = &reserveAcServiceMock{
		getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) { return nil, errors.New("boom") },
	}
	if got := run(h, requestdto.ReserveAcAfterFlightInspectionAttributes{}); got != 400 {
		t.Fatalf("expected 400 on active lookup error, got %d", got)
	}
	h.svc = &reserveAcServiceMock{
		getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) { return nil, nil },
	}
	if got := run(h, requestdto.ReserveAcAfterFlightInspectionAttributes{}); got != 404 {
		t.Fatalf("expected 404 on active lookup nil, got %d", got)
	}

	flightID := uuidv7.MustBytes()
	missionID := uuidv7.MustBytes()
	flightDataID := uuidv7.MustBytes()
	h.flight = &reserveFlightServiceMock{
		getByReserveAcFn: func(context.Context, []byte) (*flight.Flight, error) {
			return &flight.Flight{ID: flightID}, nil
		},
	}
	h.mission = reserveMissionServiceMock{
		listByFlightIDFn: func(context.Context, []byte) ([]mission.Mission, error) {
			return []mission.Mission{{
				ID:           missionID,
				FlightID:     flightID,
				FlightDataID: flightDataID,
				Type:         "HEMS",
			}}, nil
		},
	}
	h.flightData = reserveFlightDataServiceMock{
		getByIDFn: func(context.Context, []byte) (*flightdata.FlightData, error) {
			now := time.Now().UTC()
			return &flightdata.FlightData{
				ID:              flightDataID,
				MissionID:       missionID,
				CoPilotID:       uuidv7.MustBytes(),
				FromHospitalID:  uuidv7.MustBytes(),
				ToICAOID:        uuidv7.MustBytes(),
				FlightTakeOff:   now.Add(-10 * time.Minute),
				FlightLanding:   now,
				FlightDuration:  10 * time.Minute,
				FlightType:      "HEMS",
				LandingCount:    1,
				RotorBrakeCycle: 1,
				Status:          flightdata.StatusCompleted,
				FromHospital:    &hospitaldomain.Hospital{ID: uuidv7.MustBytes(), Name: "A"},
				ToICAO:          &icaodomain.ICAO{ID: uuidv7.MustBytes(), ICAOCode: "B"},
			}, nil
		},
	}

	h.heliFile = heliFileServiceMock{
		listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
			return []helicopterfile.HelicopterFile{{ID: fileID}}, nil
		},
	}
	h.fileCk = fileChecklistServiceMock{
		listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return nil, nil
		},
	}
	h.svc = &reserveAcServiceMock{
		getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
			return &reserveac.ReserveAc{ID: uuidv7.MustBytes(), AircraftID: aircraftID, InspectionID: inspectionID, Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
		},
	}
	h.after = &afterServiceMock{
		upsertFn: func(context.Context, []byte, *afterflightinspection.UpsertRequest) (*afterflightinspection.AfterFlightInspection, error) {
			return nil, afterflightinspection.ErrCapabilitiesUnavailable
		},
	}
	if got := run(h, validAttrs); got != 422 {
		t.Fatalf("expected 422 validation error, got %d", got)
	}

	h.after = &afterServiceMock{
		upsertFn: func(context.Context, []byte, *afterflightinspection.UpsertRequest) (*afterflightinspection.AfterFlightInspection, error) {
			return nil, errors.New("upsert fail")
		},
	}
	if got := run(h, validAttrs); got != 400 {
		t.Fatalf("expected 400 generic upsert error, got %d", got)
	}

	h.after = &afterServiceMock{
		upsertFn: func(context.Context, []byte, *afterflightinspection.UpsertRequest) (*afterflightinspection.AfterFlightInspection, error) {
			return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
		},
	}
	h.inspect = &inspectionServiceMock{
		getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
			return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Now().UTC()}, nil
		},
	}
	h.fileCk = fileChecklistServiceMock{
		listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return nil, errors.New("ck list fail")
		},
	}
	if got := run(h, validAttrs); got != 400 {
		t.Fatalf("expected 400 checklist section error, got %d", got)
	}
}

func TestReserveAcHandler_DeleteChecklistSectionBranches(t *testing.T) {
	inspectionID := uuidv7.MustBytes()
	aircraftID := uuidv7.MustBytes()
	fileID := uuidv7.MustBytes()

	h := NewReserveAcHandler(&reserveAcServiceMock{})
	h.heliFile = heliFileServiceMock{
		listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
			return nil, errors.New("template error")
		},
	}
	h.fileCk = fileChecklistServiceMock{}

	app := fiber.New()
	app.Get("/d", func(c *fiber.Ctx) error {
		return h.deleteInspectionFileChecklistSection(c, inspectionID, aircraftID, helicopterfile.SectionAfterLastFlightInspection)
	})

	req, _ := http.NewRequest(http.MethodGet, "/d", nil)
	res, _ := app.Test(req)
	if res.StatusCode != 500 {
		t.Fatalf("expected 500 when template list error bubbles, got %d", res.StatusCode)
	}

	h.heliFile = heliFileServiceMock{
		listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
			return []helicopterfile.HelicopterFile{{ID: fileID}}, nil
		},
	}
	h.fileCk = fileChecklistServiceMock{
		listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return nil, errors.New("existing error")
		},
	}
	req, _ = http.NewRequest(http.MethodGet, "/d", nil)
	res, _ = app.Test(req)
	if res.StatusCode != 500 {
		t.Fatalf("expected 500 when existing list error bubbles, got %d", res.StatusCode)
	}

	h.fileCk = fileChecklistServiceMock{
		listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return []flightinspectionfilechecklist.FlightInspectionFileChecklist{{ID: uuidv7.MustBytes(), HelicopterFileID: fileID}}, nil
		},
		deleteFn: func(context.Context, []byte) error { return errors.New("delete fail") },
	}
	req, _ = http.NewRequest(http.MethodGet, "/d", nil)
	res, _ = app.Test(req)
	if res.StatusCode != 500 {
		t.Fatalf("expected 500 when delete error bubbles, got %d", res.StatusCode)
	}
}

func TestReserveAcHandler_CreateLateBranchesAndValidation(t *testing.T) {
	heliID := uuidv7.MustBytes()
	flightID := uuidv7.MustBytes()
	inspectionID := uuidv7.MustBytes()
	rowID := uuidv7.MustBytes()
	fileBefore := uuidv7.MustBytes()
	filePrepare := uuidv7.MustBytes()
	heliStr, _ := uuidv7.BytesToString(heliID)
	flightStr, _ := uuidv7.BytesToString(flightID)
	fileBeforeStr, _ := uuidv7.BytesToString(fileBefore)
	filePrepareStr, _ := uuidv7.BytesToString(filePrepare)

	validBody := `{"data":{"type":"reserve_ac_create","attributes":{"helicopter_id":"` + heliStr + `","flight_id":"` + flightStr + `","inspection":{"inspection_date":"2026-05-06","before":{"fuel_amount":1,"file_checklist":[{"helicopter_file_id":"` + fileBeforeStr + `","is_done":true}]},"prepare":{"notam_briefing":true,"file_checklist":[{"helicopter_file_id":"` + filePrepareStr + `","is_done":true}]}}}}}`

	run := func(h *ReserveAcHandler, body string) int {
		app := fiber.New()
		app.Post("/create", h.Create)
		req, _ := http.NewRequest(http.MethodPost, "/create", strings.NewReader(body))
		req.Header.Set("Content-Type", "application/json")
		res, err := app.Test(req)
		if err != nil {
			t.Fatal(err)
		}
		return res.StatusCode
	}

	t.Run("validate struct error", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{})
		if got := run(h, `{"data":{"type":"reserve_ac_create","attributes":{}}}`); got != 422 {
			t.Fatalf("expected 422 got %d", got)
		}
	})

	newFullHandler := func() *ReserveAcHandler {
		h := NewReserveAcHandler(&reserveAcServiceMock{
			createFn: func(context.Context, *reserveac.ReserveAc) error { return nil },
			updateFn: func(context.Context, *reserveac.ReserveAc) error { return nil },
			getByIDFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
				return &reserveac.ReserveAc{ID: rowID, AircraftID: heliID, InspectionID: inspectionID, Status: reserveac.StatusPending, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
			aircraftExistsFn: func(context.Context, []byte) (bool, error) { return true, nil },
		})
		h.flight = &reserveFlightServiceMock{
			getByIDFn: func(context.Context, []byte) (*flight.Flight, error) { return &flight.Flight{ID: flightID}, nil },
			updateFn:  func(context.Context, *flight.Flight) error { return nil },
		}
		h.inspect = &inspectionServiceMock{
			createDraftFn: func(context.Context, *flightinspection.FlightInspection) error { return nil },
			getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
				return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Now().UTC()}, nil
			},
		}
		h.before = beforeServiceFnMock{
			upsertFn: func(context.Context, []byte, *beforeflightinspection.UpsertRequest) (*beforeflightinspection.BeforeFlightInspection, error) {
				return &beforeflightinspection.BeforeFlightInspection{}, nil
			},
		}
		h.prep = prepServiceFnMock{
			initFn: func(context.Context, []byte) (int, error) {
				return 1, nil
			},
			upsertFn: func(context.Context, []byte, *flightprepcheck.UpsertRequest) (*flightprepcheck.FlightPrepCheck, error) {
				return &flightprepcheck.FlightPrepCheck{NOTAMBriefing: true, WeatherBriefing: true, OperationalFlightPlan: true}, nil
			},
		}
		h.heliFile = heliFileServiceMock{
			listBySectionFn: func(_ context.Context, _ []byte, section string) ([]helicopterfile.HelicopterFile, error) {
				switch section {
				case helicopterfile.SectionBeforeFirstFlightInspection:
					return []helicopterfile.HelicopterFile{{ID: fileBefore}}, nil
				case helicopterfile.SectionFlightPreparationAndWB:
					return []helicopterfile.HelicopterFile{{ID: filePrepare}}, nil
				default:
					return nil, nil
				}
			},
		}
		h.fileCk = fileChecklistServiceMock{
			listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
				return nil, nil
			},
			createFn: func(context.Context, *flightinspectionfilechecklist.FlightInspectionFileChecklist) error { return nil },
			updateFn: func(context.Context, *flightinspectionfilechecklist.FlightInspectionFileChecklist) error { return nil },
		}
		return h
	}

	t.Run("before checklist upsert error", func(t *testing.T) {
		h := newFullHandler()
		badBefore := `{"data":{"type":"reserve_ac_create","attributes":{"helicopter_id":"` + heliStr + `","flight_id":"` + flightStr + `","inspection":{"inspection_date":"2026-05-06","before":{"fuel_amount":1,"file_checklist":[{"helicopter_file_id":"bad","is_done":true}]},"prepare":{"notam_briefing":true}}}}}`
		var parsed requestdto.ReserveAcCreateRequest
		if err := json.Unmarshal([]byte(badBefore), &parsed); err != nil {
			t.Fatal(err)
		}
		if len(parsed.Data.Attributes.Inspection.Before.FileChecklist) == 0 {
			t.Fatal("expected before checklist parsed")
		}
		if got := run(h, badBefore); got != 422 {
			t.Fatalf("expected 422 got %d", got)
		}
	})

	t.Run("prepare checklist upsert error", func(t *testing.T) {
		h := newFullHandler()
		badPrepare := `{"data":{"type":"reserve_ac_create","attributes":{"helicopter_id":"` + heliStr + `","flight_id":"` + flightStr + `","inspection":{"inspection_date":"2026-05-06","before":{"fuel_amount":1,"file_checklist":[{"helicopter_file_id":"` + fileBeforeStr + `","is_done":true}]},"prepare":{"notam_briefing":true,"file_checklist":[{"helicopter_file_id":"bad","is_done":true}]}}}}}`
		var parsed requestdto.ReserveAcCreateRequest
		if err := json.Unmarshal([]byte(badPrepare), &parsed); err != nil {
			t.Fatal(err)
		}
		if len(parsed.Data.Attributes.Inspection.Prepare.FileChecklist) == 0 {
			t.Fatal("expected prepare checklist parsed")
		}
		if got := run(h, badPrepare); got != 422 {
			t.Fatalf("expected 422 got %d", got)
		}
	})

	t.Run("svc update failed after status compute", func(t *testing.T) {
		h := newFullHandler()
		h.svc = &reserveAcServiceMock{
			createFn:          func(context.Context, *reserveac.ReserveAc) error { return nil },
			updateFn:          func(context.Context, *reserveac.ReserveAc) error { return errors.New("update fail") },
			getByIDFn:         func(context.Context, []byte) (*reserveac.ReserveAc, error) { return nil, nil },
			aircraftExistsFn:  func(context.Context, []byte) (bool, error) { return true, nil },
			getActiveByInspFn: nil,
		}
		if got := run(h, validBody); got != 400 {
			t.Fatalf("expected 400 got %d", got)
		}
	})

	t.Run("created row preferred and fallback row", func(t *testing.T) {
		h := newFullHandler()
		if got := run(h, validBody); got != 201 {
			t.Fatalf("expected 201 got %d", got)
		}

		h = newFullHandler()
		h.svc = &reserveAcServiceMock{
			createFn: func(context.Context, *reserveac.ReserveAc) error { return nil },
			updateFn: func(context.Context, *reserveac.ReserveAc) error { return nil },
			getByIDFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
				return nil, errors.New("not found created")
			},
			aircraftExistsFn: func(context.Context, []byte) (bool, error) { return true, nil },
		}
		if got := run(h, validBody); got != 201 {
			t.Fatalf("expected 201 got %d", got)
		}
	})
}

func TestReserveAcHandler_WrapperAndHelperBranches(t *testing.T) {
	t.Run("upsert wrapper reaches delegation", func(t *testing.T) {
		inspectionID := uuidv7.MustBytes()
		inspectionIDStr, _ := uuidv7.BytesToString(inspectionID)
		aircraftID := uuidv7.MustBytes()
		fileID := uuidv7.MustBytes()
		fileIDStr, _ := uuidv7.BytesToString(fileID)

		h := NewReserveAcHandler(&reserveAcServiceMock{
			getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
				return &reserveac.ReserveAc{ID: uuidv7.MustBytes(), AircraftID: aircraftID, InspectionID: inspectionID, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
		})
		h.after = &afterServiceMock{
			upsertFn: func(context.Context, []byte, *afterflightinspection.UpsertRequest) (*afterflightinspection.AfterFlightInspection, error) {
				return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
		}
		h.inspect = &inspectionServiceMock{getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
			return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Now().UTC()}, nil
		}}
		h.heliFile = heliFileServiceMock{listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
			return []helicopterfile.HelicopterFile{{ID: fileID}}, nil
		}}
		h.fileCk = fileChecklistServiceMock{listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return nil, nil
		}}
		app := fiber.New()
		app.Post("/upsert/:inspection_id", h.UpsertAfterFlightInspection)
		body := `{"data":{"type":"after_flight_inspection_upsert","attributes":{"file_checklist":[{"helicopter_file_id":"` + fileIDStr + `","is_done":true}]}}}`
		req, _ := http.NewRequest(http.MethodPost, "/upsert/"+inspectionIDStr, strings.NewReader(body))
		req.Header.Set("Content-Type", "application/json")
		res, _ := app.Test(req)
		if res.StatusCode != 200 {
			t.Fatalf("expected 200 got %d", res.StatusCode)
		}
	})

	t.Run("get-last delegates success", func(t *testing.T) {
		inspectionID := uuidv7.MustBytes()
		inspectionIDStr, _ := uuidv7.BytesToString(inspectionID)
		aircraftID := uuidv7.MustBytes()
		h := NewReserveAcHandler(&reserveAcServiceMock{
			getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
				return &reserveac.ReserveAc{ID: uuidv7.MustBytes(), AircraftID: aircraftID, InspectionID: inspectionID, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
		})
		h.after = &afterServiceMock{getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
			return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
		}}
		h.inspect = &inspectionServiceMock{getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
			return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Now().UTC()}, nil
		}}
		h.heliFile = heliFileServiceMock{listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) { return nil, nil }}
		h.fileCk = fileChecklistServiceMock{listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return nil, nil
		}}
		app := fiber.New()
		app.Get("/get-last", h.GetLastFlightsInspection)
		req, _ := http.NewRequest(http.MethodGet, "/get-last?inspection_id="+inspectionIDStr, nil)
		res, _ := app.Test(req)
		if res.StatusCode != 200 {
			t.Fatalf("expected 200 got %d", res.StatusCode)
		}
	})

	t.Run("create/update/delete last service error branches", func(t *testing.T) {
		inspectionID := uuidv7.MustBytes()
		inspectionIDStr, _ := uuidv7.BytesToString(inspectionID)
		app := fiber.New()

		// CreateLast validation errs path + existing duplicate
		h := NewReserveAcHandler(&reserveAcServiceMock{})
		h.after = &afterServiceMock{getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
			return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes()}, nil
		}}
		app.Post("/create-last", h.CreateLastFlightsInspection)
		req, _ := http.NewRequest(http.MethodPost, "/create-last", strings.NewReader(`{"data":{"type":"last_flights_inspection_create","attributes":{"flight_inspection_id":"`+inspectionIDStr+`"}}}`))
		req.Header.Set("Content-Type", "application/json")
		res, _ := app.Test(req)
		if res.StatusCode != 422 {
			t.Fatalf("expected 422 got %d", res.StatusCode)
		}

		// UpdateLast get error branch
		h = NewReserveAcHandler(&reserveAcServiceMock{})
		h.after = &afterServiceMock{getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
			return nil, errors.New("get failed")
		}}
		app.Patch("/update-last2", h.UpdateLastFlightsInspection)
		req, _ = http.NewRequest(http.MethodPatch, "/update-last2", strings.NewReader(`{"data":{"type":"last_flights_inspection_update","attributes":{"flight_inspection_id":"`+inspectionIDStr+`"}}}`))
		req.Header.Set("Content-Type", "application/json")
		res, _ = app.Test(req)
		if res.StatusCode != 400 {
			t.Fatalf("expected 400 got %d", res.StatusCode)
		}

		// DeleteLast downstream branches
		h = NewReserveAcHandler(&reserveAcServiceMock{
			getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
				return &reserveac.ReserveAc{ID: uuidv7.MustBytes(), AircraftID: uuidv7.MustBytes(), InspectionID: inspectionID, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
		})
		h.after = &afterServiceMock{
			getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
				return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
			delFn: func(context.Context, []byte) error { return nil },
		}
		h.heliFile = heliFileServiceMock{listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
			return []helicopterfile.HelicopterFile{{ID: uuidv7.MustBytes()}}, nil
		}}
		h.fileCk = fileChecklistServiceMock{
			listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
				return []flightinspectionfilechecklist.FlightInspectionFileChecklist{}, nil
			},
			deleteFn: func(context.Context, []byte) error { return nil },
		}
		app.Delete("/delete-last2", h.DeleteLastFlightsInspection)
		req, _ = http.NewRequest(http.MethodDelete, "/delete-last2", strings.NewReader(`{"data":{"type":"last_flights_inspection_delete","attributes":{"flight_inspection_id":"`+inspectionIDStr+`"}}}`))
		req.Header.Set("Content-Type", "application/json")
		res, _ = app.Test(req)
		if res.StatusCode != 200 {
			t.Fatalf("expected 200 got %d", res.StatusCode)
		}
	})

	t.Run("create-last rejects incomplete mission flight data", func(t *testing.T) {
		inspectionID := uuidv7.MustBytes()
		inspectionIDStr, _ := uuidv7.BytesToString(inspectionID)
		reserveID := uuidv7.MustBytes()
		flightID := uuidv7.MustBytes()
		completeMissionID := uuidv7.MustBytes()
		incompleteMissionID := uuidv7.MustBytes()
		completeFlightDataID := uuidv7.MustBytes()
		incompleteFlightDataID := uuidv7.MustBytes()

		h := NewReserveAcHandler(&reserveAcServiceMock{
			getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
				return &reserveac.ReserveAc{ID: reserveID, AircraftID: uuidv7.MustBytes(), InspectionID: inspectionID}, nil
			},
		})
		h.flight = &reserveFlightServiceMock{
			getByReserveAcFn: func(context.Context, []byte) (*flight.Flight, error) {
				return &flight.Flight{ID: flightID}, nil
			},
		}
		h.mission = reserveMissionServiceMock{
			listByFlightIDFn: func(context.Context, []byte) ([]mission.Mission, error) {
				return []mission.Mission{
					{ID: completeMissionID, FlightDataID: completeFlightDataID, Type: "CAT"},
					{ID: incompleteMissionID, FlightDataID: incompleteFlightDataID, Type: "CAT"},
				}, nil
			},
		}
		h.flightData = reserveFlightDataServiceMock{
			getByIDFn: func(_ context.Context, id []byte) (*flightdata.FlightData, error) {
				switch {
				case bytes.Equal(id, completeFlightDataID):
					takeoff := time.Date(2026, 6, 15, 8, 0, 0, 0, time.UTC)
					landing := takeoff.Add(10 * time.Minute)
					return &flightdata.FlightData{
						ID:              completeFlightDataID,
						MissionID:       completeMissionID,
						CoPilotID:       uuidv7.MustBytes(),
						FromHospitalID:  uuidv7.MustBytes(),
						ToHospitalID:    uuidv7.MustBytes(),
						FlightTakeOff:   takeoff,
						FlightLanding:   landing,
						FlightDuration:  10 * time.Minute,
						LandingCount:    1,
						RotorBrakeCycle: 1,
						Status:          flightdata.StatusCompleted,
						Mission:         &mission.Mission{Type: "CAT"},
					}, nil
				case bytes.Equal(id, incompleteFlightDataID):
					takeoff := time.Date(2026, 6, 15, 8, 30, 0, 0, time.UTC)
					landing := takeoff.Add(10 * time.Minute)
					return &flightdata.FlightData{
						ID:             incompleteFlightDataID,
						MissionID:      incompleteMissionID,
						CoPilotID:      uuidv7.MustBytes(),
						FromHospitalID: uuidv7.MustBytes(),
						ToHospitalID:   uuidv7.MustBytes(),
						FlightTakeOff:  takeoff,
						FlightLanding:  landing,
						FlightDuration: 10 * time.Minute,
						// incomplete on purpose
						Status:  flightdata.StatusInProgress,
						Mission: &mission.Mission{Type: "CAT"},
					}, nil
				default:
					return nil, nil
				}
			},
		}
		h.after = &afterServiceMock{}
		h.inspect = &inspectionServiceMock{getByIDFn: func(context.Context, []byte) (*flightinspection.FlightInspection, error) {
			return &flightinspection.FlightInspection{ID: inspectionID, InspectionDate: time.Now().UTC()}, nil
		}}
		h.heliFile = heliFileServiceMock{listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
			return []helicopterfile.HelicopterFile{{ID: uuidv7.MustBytes()}}, nil
		}}
		h.fileCk = fileChecklistServiceMock{listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
			return nil, nil
		}}

		app := fiber.New()
		app.Post("/create-last", h.CreateLastFlightsInspection)
		body := `{"data":{"type":"last_flights_inspection_create","attributes":{"flight_inspection_id":"` + inspectionIDStr + `"}}}`
		req, _ := http.NewRequest(http.MethodPost, "/create-last", strings.NewReader(body))
		req.Header.Set("Content-Type", "application/json")
		res, _ := app.Test(req)
		if res.StatusCode != http.StatusUnprocessableEntity {
			t.Fatalf("expected 422 got %d", res.StatusCode)
		}
		bodyBytes, _ := io.ReadAll(res.Body)
		bodyStr := string(bodyBytes)
		if !strings.Contains(bodyStr, "cannot submit after-flight: mission") {
			t.Fatalf("expected detailed after-flight validation message, got %s", bodyStr)
		}
		if !strings.Contains(bodyStr, `"code":"FLIGHT_DATA_AFTER_FLIGHT_INCOMPLETE"`) {
			t.Fatalf("expected flight data error code, got %s", bodyStr)
		}
		if !strings.Contains(bodyStr, `"error_code":"4222616"`) {
			t.Fatalf("expected flight data error code id, got %s", bodyStr)
		}
	})

	t.Run("helper branches for before payload and summaries", func(t *testing.T) {
		if !hasReserveAcBeforePayload(requestdto.ReserveAcBeforeInspectionAttributes{OilTransmissionMGBChecked: ptrBool(true)}) {
			t.Fatal("expected transmission payload true")
		}
		if !hasReserveAcBeforePayload(requestdto.ReserveAcBeforeInspectionAttributes{FuelAddedAmount: ptrFloat(1)}) {
			t.Fatal("expected fuel_added payload true")
		}

		h := NewReserveAcHandler(&reserveAcServiceMock{}).WithFileStorage(fileStorageMock{})
		app := fiber.New()
		app.Get("/x", func(c *fiber.Ctx) error {
			file := &filemanager.File{ID: uuidv7.MustBytes(), Name: " doc.pdf ", Bucket: "b", ObjectKey: "k"}
			att := &filemanager.Attachment{ID: uuidv7.MustBytes(), File: file}
			files := []helicopterfile.HelicopterFile{
				{ID: uuidv7.MustBytes(), FileAttachment: att},
				{ID: uuidv7.MustBytes()},
			}
			out := h.buildChecklistSectionSummary(c, files, map[string]bool{idString(files[0].ID): true})
			if out.Completed != 1 || len(out.DoneFiles) != 1 || out.FileChecklist[0].DownloadURL == "" {
				t.Fatal("expected checklist with done + download url")
			}
			payload := afterFlightInspectionPayload(uuidv7.MustBytes(), nil, nil, nil, reserveAcChecklistSectionCommon{Total: 0, Completed: 0}, nil)
			if payload.Data.Attributes.Total != 0 {
				t.Fatal("expected zero total")
			}
			return c.SendStatus(200)
		})
		req, _ := http.NewRequest(http.MethodGet, "/x", nil)
		res, err := app.Test(req)
		if err != nil || res.StatusCode != 200 {
			t.Fatalf("expected 200 got err=%v code=%d", err, res.StatusCode)
		}
	})

	t.Run("load mission flight data prefers latest mission row", func(t *testing.T) {
		missionID := uuidv7.MustBytes()
		staleFlightDataID := uuidv7.MustBytes()
		latestFlightDataID := uuidv7.MustBytes()

		h := NewReserveAcHandler(&reserveAcServiceMock{})
		h.flightData = reserveFlightDataServiceMock{
			getByIDFn: func(_ context.Context, id []byte) (*flightdata.FlightData, error) {
				if bytes.Equal(id, staleFlightDataID) {
					return &flightdata.FlightData{
						ID:        staleFlightDataID,
						MissionID: missionID,
						Status:    flightdata.StatusInProgress,
						Mission:   &mission.Mission{Type: "CAT"},
					}, nil
				}
				return nil, nil
			},
			getByMissionIDFn: func(_ context.Context, id []byte) (*flightdata.FlightData, error) {
				if bytes.Equal(id, missionID) {
					return &flightdata.FlightData{
						ID:        latestFlightDataID,
						MissionID: missionID,
						Status:    flightdata.StatusCompleted,
						Mission:   &mission.Mission{Type: "CAT"},
					}, nil
				}
				return nil, nil
			},
		}

		fd, ok := h.loadMissionFlightData(context.Background(), mission.Mission{ID: missionID, FlightDataID: staleFlightDataID, Type: "CAT"})
		if !ok {
			t.Fatal("expected flight data to be found")
		}
		if fd == nil || !bytes.Equal(fd.ID, latestFlightDataID) {
			t.Fatalf("expected latest mission row, got %+v", fd)
		}
		if !flightdata.IsComplete(fd) {
			t.Fatalf("expected latest mission row to be complete, got %+v", fd)
		}
	})
}

func TestReserveAcHandler_LastInspectionAndListMoreBranches(t *testing.T) {
	inspectionID := uuidv7.MustBytes()
	inspectionIDStr, _ := uuidv7.BytesToString(inspectionID)

	t.Run("create-last get existing error", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{})
		h.after = &afterServiceMock{
			getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
				return nil, errors.New("err")
			},
		}
		app := fiber.New()
		app.Post("/create-last", h.CreateLastFlightsInspection)
		req, _ := http.NewRequest(http.MethodPost, "/create-last", strings.NewReader(`{"data":{"type":"last_flights_inspection_create","attributes":{"flight_inspection_id":"`+inspectionIDStr+`"}}}`))
		req.Header.Set("Content-Type", "application/json")
		res, _ := app.Test(req)
		if res.StatusCode != 400 {
			t.Fatalf("expected 400 got %d", res.StatusCode)
		}
	})

	t.Run("update-last validation error", func(t *testing.T) {
		h := NewReserveAcHandler(&reserveAcServiceMock{})
		h.after = &afterServiceMock{}
		app := fiber.New()
		app.Patch("/update-last", h.UpdateLastFlightsInspection)
		req, _ := http.NewRequest(http.MethodPatch, "/update-last", strings.NewReader(`{"data":{"type":"wrong","attributes":{"flight_inspection_id":"`+inspectionIDStr+`"}}}`))
		req.Header.Set("Content-Type", "application/json")
		res, _ := app.Test(req)
		if res.StatusCode != 422 {
			t.Fatalf("expected 422 got %d", res.StatusCode)
		}
	})

	t.Run("delete-last full error matrix", func(t *testing.T) {
		aircraftID := uuidv7.MustBytes()
		fileID := uuidv7.MustBytes()
		app := fiber.New()

		// existing fetch error
		h := NewReserveAcHandler(&reserveAcServiceMock{})
		h.after = &afterServiceMock{
			getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
				return nil, errors.New("get err")
			},
		}
		h.heliFile = heliFileServiceMock{}
		h.fileCk = fileChecklistServiceMock{}
		app.Delete("/d1", h.DeleteLastFlightsInspection)
		req, _ := http.NewRequest(http.MethodDelete, "/d1", strings.NewReader(`{"data":{"type":"last_flights_inspection_delete","attributes":{"flight_inspection_id":"`+inspectionIDStr+`"}}}`))
		req.Header.Set("Content-Type", "application/json")
		res, _ := app.Test(req)
		if res.StatusCode != 400 {
			t.Fatalf("expected 400 got %d", res.StatusCode)
		}

		// existing not found
		h = NewReserveAcHandler(&reserveAcServiceMock{})
		h.after = &afterServiceMock{getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) { return nil, nil }}
		h.heliFile = heliFileServiceMock{}
		h.fileCk = fileChecklistServiceMock{}
		app.Delete("/d2", h.DeleteLastFlightsInspection)
		req, _ = http.NewRequest(http.MethodDelete, "/d2", strings.NewReader(`{"data":{"type":"last_flights_inspection_delete","attributes":{"flight_inspection_id":"`+inspectionIDStr+`"}}}`))
		req.Header.Set("Content-Type", "application/json")
		res, _ = app.Test(req)
		if res.StatusCode != 404 {
			t.Fatalf("expected 404 got %d", res.StatusCode)
		}

		// get active error and nil
		h = NewReserveAcHandler(&reserveAcServiceMock{
			getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) { return nil, errors.New("active err") },
		})
		h.after = &afterServiceMock{getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
			return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
		}}
		h.heliFile = heliFileServiceMock{}
		h.fileCk = fileChecklistServiceMock{}
		app.Delete("/d3", h.DeleteLastFlightsInspection)
		req, _ = http.NewRequest(http.MethodDelete, "/d3", strings.NewReader(`{"data":{"type":"last_flights_inspection_delete","attributes":{"flight_inspection_id":"`+inspectionIDStr+`"}}}`))
		req.Header.Set("Content-Type", "application/json")
		res, _ = app.Test(req)
		if res.StatusCode != 400 {
			t.Fatalf("expected 400 got %d", res.StatusCode)
		}

		h = NewReserveAcHandler(&reserveAcServiceMock{
			getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) { return nil, nil },
		})
		h.after = &afterServiceMock{getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
			return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
		}}
		h.heliFile = heliFileServiceMock{}
		h.fileCk = fileChecklistServiceMock{}
		app.Delete("/d4", h.DeleteLastFlightsInspection)
		req, _ = http.NewRequest(http.MethodDelete, "/d4", strings.NewReader(`{"data":{"type":"last_flights_inspection_delete","attributes":{"flight_inspection_id":"`+inspectionIDStr+`"}}}`))
		req.Header.Set("Content-Type", "application/json")
		res, _ = app.Test(req)
		if res.StatusCode != 404 {
			t.Fatalf("expected 404 got %d", res.StatusCode)
		}

		// delete checklist error
		h = NewReserveAcHandler(&reserveAcServiceMock{
			getActiveByInspFn: func(context.Context, []byte) (*reserveac.ReserveAc, error) {
				return &reserveac.ReserveAc{ID: uuidv7.MustBytes(), AircraftID: aircraftID, InspectionID: inspectionID, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
		})
		h.after = &afterServiceMock{
			getFn: func(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) {
				return &afterflightinspection.AfterFlightInspection{ID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}, nil
			},
			delFn: func(context.Context, []byte) error { return nil },
		}
		h.heliFile = heliFileServiceMock{
			listBySectionFn: func(context.Context, []byte, string) ([]helicopterfile.HelicopterFile, error) {
				return []helicopterfile.HelicopterFile{{ID: fileID}}, nil
			},
		}
		h.fileCk = fileChecklistServiceMock{
			listByInspectionFn: func(context.Context, []byte) ([]flightinspectionfilechecklist.FlightInspectionFileChecklist, error) {
				return []flightinspectionfilechecklist.FlightInspectionFileChecklist{{ID: uuidv7.MustBytes(), HelicopterFileID: fileID}}, nil
			},
			deleteFn: func(context.Context, []byte) error { return errors.New("delete ck fail") },
		}
		app.Delete("/d5", h.DeleteLastFlightsInspection)
		req, _ = http.NewRequest(http.MethodDelete, "/d5", strings.NewReader(`{"data":{"type":"last_flights_inspection_delete","attributes":{"flight_inspection_id":"`+inspectionIDStr+`"}}}`))
		req.Header.Set("Content-Type", "application/json")
		res, _ = app.Test(req)
		if res.StatusCode != 400 {
			t.Fatalf("expected 400 got %d", res.StatusCode)
		}
	})

	t.Run("list fallback branches", func(t *testing.T) {
		id := uuidv7.MustBytes()
		aircraftID := uuidv7.MustBytes()
		h := NewReserveAcHandler(&reserveAcServiceMock{
			listFn: func(context.Context, string, string, int, int) ([]reserveac.ReserveAc, int64, error) {
				return []reserveac.ReserveAc{{ID: id, AircraftID: aircraftID, InspectionID: uuidv7.MustBytes(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}}, 1, nil
			},
		})
		// leave h.flight nil and other deps nil to hit guard branches
		app := fiber.New()
		app.Get("/list", h.List)
		req, _ := http.NewRequest(http.MethodGet, "/list?page[number]=-10&page[size]=-1", nil)
		res, _ := app.Test(req)
		if res.StatusCode != 401 {
			t.Fatalf("expected 401 got %d", res.StatusCode)
		}
	})
}
