package http

import (
	"database/sql"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/example/storage-appliance/internal/service/mock"
)

func TestPoolsHandler(t *testing.T) {
	m := &mock.MockZFSService{}
	app := &App{DB: &sql.DB{}, ZFSSvc: m}
	req := httptest.NewRequest(http.MethodGet, "/api/pools", nil)
	w := httptest.NewRecorder()
	app.PoolsHandler(w, req)
	if w.Code != http.StatusOK {
		t.Fatalf("expected 200, got %d", w.Code)
	}
	body := w.Body.String()
	if body == "" {
		t.Fatalf("expected non-empty body")
	}
}

func TestCreatePoolHandler(t *testing.T) {
	m := &mock.MockZFSService{}
	j := &mock.MockJobRunner{}
	app := &App{DB: &sql.DB{}, ZFSSvc: m, JobRunner: j}
	body := `{"name":"tank","vdevs":["/dev/sda"]}`
	req := httptest.NewRequest(http.MethodPost, "/api/pools", strings.NewReader(body))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-Auth-User", "admin")
	req.Header.Set("X-Auth-Role", "admin")
	w := httptest.NewRecorder()
	app.CreatePoolHandler(w, req)
	if w.Code != http.StatusOK {
		t.Fatalf("expected 200, got %d", w.Code)
	}
	if !strings.Contains(w.Body.String(), "job_id") {
		t.Fatalf("expected job_id in response")
	}
}

func TestSharesNFSHandler(t *testing.T) {
	m := &mock.MockSharesService{}
	app := &App{DB: &sql.DB{}, ShareSvc: m}
	req := httptest.NewRequest(http.MethodGet, "/shares/nfs", nil)
	w := httptest.NewRecorder()
	app.SharesNFSHandler(w, req)
	if w.Code != http.StatusOK {
		t.Fatalf("expected 200, got %d; body: %s", w.Code, w.Body.String())
	}
}

func TestCreateNFSHandler(t *testing.T) {
	m := &mock.MockSharesService{}
	app := &App{DB: &sql.DB{}, ShareSvc: m}
	form := "name=data&path=tank/ds&options={}" // simple form body
	req := httptest.NewRequest(http.MethodPost, "/shares/nfs/create", strings.NewReader(form))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("X-Auth-User", "admin")
	req.Header.Set("X-Auth-Role", "admin")
	w := httptest.NewRecorder()
	app.CreateNFSHandler(w, req)
	if w.Code != http.StatusOK {
		t.Fatalf("expected 200, got %d; body: %s", w.Code, w.Body.String())
	}
}

func TestNFSStatusHandler(t *testing.T) {
	m := &mock.MockSharesService{}
	app := &App{DB: &sql.DB{}, ShareSvc: m}
	req := httptest.NewRequest(http.MethodGet, "/api/shares/nfs/status", nil)
	w := httptest.NewRecorder()
	app.NFSStatusHandler(w, req)
	if w.Code != http.StatusOK {
		t.Fatalf("expected 200, got %d; body: %s", w.Code, w.Body.String())
	}
}

func TestSharesSMBHandler(t *testing.T) {
	m := &mock.MockSharesService{}
	app := &App{DB: &sql.DB{}, ShareSvc: m}
	req := httptest.NewRequest(http.MethodGet, "/shares/smb", nil)
	w := httptest.NewRecorder()
	app.SharesSMBHandler(w, req)
	if w.Code != http.StatusOK {
		t.Fatalf("expected 200, got %d; body: %s", w.Code, w.Body.String())
	}
}

func TestCreateSMBHandler(t *testing.T) {
	m := &mock.MockSharesService{}
	app := &App{DB: &sql.DB{}, ShareSvc: m}
	form := "name=smb1&path=tank/ds&allowed_users=user1,user2&read_only=1"
	req := httptest.NewRequest(http.MethodPost, "/shares/smb/create", strings.NewReader(form))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("X-Auth-User", "admin")
	req.Header.Set("X-Auth-Role", "admin")
	w := httptest.NewRecorder()
	app.CreateSMBHandler(w, req)
	if w.Code != http.StatusOK {
		t.Fatalf("expected 200, got %d; body: %s", w.Code, w.Body.String())
	}
}

func TestDeleteSMBHandler(t *testing.T) {
	m := &mock.MockSharesService{}
	app := &App{DB: &sql.DB{}, ShareSvc: m}
	form := "id=smb-1"
	req := httptest.NewRequest(http.MethodPost, "/shares/smb/delete", strings.NewReader(form))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("X-Auth-User", "admin")
	req.Header.Set("X-Auth-Role", "admin")
	w := httptest.NewRecorder()
	app.DeleteSMBHandler(w, req)
	if w.Code != http.StatusOK {
		t.Fatalf("expected 200, got %d; body: %s", w.Code, w.Body.String())
	}
}
