package handler

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

	"github.com/gofiber/fiber/v2"
)

// helper to build a Fiber app with the handler route mounted.
func newTestApp(h *AuthHandler) *fiber.App {
	app := fiber.New()
	app.Post("/api/v1/auth/password/reset/complete", h.CompletePasswordReset)
	return app
}

func TestCompletePasswordReset_MissingLoginID(t *testing.T) {
	h := &AuthHandler{}
	app := newTestApp(h)

	body, _ := json.Marshal(map[string]string{
		"newPassword": "Password1!",
	})

	req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/password/reset/complete", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")

	resp, err := app.Test(req)
	if err != nil {
		t.Fatalf("request failed: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusBadRequest {
		t.Fatalf("expected 400 for missing loginId, got %d", resp.StatusCode)
	}

	var got map[string]string
	if err := json.NewDecoder(resp.Body).Decode(&got); err != nil {
		t.Fatalf("failed to decode response: %v", err)
	}
	if got["error"] != "Login ID and new password are required" {
		t.Fatalf("unexpected error message: %v", got["error"])
	}
}

func TestCompletePasswordReset_InvalidPasswordPolicy(t *testing.T) {
	h := &AuthHandler{}
	app := newTestApp(h)

	body, _ := json.Marshal(map[string]string{
		"newPassword": "short", // too short + missing complexity
	})

	req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/password/reset/complete?loginId=user@example.com", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")

	resp, err := app.Test(req)
	if err != nil {
		t.Fatalf("request failed: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusBadRequest {
		t.Fatalf("expected 400 for weak password, got %d", resp.StatusCode)
	}

	var got map[string]string
	if err := json.NewDecoder(resp.Body).Decode(&got); err != nil {
		t.Fatalf("failed to decode response: %v", err)
	}
	if got["error"] != "Password must be at least 8 characters long" {
		t.Fatalf("unexpected error message: %v", got["error"])
	}
}

func TestCompletePasswordReset_NilDescopeClient(t *testing.T) {
	h := &AuthHandler{} // DescopeClient intentionally nil to hit the configuration error branch
	app := newTestApp(h)

	body, _ := json.Marshal(map[string]string{
		"newPassword": "StrongPass1!",
	})

	req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/password/reset/complete?loginId=user@example.com", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")

	resp, err := app.Test(req)
	if err != nil {
		t.Fatalf("request failed: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusInternalServerError {
		t.Fatalf("expected 500 when Descope client is nil, got %d", resp.StatusCode)
	}

	var got map[string]string
	if err := json.NewDecoder(resp.Body).Decode(&got); err != nil {
		t.Fatalf("failed to decode response: %v", err)
	}
	if got["error"] != "Authentication service not configured" {
		t.Fatalf("unexpected error message: %v", got["error"])
	}
}
