package handlers

import (
	"context"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

func TestGetTabloDetailPage_Returns200(t *testing.T) {
	handler := newTestAuthHandler(t)
	sessionCookie := loginTestUser(t, handler, "demo@xtablo.com", "xtablo-demo")

	// Create a tablo owned by demo user
	user, err := handler.repo.(interface {
		GetAuthUserByEmail(ctx context.Context, email string) (AuthUser, error)
	}).GetAuthUserByEmail(context.Background(), "demo@xtablo.com")
	if err != nil {
		t.Fatalf("get demo user: %v", err)
	}

	tablo, err := handler.repo.CreateTablo(context.Background(), CreateTabloInput{
		OwnerID: user.ID,
		Name:    "Test Project",
		Status:  TabloStatusTodo,
		Color:   "#3B82F6",
	})
	if err != nil {
		t.Fatalf("create tablo: %v", err)
	}

	req := httptest.NewRequest(http.MethodGet, "/tablos/"+tablo.ID.String(), nil)
	req.SetPathValue("tabloID", tablo.ID.String())
	req.AddCookie(sessionCookie)
	rec := httptest.NewRecorder()

	handler.GetTabloDetailPage().ServeHTTP(rec, req)

	if rec.Code != http.StatusOK {
		t.Fatalf("expected 200, got %d\nbody: %s", rec.Code, rec.Body.String())
	}

	body := rec.Body.String()
	if !strings.Contains(body, "Test Project") {
		t.Errorf("expected body to contain tablo name 'Test Project', got: %s", body[:min(len(body), 500)])
	}
}

func TestGetTabloDetailPage_Returns404(t *testing.T) {
	handler := newTestAuthHandler(t)
	sessionCookie := loginTestUser(t, handler, "demo@xtablo.com", "xtablo-demo")

	// Use a random UUID that doesn't belong to the user
	unknownID := "00000000-0000-0000-0000-000000000099"

	req := httptest.NewRequest(http.MethodGet, "/tablos/"+unknownID, nil)
	req.SetPathValue("tabloID", unknownID)
	req.AddCookie(sessionCookie)
	rec := httptest.NewRecorder()

	handler.GetTabloDetailPage().ServeHTTP(rec, req)

	if rec.Code != http.StatusNotFound {
		t.Fatalf("expected 404, got %d", rec.Code)
	}
}

func TestGetTabloDetailPage_Returns400(t *testing.T) {
	handler := newTestAuthHandler(t)
	sessionCookie := loginTestUser(t, handler, "demo@xtablo.com", "xtablo-demo")

	req := httptest.NewRequest(http.MethodGet, "/tablos/not-a-uuid", nil)
	req.SetPathValue("tabloID", "not-a-uuid")
	req.AddCookie(sessionCookie)
	rec := httptest.NewRecorder()

	handler.GetTabloDetailPage().ServeHTTP(rec, req)

	if rec.Code != http.StatusBadRequest {
		t.Fatalf("expected 400, got %d", rec.Code)
	}
}

func TestGetTabloDetailPage_Unauthenticated(t *testing.T) {
	handler := newTestAuthHandler(t)

	req := httptest.NewRequest(http.MethodGet, "/tablos/00000000-0000-0000-0000-000000000001", nil)
	req.SetPathValue("tabloID", "00000000-0000-0000-0000-000000000001")
	rec := httptest.NewRecorder()

	handler.GetTabloDetailPage().ServeHTTP(rec, req)

	if rec.Code != http.StatusSeeOther {
		t.Fatalf("expected 302 redirect to /login, got %d", rec.Code)
	}

	location := rec.Header().Get("Location")
	if location != "/login" {
		t.Errorf("expected redirect to /login, got %q", location)
	}
}

func TestTabloDetailKanbanColumns(t *testing.T) {
	handler := newTestAuthHandler(t)
	sessionCookie := loginTestUser(t, handler, "demo@xtablo.com", "xtablo-demo")

	user, err := handler.repo.(interface {
		GetAuthUserByEmail(ctx context.Context, email string) (AuthUser, error)
	}).GetAuthUserByEmail(context.Background(), "demo@xtablo.com")
	if err != nil {
		t.Fatalf("get demo user: %v", err)
	}

	tablo, err := handler.repo.CreateTablo(context.Background(), CreateTabloInput{
		OwnerID: user.ID,
		Name:    "Kanban Test",
		Status:  TabloStatusTodo,
		Color:   "#3B82F6",
	})
	if err != nil {
		t.Fatalf("create tablo: %v", err)
	}

	req := httptest.NewRequest(http.MethodGet, "/tablos/"+tablo.ID.String(), nil)
	req.SetPathValue("tabloID", tablo.ID.String())
	req.AddCookie(sessionCookie)
	rec := httptest.NewRecorder()

	handler.GetTabloDetailPage().ServeHTTP(rec, req)

	if rec.Code != http.StatusOK {
		t.Fatalf("expected 200, got %d", rec.Code)
	}

	body := rec.Body.String()
	for _, status := range []string{"todo", "in_progress", "in_review", "done"} {
		if !strings.Contains(body, status) {
			t.Errorf("expected body to contain kanban column status %q", status)
		}
	}
}

func TestGetTabloDetailPage_ContainsSortableScript(t *testing.T) {
	handler := newTestAuthHandler(t)
	sessionCookie := loginTestUser(t, handler, "demo@xtablo.com", "xtablo-demo")

	user, err := handler.repo.(interface {
		GetAuthUserByEmail(ctx context.Context, email string) (AuthUser, error)
	}).GetAuthUserByEmail(context.Background(), "demo@xtablo.com")
	if err != nil {
		t.Fatalf("get demo user: %v", err)
	}

	tablo, err := handler.repo.CreateTablo(context.Background(), CreateTabloInput{
		OwnerID: user.ID,
		Name:    "Sortable Test",
		Status:  TabloStatusTodo,
		Color:   "#3B82F6",
	})
	if err != nil {
		t.Fatalf("create tablo: %v", err)
	}

	req := httptest.NewRequest(http.MethodGet, "/tablos/"+tablo.ID.String(), nil)
	req.SetPathValue("tabloID", tablo.ID.String())
	req.AddCookie(sessionCookie)
	rec := httptest.NewRecorder()

	handler.GetTabloDetailPage().ServeHTTP(rec, req)

	if rec.Code != http.StatusOK {
		t.Fatalf("expected 200, got %d", rec.Code)
	}

	body := rec.Body.String()
	if !strings.Contains(body, "initTabloDetailSortable") {
		t.Errorf("expected body to contain 'initTabloDetailSortable', got body[:500]: %s", body[:min(len(body), 500)])
	}
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}
