package hive

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

// HiveClient provides integration with the Hive task coordination system
type HiveClient struct {
	BaseURL    string
	APIKey     string
	HTTPClient *http.Client
}

// NewHiveClient creates a new Hive API client
func NewHiveClient(baseURL, apiKey string) *HiveClient {
	return &HiveClient{
		BaseURL: baseURL,
		APIKey:  apiKey,
		HTTPClient: &http.Client{
			Timeout: 30 * time.Second,
		},
	}
}

// Repository represents a Git repository configuration from Hive
type Repository struct {
	ProjectID            int    `json:"project_id"`
	Name                 string `json:"name"`
	GitURL               string `json:"git_url"`
	Owner                string `json:"owner"`
	Repository           string `json:"repository"`
	Branch               string `json:"branch"`
	BzzzEnabled          bool   `json:"bzzz_enabled"`
	ReadyToClaim         bool   `json:"ready_to_claim"`
	PrivateRepo          bool   `json:"private_repo"`
	GitHubTokenRequired  bool   `json:"github_token_required"`
}

// ActiveRepositoriesResponse represents the response from /api/bzzz/active-repos
type ActiveRepositoriesResponse struct {
	Repositories []Repository `json:"repositories"`
}

// TaskClaimRequest represents a task claim request to Hive
type TaskClaimRequest struct {
	TaskID    int    `json:"task_id"`
	AgentID   string `json:"agent_id"`
	ClaimedAt int64  `json:"claimed_at"`
}

// TaskStatusUpdate represents a task status update to Hive
type TaskStatusUpdate struct {
	Status    string                 `json:"status"`
	UpdatedAt int64                  `json:"updated_at"`
	Results   map[string]interface{} `json:"results,omitempty"`
}

// GetActiveRepositories fetches all repositories marked for Bzzz consumption
func (c *HiveClient) GetActiveRepositories(ctx context.Context) ([]Repository, error) {
	url := fmt.Sprintf("%s/api/bzzz/active-repos", c.BaseURL)
	
	req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %w", err)
	}
	
	// Add authentication if API key is provided
	if c.APIKey != "" {
		req.Header.Set("Authorization", "Bearer "+c.APIKey)
	}
	req.Header.Set("Content-Type", "application/json")
	
	resp, err := c.HTTPClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to execute request: %w", err)
	}
	defer resp.Body.Close()
	
	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body))
	}
	
	var response ActiveRepositoriesResponse
	if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
		return nil, fmt.Errorf("failed to decode response: %w", err)
	}
	
	return response.Repositories, nil
}

// GetProjectTasks fetches bzzz-task labeled issues for a specific project
func (c *HiveClient) GetProjectTasks(ctx context.Context, projectID int) ([]map[string]interface{}, error) {
	url := fmt.Sprintf("%s/api/bzzz/projects/%d/tasks", c.BaseURL, projectID)
	
	req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %w", err)
	}
	
	if c.APIKey != "" {
		req.Header.Set("Authorization", "Bearer "+c.APIKey)
	}
	req.Header.Set("Content-Type", "application/json")
	
	resp, err := c.HTTPClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to execute request: %w", err)
	}
	defer resp.Body.Close()
	
	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body))
	}
	
	var tasks []map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&tasks); err != nil {
		return nil, fmt.Errorf("failed to decode response: %w", err)
	}
	
	return tasks, nil
}

// ClaimTask registers a task claim with the Hive system
func (c *HiveClient) ClaimTask(ctx context.Context, projectID, taskID int, agentID string) error {
	url := fmt.Sprintf("%s/api/bzzz/projects/%d/claim", c.BaseURL, projectID)
	
	claimRequest := TaskClaimRequest{
		TaskID:    taskID,
		AgentID:   agentID,
		ClaimedAt: time.Now().Unix(),
	}
	
	jsonData, err := json.Marshal(claimRequest)
	if err != nil {
		return fmt.Errorf("failed to marshal claim request: %w", err)
	}
	
	req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return fmt.Errorf("failed to create request: %w", err)
	}
	
	if c.APIKey != "" {
		req.Header.Set("Authorization", "Bearer "+c.APIKey)
	}
	req.Header.Set("Content-Type", "application/json")
	
	resp, err := c.HTTPClient.Do(req)
	if err != nil {
		return fmt.Errorf("failed to execute request: %w", err)
	}
	defer resp.Body.Close()
	
	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
		body, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("claim request failed with status %d: %s", resp.StatusCode, string(body))
	}
	
	return nil
}

// UpdateTaskStatus updates the task status in the Hive system
func (c *HiveClient) UpdateTaskStatus(ctx context.Context, projectID, taskID int, status string, results map[string]interface{}) error {
	url := fmt.Sprintf("%s/api/bzzz/projects/%d/status", c.BaseURL, projectID)
	
	statusUpdate := TaskStatusUpdate{
		Status:    status,
		UpdatedAt: time.Now().Unix(),
		Results:   results,
	}
	
	jsonData, err := json.Marshal(statusUpdate)
	if err != nil {
		return fmt.Errorf("failed to marshal status update: %w", err)
	}
	
	req, err := http.NewRequestWithContext(ctx, "PUT", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return fmt.Errorf("failed to create request: %w", err)
	}
	
	if c.APIKey != "" {
		req.Header.Set("Authorization", "Bearer "+c.APIKey)
	}
	req.Header.Set("Content-Type", "application/json")
	
	resp, err := c.HTTPClient.Do(req)
	if err != nil {
		return fmt.Errorf("failed to execute request: %w", err)
	}
	defer resp.Body.Close()
	
	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("status update failed with status %d: %s", resp.StatusCode, string(body))
	}
	
	return nil
}

// HealthCheck verifies connectivity to the Hive API
func (c *HiveClient) HealthCheck(ctx context.Context) error {
	url := fmt.Sprintf("%s/health", c.BaseURL)
	
	req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
	if err != nil {
		return fmt.Errorf("failed to create health check request: %w", err)
	}
	
	resp, err := c.HTTPClient.Do(req)
	if err != nil {
		return fmt.Errorf("health check request failed: %w", err)
	}
	defer resp.Body.Close()
	
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("Hive API health check failed with status: %d", resp.StatusCode)
	}
	
	return nil
}