package framework

import (
	"fmt"

	"github.com/smarty/assertions"
)

// CommonResponseChecker common response checker
type CommonResponseChecker struct {
	result *CaseResult
	origin string
}

// NewCommonResponseChecker creates a new common response checker
func NewCommonResponseChecker(result *CaseResult, origin string) *CommonResponseChecker {
	return &CommonResponseChecker{
		result: result,
		origin: origin,
	}
}

// CORSCheckOptions options for CORS header checking
type CORSCheckOptions struct {
	ExpectedOrigin      string // expected value for access-control-allow-origin
	CredentialsOptional bool   // if true, allow-credentials header can be absent
}

// CheckCORSHeaders checks CORS response headers (strict mode)
// The origin parameter passed to NewCommonResponseChecker determines the expected value.
// Pass ctx.Origin for strict mode, or "*" if the API returns wildcard origin.
func (c *CommonResponseChecker) CheckCORSHeaders(resp *Response) *CommonResponseChecker {
	return c.CheckCORSHeadersWithOptions(resp, CORSCheckOptions{
		ExpectedOrigin:      c.origin,
		CredentialsOptional: false,
	})
}

// CheckCORSHeadersWithOptions checks CORS response headers with custom options
func (c *CommonResponseChecker) CheckCORSHeadersWithOptions(resp *Response, opts CORSCheckOptions) *CommonResponseChecker {
	if resp == nil {
		c.result.AddError("Response is nil, cannot check CORS headers")
		return c
	}

	// Check access-control-allow-credentials
	allowCredentials := resp.Headers.Get("Access-Control-Allow-Credentials")
	if opts.CredentialsOptional {
		// Credentials header is optional, only validate if present
		if allowCredentials != "" && allowCredentials != "true" {
			c.result.AddError(fmt.Sprintf("access-control-allow-credentials should be true or absent, got: %s", allowCredentials))
		}
	} else {
		// Credentials header is required
		if msg := assertions.ShouldEqual(allowCredentials, "true"); msg != "" {
			c.result.AddError(fmt.Sprintf("access-control-allow-credentials should be true: %s", msg))
		}
	}

	// Check access-control-allow-origin (must match the expected origin)
	expectedOrigin := opts.ExpectedOrigin
	if expectedOrigin == "" {
		expectedOrigin = c.origin
	}
	allowOrigin := resp.Headers.Get("Access-Control-Allow-Origin")
	if msg := assertions.ShouldEqual(allowOrigin, expectedOrigin); msg != "" {
		c.result.AddError(fmt.Sprintf("access-control-allow-origin should be %s: %s", expectedOrigin, msg))
	}

	return c
}

// CheckStatusCode checks HTTP status code
func (c *CommonResponseChecker) CheckStatusCode(resp *Response, expected int) *CommonResponseChecker {
	if resp == nil {
		c.result.AddError("Response is nil, cannot check status code")
		return c
	}

	if msg := assertions.ShouldEqual(resp.StatusCode, expected); msg != "" {
		c.result.AddError(fmt.Sprintf("HTTP status code should be %d: %s", expected, msg))
	}

	return c
}

// Result returns the test result
func (c *CommonResponseChecker) Result() *CaseResult {
	return c.result
}
