package arxiv

import (
	"context"
	"encoding/xml"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"time"
)

// Client represents an arXiv API client
type Client struct {
	baseURL    string
	httpClient *http.Client
}

// NewClient creates a new arXiv API client
func NewClient() *Client {
	return &Client{
		baseURL:    "http://export.arxiv.org/api/query",
		httpClient: &http.Client{Timeout: 30 * time.Second},
	}
}

// Query represents search parameters for arXiv API
type Query struct {
	Category    string
	DateRange   string
	MaxResults  int
	StartOffset int
}

// Paper represents a single arXiv paper
type Paper struct {
	ID        string    `xml:"id"`
	Title     string    `xml:"title"`
	Summary   string    `xml:"summary"`
	Published time.Time `xml:"published"`
	Updated   time.Time `xml:"updated"`
	Authors   []Author  `xml:"author"`
}

// Author represents a paper author
type Author struct {
	Name string `xml:"name"`
}

// FetchPapers retrieves papers from arXiv API
func (c *Client) FetchPapers(ctx context.Context, query Query) ([]Paper, error) {
	params := url.Values{}
	params.Add("search_query", fmt.Sprintf("%s AND submittedDate:[%s]", query.Category, query.DateRange))
	params.Add("max_results", fmt.Sprintf("%d", query.MaxResults))
	params.Add("start", fmt.Sprintf("%d", query.StartOffset))

	resp, err := c.httpClient.Get(fmt.Sprintf("%s?%s", c.baseURL, params.Encode()))
	if err != nil {
		return nil, fmt.Errorf("failed to fetch papers: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
	}

	return parseResponse(resp.Body)
}

func parseResponse(r io.Reader) ([]Paper, error) {
	var feed struct {
		Entries []Paper `xml:"entry"`
	}
	if err := xml.NewDecoder(r).Decode(&feed); err != nil {
		return nil, fmt.Errorf("failed to parse response: %w", err)
	}
	return feed.Entries, nil
}
