package file

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

	"github.com/perfect-panel/server/internal/config"
	"github.com/perfect-panel/server/internal/svc"
	"github.com/perfect-panel/server/pkg/storage"
)

const testAllowedContentTypes = "application/zip,application/x-zip-compressed,application/gzip,application/x-gzip,application/octet-stream,text/plain,application/json,image/jpeg,image/jpg,image/png,image/webp,image/gif,image/heic,image/heif,image/bmp"

type testMultipartFile struct {
	*strings.Reader
}

func (testMultipartFile) Close() error {
	return nil
}

func TestValidateInitRequestAllowedContentTypes(t *testing.T) {
	svcCtx := &svc.ServiceContext{
		Config: config.Config{
			S3: config.S3Config{
				Enable:              true,
				MaxUploadSize:       1024,
				AllowedContentTypes: testAllowedContentTypes,
			},
		},
		S3Store: &storage.S3Store{},
	}

	tests := []struct {
		name        string
		contentType string
		wantErr     bool
	}{
		{name: "allow jpeg", contentType: "image/jpeg"},
		{name: "allow png", contentType: "image/png"},
		{name: "allow webp", contentType: "image/webp"},
		{name: "reject unknown", contentType: "application/x-sh", wantErr: true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := validateInitRequest(svcCtx, "app-package", "demo.bin", tt.contentType, 10)
			if tt.wantErr {
				if err == nil {
					t.Fatal("expected error, got nil")
				}
				if !strings.Contains(err.Error(), "content_type is not allowed") {
					t.Fatalf("expected content type error, got %v", err)
				}
				return
			}
			if err != nil {
				t.Fatalf("expected nil error, got %v", err)
			}
		})
	}
}

func TestSniffContentTypeDetectsCommonImages(t *testing.T) {
	tests := []struct {
		name string
		data string
		want string
	}{
		{name: "jpeg", data: "\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01", want: "image/jpeg"},
		{name: "png", data: "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR", want: "image/png"},
		{name: "webp", data: "RIFF\x1a\x00\x00\x00WEBPVP8 \x0e\x00\x00\x00", want: "image/webp"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			file := testMultipartFile{Reader: strings.NewReader(tt.data)}
			got, err := sniffContentType(&multipart.FileHeader{}, file)
			if err != nil {
				t.Fatalf("expected nil error, got %v", err)
			}
			if got != tt.want {
				t.Fatalf("expected %q, got %q", tt.want, got)
			}
			if pos, err := file.Seek(0, 1); err != nil || pos != 0 {
				t.Fatalf("expected reader reset to start, pos=%d err=%v", pos, err)
			}
		})
	}
}
