package weather

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

	"github.com/paramah/ai_devs4/s01e03/internal/domain"
)

// APIClient implements domain.WeatherClient using wttr.in
type APIClient struct {
	baseURL string
	client  *http.Client
}

// NewAPIClient creates a new weather API client
// apiKey parameter is ignored as wttr.in doesn't require authentication
func NewAPIClient(baseURL, apiKey string) *APIClient {
	if baseURL == "" {
		baseURL = "https://wttr.in"
	}
	return &APIClient{
		baseURL: baseURL,
		client:  &http.Client{},
	}
}

type wttrResponse struct {
	CurrentCondition []struct {
		TempC       string `json:"temp_C"`
		Humidity    string `json:"humidity"`
		WeatherDesc []struct {
			Value string `json:"value"`
		} `json:"weatherDesc"`
	} `json:"current_condition"`
	NearestArea []struct {
		AreaName []struct {
			Value string `json:"value"`
		} `json:"areaName"`
	} `json:"nearest_area"`
}

// GetWeather gets weather information for a location using wttr.in
func (c *APIClient) GetWeather(ctx context.Context, location string) (*domain.WeatherInfo, error) {
	// Build URL - wttr.in format: https://wttr.in/Location?format=j1
	u, err := url.Parse(c.baseURL + "/" + url.PathEscape(location))
	if err != nil {
		return nil, fmt.Errorf("parsing URL: %w", err)
	}

	q := u.Query()
	q.Set("format", "j1")
	u.RawQuery = q.Encode()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
	if err != nil {
		return nil, fmt.Errorf("creating request: %w", err)
	}

	// wttr.in prefers this header to return JSON
	req.Header.Set("User-Agent", "curl/7.0")

	resp, err := c.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("sending request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return nil, fmt.Errorf("API error (status %d): %s", resp.StatusCode, string(body))
	}

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

	var apiResp wttrResponse
	if err := json.Unmarshal(body, &apiResp); err != nil {
		return nil, fmt.Errorf("unmarshaling response: %w", err)
	}

	if len(apiResp.CurrentCondition) == 0 {
		return nil, fmt.Errorf("no weather data available for location: %s", location)
	}

	current := apiResp.CurrentCondition[0]

	// Parse temperature
	temp, err := strconv.ParseFloat(current.TempC, 64)
	if err != nil {
		return nil, fmt.Errorf("parsing temperature: %w", err)
	}

	// Parse humidity
	humidity, err := strconv.Atoi(current.Humidity)
	if err != nil {
		return nil, fmt.Errorf("parsing humidity: %w", err)
	}

	// Get description
	description := "unknown"
	if len(current.WeatherDesc) > 0 {
		description = current.WeatherDesc[0].Value
	}

	// Get location name
	locationName := location
	if len(apiResp.NearestArea) > 0 && len(apiResp.NearestArea[0].AreaName) > 0 {
		locationName = apiResp.NearestArea[0].AreaName[0].Value
	}

	return &domain.WeatherInfo{
		Location:    locationName,
		Temperature: temp,
		Description: description,
		Humidity:    humidity,
	}, nil
}
