package service

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/korap/korap-mcp/auth"
	"github.com/korap/korap-mcp/config"
)

// Client represents a KorAP API client
type Client struct {
	baseURL     string
	httpClient  *http.Client
	oauthClient *auth.OAuthClient
	cache       *Cache
}

// ClientOptions configures the KorAP client
type ClientOptions struct {
	BaseURL     string
	Timeout     time.Duration
	OAuthConfig *config.OAuthConfig
	CacheConfig *config.CacheConfig
}

// NewClient creates a new KorAP API client
func NewClient(opts ClientOptions) (*Client, error) {
	if opts.BaseURL == "" {
		return nil, fmt.Errorf("base URL is required")
	}

	// Ensure base URL ends with /
	baseURL := strings.TrimSuffix(opts.BaseURL, "/") + "/"

	// Set default timeout if not specified
	timeout := opts.Timeout
	if timeout == 0 {
		timeout = 30 * time.Second
	}

	client := &Client{
		baseURL: baseURL,
		httpClient: &http.Client{
			Timeout: timeout,
		},
	}

	// Initialize OAuth client if configuration is provided
	if opts.OAuthConfig != nil && opts.OAuthConfig.Enabled {
		oauthClient, err := auth.NewOAuthClient(opts.OAuthConfig)
		if err != nil {
			return nil, fmt.Errorf("failed to create OAuth client: %w", err)
		}
		client.oauthClient = oauthClient
	}

	// Initialize cache if configuration is provided
	if opts.CacheConfig != nil {
		cache, err := NewCache(opts.CacheConfig)
		if err != nil {
			return nil, fmt.Errorf("failed to create cache: %w", err)
		}
		client.cache = cache
	} else {
		// Use default cache configuration
		defaultConfig := config.DefaultCacheConfig()
		cache, err := NewCache(defaultConfig)
		if err != nil {
			return nil, fmt.Errorf("failed to create default cache: %w", err)
		}
		client.cache = cache
	}

	return client, nil
}

// SetOAuthClient sets the OAuth client for authentication
func (c *Client) SetOAuthClient(oauthClient *auth.OAuthClient) {
	c.oauthClient = oauthClient
}

// IsAuthenticated returns true if the client has valid authentication
func (c *Client) IsAuthenticated() bool {
	return c.oauthClient != nil && c.oauthClient.IsAuthenticated()
}

// AuthenticateWithClientCredentials performs client credentials OAuth flow
func (c *Client) AuthenticateWithClientCredentials(ctx context.Context) error {
	if c.oauthClient == nil {
		return fmt.Errorf("OAuth client not configured")
	}

	return c.oauthClient.ClientCredentialsFlow(ctx)
}

// buildURL constructs a full URL from the base URL and endpoint
func (c *Client) buildURL(endpoint string) (string, error) {
	endpoint = strings.TrimPrefix(endpoint, "/")
	if endpoint == "" {
		return c.baseURL, nil
	}
	fullURL, err := url.JoinPath(c.baseURL, endpoint)
	if err != nil {
		return "", fmt.Errorf("failed to build URL: %w", err)
	}
	return fullURL, nil
}

// doRequest performs an HTTP request with optional authentication
func (c *Client) doRequest(ctx context.Context, method, endpoint string, body io.Reader) (*http.Response, error) {
	fullURL, err := c.buildURL(endpoint)
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequestWithContext(ctx, method, fullURL, body)
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %w", err)
	}

	// Set common headers
	req.Header.Set("Accept", "application/json")
	if body != nil {
		req.Header.Set("Content-Type", "application/json")
	}

	// Add authentication if available
	if c.oauthClient != nil && c.oauthClient.IsAuthenticated() {
		if err := c.oauthClient.AddAuthHeader(req); err != nil {
			return nil, fmt.Errorf("failed to add auth header: %w", err)
		}
	}

	// Use OAuth HTTP client if available, otherwise use default client
	httpClient := c.httpClient
	if c.oauthClient != nil {
		httpClient = c.oauthClient.GetHTTPClient()
	}

	resp, err := httpClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("request failed: %w", err)
	}

	return resp, nil
}

