package service

import (
	"bytes"
	"context"
	"mime/multipart"
	"net/http/httptest"
	"strings"
	"testing"

	commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
	"gitlab.com/mbugroup/lti-api.git/internal/config"
	"gitlab.com/mbugroup/lti-api.git/internal/database"
	entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
	"gorm.io/gorm"
)

func TestDocumentServiceUpload(t *testing.T) {
	if strings.TrimSpace(config.S3Bucket) == "" {
		t.Fatal("S3 bucket is not configured; set S3_* env vars to run this test")
	}

	ctx := context.Background()
	db := setupDocumentTestDB(t)
	repo := commonRepo.NewDocumentRepository(db)

	svc, err := NewDocumentServiceFromConfig(ctx, repo)
	if err != nil {
		t.Fatalf("failed to create document service from config: %v", err)
	}

	file := newTestFileHeader(t, "integration-proof.txt", "text/plain", []byte("document integration test"))
	userID := uint(100)

	results, err := svc.UploadDocuments(ctx, DocumentUploadRequest{
		DocumentableType: "INVENTORY_TRANSFER",
		DocumentableID:   99,
		CreatedBy:        &userID,
		Files: []DocumentFile{
			{File: file, Type: "integration"},
		},
	})
	if err != nil {
		t.Fatalf("upload to S3 failed: %v", err)
	}
	if len(results) != 1 {
		t.Fatalf("expected 1 uploaded document, got %d", len(results))
	}

	doc := results[0].Document
	if doc.Path == "" {
		t.Fatalf("expected non-empty storage path")
	}
	if results[0].URL == "" {
		t.Fatalf("expected public URL for uploaded document")
	}

	t.Logf("uploaded document #%d to %s (path=%s)", doc.Id, results[0].URL, doc.Path)
}

func setupDocumentTestDB(t *testing.T) *gorm.DB {
	t.Helper()
	if strings.TrimSpace(config.DBHost) == "" || strings.TrimSpace(config.DBName) == "" {
		t.Fatal("database configuration missing; ensure DB_HOST and DB_NAME are set")
	}
	db := database.Connect(config.DBHost, config.DBName)
	if db == nil {
		t.Fatal("failed to create database connection")
	}
	if err := db.AutoMigrate(&entity.Document{}); err != nil {
		t.Fatalf("failed to migrate document table: %v", err)
	}
	return db
}

func newTestFileHeader(t *testing.T, filename, contentType string, data []byte) *multipart.FileHeader {
	t.Helper()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	part, err := writer.CreateFormFile("documents", filename)
	if err != nil {
		t.Fatalf("failed to create form file: %v", err)
	}
	if _, err := part.Write(data); err != nil {
		t.Fatalf("failed to write file data: %v", err)
	}
	if err := writer.Close(); err != nil {
		t.Fatalf("failed to close writer: %v", err)
	}

	req := httptest.NewRequest("POST", "http://example.com/upload", body)
	req.Header.Set("Content-Type", writer.FormDataContentType())

	_, fileHeader, err := req.FormFile("documents")
	if err != nil {
		t.Fatalf("failed to parse form file: %v", err)
	}
	fileHeader.Header.Set("Content-Type", contentType)
	return fileHeader
}
