package main

import (
	"encoding/json"
	"io"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"testing"

	"github.com/evanreichard/markdown-editor/internal/api"
	"github.com/evanreichard/markdown-editor/internal/logger"
	"github.com/gorilla/mux"
	"github.com/stretchr/testify/assert"
)

func TestFileListing(t *testing.T) {
	dataDir, err := setupTestDir()
	if err != nil {
		t.Fatalf("Failed to create test dir: %v", err)
	}
	defer cleanupTestDir(dataDir)

	// Create some test files
	testFiles := []string{
		"file1.md",
		"file2.md",
		"file3.md",
	}
	
	for _, filename := range testFiles {
		filepath := filepath.Join(dataDir, filename)
		content := "# " + filename + "\n\nContent of " + filename
		if err := os.WriteFile(filepath, []byte(content), 0644); err != nil {
			t.Fatalf("Failed to create test file %s: %v", filename, err)
		}
	}

	log := logger.NewLogger()
	handler := api.NewAPIHandler(dataDir, log)
	router := mux.NewRouter()
	router.Handle("/api", handler).Methods("GET")
	router.Handle("/api/{filename:.+\\.md}", handler)

	// Test GET /api (list files)
	req := httptest.NewRequest("GET", "/api", nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)
	
	var response struct {
		Files []string `json:"files"`
	}
	body, _ := io.ReadAll(w.Body)
	assert.NoError(t, json.Unmarshal(body, &response))
	
	// Verify all test files are returned
	assert.Len(t, response.Files, 3)
	assert.Contains(t, response.Files, "file1.md")
	assert.Contains(t, response.Files, "file2.md")
	assert.Contains(t, response.Files, "file3.md")
}

func TestFileListingWithNonMarkdownFiles(t *testing.T) {
	dataDir, err := setupTestDir()
	if err != nil {
		t.Fatalf("Failed to create test dir: %v", err)
	}
	defer cleanupTestDir(dataDir)

	// Create test files including non-markdown files
	testFiles := []string{
		"file1.md",
		"file2.txt",
		"file3.md",
		"file4.log",
	}
	
	for _, filename := range testFiles {
		filepath := filepath.Join(dataDir, filename)
		content := "Content of " + filename
		if err := os.WriteFile(filepath, []byte(content), 0644); err != nil {
			t.Fatalf("Failed to create test file %s: %v", filename, err)
		}
	}

	log := logger.NewLogger()
	handler := api.NewAPIHandler(dataDir, log)
	router := mux.NewRouter()
	router.Handle("/api", handler).Methods("GET")
	router.Handle("/api/{filename:.+\\.md}", handler)

	// Test GET /api (list files)
	req := httptest.NewRequest("GET", "/api", nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)
	
	var response struct {
		Files []string `json:"files"`
	}
	body, _ := io.ReadAll(w.Body)
	assert.NoError(t, json.Unmarshal(body, &response))
	
	// Verify only markdown files are returned
	assert.Len(t, response.Files, 2)
	assert.Contains(t, response.Files, "file1.md")
	assert.Contains(t, response.Files, "file3.md")
	assert.NotContains(t, response.Files, "file2.txt")
	assert.NotContains(t, response.Files, "file4.log")
}

func TestFileListingEmptyDirectory(t *testing.T) {
	dataDir, err := setupTestDir()
	if err != nil {
		t.Fatalf("Failed to create test dir: %v", err)
	}
	defer cleanupTestDir(dataDir)

	log := logger.NewLogger()
	handler := api.NewAPIHandler(dataDir, log)
	router := mux.NewRouter()
	router.Handle("/api", handler).Methods("GET")
	router.Handle("/api/{filename:.+\\.md}", handler)

	// Test GET /api (list files in empty directory)
	req := httptest.NewRequest("GET", "/api", nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)
	
	var response struct {
		Files []string `json:"files"`
	}
	body, _ := io.ReadAll(w.Body)
	assert.NoError(t, json.Unmarshal(body, &response))
	
	// Verify empty array is returned
	assert.Len(t, response.Files, 0)
}