// Get performs a GET request to the specified endpoint
func (c *Client) Get(ctx context.Context, endpoint string) (*http.Response, error) {
	return c.doRequest(ctx, http.MethodGet, endpoint, nil)
}

// Post performs a POST request to the specified endpoint with JSON body
func (c *Client) Post(ctx context.Context, endpoint string, body any) (*http.Response, error) {
	var bodyReader io.Reader
	if body != nil {
		jsonBody, err := json.Marshal(body)
		if err != nil {
			return nil, fmt.Errorf("failed to marshal request body: %w", err)
		}
		bodyReader = strings.NewReader(string(jsonBody))
	}

	return c.doRequest(ctx, http.MethodPost, endpoint, bodyReader)
}

// GetJSON performs a GET request and unmarshals the JSON response with caching
func (c *Client) GetJSON(ctx context.Context, endpoint string, target any) error {
	// Generate cache key for GET requests
	cacheKey := ""
	if c.cache != nil {
		// For GET requests, we can cache based on endpoint and query parameters
		// Extract query parameters from endpoint if any
		endpointURL, _ := url.Parse(endpoint)
		params := make(map[string]any)
		for key, values := range endpointURL.Query() {
			if len(values) > 0 {
				params[key] = values[0]
			}
		}
		cacheKey = c.cache.generateCacheKey("GET", endpointURL.Path, params)

		// Try to get from cache first
		if cachedData, found := c.cache.Get(ctx, cacheKey); found {
			if err := json.Unmarshal(cachedData, target); err == nil {
				return nil
			}
			// If unmarshal fails, continue with API call
		}
	}

	resp, err := c.Get(ctx, endpoint)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return c.handleErrorResponse(resp)
	}

	// Read response body
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("failed to read response body: %w", err)
	}

	// Unmarshal JSON
	if err := json.Unmarshal(body, target); err != nil {
		return fmt.Errorf("failed to decode JSON response: %w", err)
	}

	// Cache the response for GET requests
	if c.cache != nil && cacheKey != "" {
		ttl := c.cache.GetTTLForEndpoint(endpoint)
		c.cache.Set(ctx, cacheKey, body, ttl)
	}

	return nil
}

// PostJSON performs a POST request and unmarshals the JSON response
func (c *Client) PostJSON(ctx context.Context, endpoint string, body any, target any) error {
	resp, err := c.Post(ctx, endpoint, body)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return c.handleErrorResponse(resp)
	}

	if target != nil {
		if err := json.NewDecoder(resp.Body).Decode(target); err != nil {
			return fmt.Errorf("failed to decode JSON response: %w", err)
		}
	}

	return nil
}

// handleErrorResponse processes error responses from the KorAP API
func (c *Client) handleErrorResponse(resp *http.Response) error {
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("HTTP %d: failed to read error response", resp.StatusCode)
	}

	// Try to parse as KorAP error response
	var errorResp ErrorResponse
	if json.Unmarshal(body, &errorResp) == nil && errorResp.Error != "" {
		return &APIError{
			StatusCode: resp.StatusCode,
			Message:    errorResp.Error,
			Details:    errorResp.ErrorDescription,
		}
	}

	// Fallback to generic error
	return &APIError{
		StatusCode: resp.StatusCode,
		Message:    fmt.Sprintf("HTTP %d", resp.StatusCode),
		Details:    string(body),
	}
}

// GetBaseURL returns the base URL of the KorAP instance
func (c *Client) GetBaseURL() string {
	return c.baseURL
}

// Ping checks if the KorAP server is reachable
func (c *Client) Ping(ctx context.Context) error {
	resp, err := c.Get(ctx, "")
	if err != nil {
		return fmt.Errorf("failed to ping KorAP server: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 500 {
		return fmt.Errorf("KorAP server error: HTTP %d", resp.StatusCode)
	}

	return nil
}

// GetCache returns the cache instance (for testing and monitoring)
func (c *Client) GetCache() *Cache {
	return c.cache
}

// Close closes the client and cleans up resources
func (c *Client) Close() error {
	if c.cache != nil {
		return c.cache.Close()
	}
	return nil
}
