package giphy

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"time"
)

const apiBase = "https://api.giphy.com/v1/gifs"

type Client struct {
	apiKey string
	client *http.Client
}

func NewClient(apiKey string) *Client {
	if apiKey == "" {
		return nil
	}
	return &Client{
		apiKey: apiKey,
		client: &http.Client{Timeout: 10 * time.Second},
	}
}

type Image struct {
	URL    string `json:"url"`
	Width  string `json:"width"`
	Height string `json:"height"`
}

type Images struct {
	Original    Image `json:"original"`
	FixedHeight Image `json:"fixed_height"`
	FixedWidth  Image `json:"fixed_width"`
}

type Gif struct {
	ID       string `json:"id"`
	Title    string `json:"title"`
	URL      string `json:"url"`
	Slug     string `json:"slug"`
	Images   Images `json:"images"`
	Username string `json:"username"`
}

type SearchResponse struct {
	Data []Gif `json:"data"`
}

func (c *Client) Search(query string, limit int) ([]Gif, error) {
	if c == nil {
		return nil, fmt.Errorf("giphy client not configured")
	}
	if limit <= 0 || limit > 50 {
		limit = 25
	}

	u, err := url.Parse(apiBase + "/search")
	if err != nil {
		return nil, err
	}
	q := u.Query()
	q.Set("api_key", c.apiKey)
	q.Set("q", query)
	q.Set("limit", fmt.Sprintf("%d", limit))
	q.Set("rating", "pg-13")
	q.Set("lang", "en")
	u.RawQuery = q.Encode()

	req, err := http.NewRequest("GET", u.String(), nil)
	if err != nil {
		return nil, err
	}

	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("giphy API returned %d", resp.StatusCode)
	}

	var sr SearchResponse
	if err := json.NewDecoder(resp.Body).Decode(&sr); err != nil {
		return nil, err
	}

	return sr.Data, nil
}

func (c *Client) GetTrending(limit int) ([]Gif, error) {
	if c == nil {
		return nil, fmt.Errorf("giphy client not configured")
	}
	if limit <= 0 || limit > 50 {
		limit = 25
	}

	u, err := url.Parse(apiBase + "/trending")
	if err != nil {
		return nil, err
	}
	q := u.Query()
	q.Set("api_key", c.apiKey)
	q.Set("limit", fmt.Sprintf("%d", limit))
	q.Set("rating", "pg-13")
	u.RawQuery = q.Encode()

	resp, err := c.client.Get(u.String())
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("giphy API returned %d", resp.StatusCode)
	}

	var sr SearchResponse
	if err := json.NewDecoder(resp.Body).Decode(&sr); err != nil {
		return nil, err
	}

	return sr.Data, nil
}
