package workspace

import (
	"bytes"
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/go-chi/chi/v5"
	"github.com/google/uuid"
	"github.com/stretchr/testify/require"

	"github.com/yan1h/agent-coding-workflow/internal/transport/http/middleware"
)

// fakeWS / fakeWT / fakeGOP 是 handler 单测用的桩（只覆盖必要方法）。
type fakeWS struct{ created *Workspace }

func (f *fakeWS) Create(_ context.Context, _ Caller, _ string, _ CreateWorkspaceInput) (*Workspace, error) {
	w := &Workspace{ID: uuid.New(), Slug: "ws1", Name: "W1", SyncStatus: SyncStatusCloning}
	f.created = w
	return w, nil
}

func (f *fakeWS) Get(_ context.Context, _ Caller, id uuid.UUID) (*Workspace, error) {
	return &Workspace{ID: id, Slug: "ws1"}, nil
}

func (f *fakeWS) List(_ context.Context, _ Caller, _ string) ([]*Workspace, error) { return nil, nil }

func (f *fakeWS) Update(_ context.Context, _ Caller, id uuid.UUID, _ UpdateWorkspaceInput) (*Workspace, error) {
	return &Workspace{ID: id}, nil
}

func (f *fakeWS) Delete(_ context.Context, _ Caller, _ uuid.UUID) error { return nil }

func (f *fakeWS) Sync(_ context.Context, _ Caller, id uuid.UUID) (*Workspace, error) {
	return &Workspace{ID: id, SyncStatus: SyncStatusIdle}, nil
}

func (f *fakeWS) UpsertCredential(_ context.Context, _ Caller, _ uuid.UUID, _ UpsertCredentialInput) (*Credential, error) {
	return &Credential{Kind: CredKindPAT, Fingerprint: "****abcd"}, nil
}

func (f *fakeWS) GetCredentialMeta(_ context.Context, _ Caller, _ uuid.UUID) (*Credential, error) {
	return &Credential{Kind: CredKindNone}, nil
}

func (f *fakeWS) ListBranches(_ context.Context, _ Caller, _ uuid.UUID) ([]string, error) {
	return []string{"main", "develop"}, nil
}

// fakeResolver 把固定 token 解码为 uuid（沿 internal/project handler_test.go 模式）。
type fakeResolver struct{ valid map[string]uuid.UUID }

func (f *fakeResolver) ResolveSession(_ context.Context, token string) (uuid.UUID, bool, error) {
	uid, ok := f.valid[token]
	return uid, ok, nil
}

// fakeAdmin 始终返回 false。
type fakeAdmin struct{}

func (fakeAdmin) IsAdmin(_ context.Context, _ uuid.UUID) (bool, error) { return false, nil }

func TestHandler_CreateWorkspace_Smoke(t *testing.T) {
	t.Parallel()
	ws := &fakeWS{}
	uid := uuid.New()
	tok := "tok-1"
	resolver := &fakeResolver{valid: map[string]uuid.UUID{tok: uid}}
	h := NewHandler(ws, nil, nil, resolver, fakeAdmin{})
	r := chi.NewRouter()
	r.Use(middleware.RequestID)
	h.Mount(r)

	body, _ := json.Marshal(createWorkspaceReq{
		Slug: "ws1", Name: "W1", GitRemoteURL: "https://x",
		Credential: credentialBody{Kind: "none"},
	})
	req := httptest.NewRequest("POST", "/api/v1/projects/p/workspaces", bytes.NewReader(body))
	req.Header.Set("Authorization", "Bearer "+tok)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	require.Equal(t, http.StatusCreated, w.Code)
}

func TestHandler_ListBranches_Smoke(t *testing.T) {
	t.Parallel()
	ws := &fakeWS{}
	uid := uuid.New()
	tok := "tok-branches"
	resolver := &fakeResolver{valid: map[string]uuid.UUID{tok: uid}}
	h := NewHandler(ws, nil, nil, resolver, fakeAdmin{})
	r := chi.NewRouter()
	r.Use(middleware.RequestID)
	h.Mount(r)

	wsID := uuid.New()
	req := httptest.NewRequest("GET", "/api/v1/workspaces/"+wsID.String()+"/branches", nil)
	req.Header.Set("Authorization", "Bearer "+tok)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	require.Equal(t, http.StatusOK, w.Code)

	var resp branchListResp
	require.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
	require.Equal(t, []string{"main", "develop"}, resp.Branches)
}
