package handlers

import (
	"context"
	"errors"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/gofiber/fiber/v2"

	filemanager "wucher/internal/domain/file_manager"
	"wucher/internal/shared/pkg/attachmentresolver"
	"wucher/internal/shared/pkg/uuidv7"
)

func TestAttachmentResolverHelpers(t *testing.T) {
	app := fiber.New()
	app.Get("/invalid-attachment", func(c *fiber.Ctx) error {
		raw := "bad"
		_, handled := resolveAttachmentIDFromInput(c, attachmentresolver.Params{
			RawAttachmentID: &raw,
			AttachmentField: "attachment_id",
			FileField:       "file_uuid",
		}, "Update failed")
		if !handled {
			t.Fatalf("expected handled invalid attachment")
		}
		return nil
	})
	app.Get("/invalid-file", func(c *fiber.Ctx) error {
		raw := "bad"
		_, handled := resolveAttachmentIDFromInput(c, attachmentresolver.Params{
			RawFileID:   &raw,
			FileManager: &fileManagerAttachmentHandlerServiceMock{},
		}, "Update failed")
		if !handled {
			t.Fatalf("expected handled invalid file")
		}
		return nil
	})
	app.Get("/cannot-resolve", func(c *fiber.Ctx) error {
		raw := mustUUIDStringContact(t, uuidv7.MustBytes())
		_, handled := resolveAttachmentIDFromInput(c, attachmentresolver.Params{
			RawFileID: &raw,
			FileManager: &fileManagerAttachmentHandlerServiceMock{
				createAttachmentFn: func(context.Context, filemanager.CreateAttachmentParams) (*filemanager.Attachment, error) {
					return nil, filemanager.ErrAttachmentAlreadyExists
				},
				listAttachmentsFn: func(context.Context, filemanager.ListAttachmentsParams) ([]filemanager.Attachment, int64, error) {
					return nil, 0, nil
				},
			},
		}, "Update failed")
		if !handled {
			t.Fatalf("expected handled cannot resolve")
		}
		return nil
	})
	app.Get("/not-ready", func(c *fiber.Ctx) error {
		raw := mustUUIDStringContact(t, uuidv7.MustBytes())
		_, handled := resolveAttachmentIDFromInput(c, attachmentresolver.Params{
			RawFileID: &raw,
			FileManager: &fileManagerAttachmentHandlerServiceMock{
				createAttachmentFn: func(context.Context, filemanager.CreateAttachmentParams) (*filemanager.Attachment, error) {
					return nil, filemanager.ErrFileNotReadyForAttachment
				},
				getFileFn: func(context.Context, []byte) (*filemanager.File, error) {
					return &filemanager.File{Status: filemanager.FileStatusUploaded}, nil
				},
			},
		}, "Update failed")
		if !handled {
			t.Fatalf("expected handled file-not-ready")
		}
		return nil
	})
	app.Get("/bad-request", func(c *fiber.Ctx) error {
		raw := mustUUIDStringContact(t, uuidv7.MustBytes())
		_, handled := resolveAttachmentIDFromInput(c, attachmentresolver.Params{
			RawAttachmentID:          &raw,
			ValidateAttachmentExists: true,
			AttachmentExists: func(context.Context, []byte) (bool, error) {
				return false, errors.New("db down")
			},
		}, "Update failed")
		if !handled {
			t.Fatalf("expected handled bad request")
		}
		return nil
	})

	for _, path := range []string{"/invalid-attachment", "/invalid-file", "/cannot-resolve", "/not-ready", "/bad-request"} {
		resp, err := app.Test(httptest.NewRequest(http.MethodGet, path, nil), 30000)
		if err != nil {
			t.Fatalf("%s err: %v", path, err)
		}
		if resp.StatusCode == http.StatusOK {
			t.Fatalf("expected non-200 for %s", path)
		}
	}
}

func TestOptionalStringHelpers(t *testing.T) {
	if hasNonEmptyOptionalString(nil) || hasBlankOptionalString(nil) {
		t.Fatalf("nil optional helpers should be false")
	}
	blank := " "
	if hasNonEmptyOptionalString(&blank) || !hasBlankOptionalString(&blank) {
		t.Fatalf("blank optional helper mismatch")
	}
	val := "x"
	if !hasNonEmptyOptionalString(&val) || hasBlankOptionalString(&val) {
		t.Fatalf("non-blank optional helper mismatch")
	}
	if fieldOrDefault("", "a") != "a" || fieldOrDefault("x", "a") != "x" {
		t.Fatalf("fieldOrDefault mismatch")
	}
}
