package distribution

import (
	"context"
	"errors"
	"mime/multipart"
	"strings"
	"testing"

	"github.com/TaruLab/keluargamart-backend/internal/db"
)

// Reported: "selesaikan pesanan DO tidak bisa" — every POST
// /delivery-orders/{id}/deliver panicked (nil pointer in q.Exec) because
// SetDeliveryOrderPOD passed nil as the transaction to the row writer. The
// panic hit every completion, with or without a photo.

func TestSetDeliveryOrderPOD_UsesTheCallerTransaction(t *testing.T) {
	fs := newFakeStore()
	fs.dos[1] = &db.GetDeliveryOrderByIDRow{}
	svc := NewService(fs, nil, nil)

	tx := &fakeTx{store: fs}
	if err := svc.SetDeliveryOrderPOD(context.Background(), tx, 1, nil, "Budi"); err != nil {
		t.Fatalf("SetDeliveryOrderPOD: %v", err)
	}
	d := fs.dos[1]
	if d.ProofPhotoUrl.Valid {
		t.Errorf("photoURL set for a body-less completion: %q", d.ProofPhotoUrl.String)
	}
	if got := d.PodRecipientName.String; got != "Budi" {
		t.Errorf("recipient = %q, want Budi", got)
	}
}

// An attached photo routes through the wired saver and lands in the row.
func TestSetDeliveryOrderPOD_PhotoGoesThroughTheSaver(t *testing.T) {
	fs := newFakeStore()
	fs.dos[1] = &db.GetDeliveryOrderByIDRow{}
	var saverCalled bool
	svc := NewService(fs, nil, nil).WithPODSaver(func(_ context.Context, _ *multipart.FileHeader) (string, error) {
		saverCalled = true
		return "/uploads/proof-abc.jpg", nil
	})

	tx := &fakeTx{store: fs}
	if err := svc.SetDeliveryOrderPOD(context.Background(), tx, 1, testPhotoHeader("pod.jpg"), "Sari"); err != nil {
		t.Fatalf("SetDeliveryOrderPOD: %v", err)
	}
	if !saverCalled {
		t.Error("POD saver was not called for an attached photo")
	}
	d := fs.dos[1]
	if !d.ProofPhotoUrl.Valid || !strings.HasPrefix(d.ProofPhotoUrl.String, "/uploads/") {
		t.Fatalf("photoURL = %v, want an /uploads/ path", d.ProofPhotoUrl)
	}
	if d.PodRecipientName.String != "Sari" {
		t.Errorf("recipient = %q, want Sari", d.PodRecipientName.String)
	}
}

// A saver that fails must abort the write — losing evidence quietly is worse
// than refusing the completion.
func TestSetDeliveryOrderPOD_SaverFailureAborts(t *testing.T) {
	fs := newFakeStore()
	fs.dos[1] = &db.GetDeliveryOrderByIDRow{}
	svc := NewService(fs, nil, nil).WithPODSaver(func(_ context.Context, _ *multipart.FileHeader) (string, error) {
		return "", errors.New("storage unavailable")
	})
	tx := &fakeTx{store: fs}
	if err := svc.SetDeliveryOrderPOD(context.Background(), tx, 1, testPhotoHeader("pod.jpg"), "Sari"); err == nil {
		t.Fatal("a failing saver must return an error")
	}
	if fs.dos[1].ProofPhotoUrl.Valid {
		t.Error("photo URL recorded despite the saver failing")
	}
}

func testPhotoHeader(name string) *multipart.FileHeader {
	return &multipart.FileHeader{Filename: name}
}
