package academy

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

// HeyGenClient handles avatar video generation via the HeyGen API
type HeyGenClient struct {
	apiKey   string
	avatarID string
	client   *http.Client
}

// NewHeyGenClient creates a new HeyGen client
func NewHeyGenClient() *HeyGenClient {
	apiKey := os.Getenv("HEYGEN_API_KEY")
	avatarID := os.Getenv("HEYGEN_AVATAR_ID")
	if avatarID == "" {
		avatarID = "josh_lite3_20230714" // Default avatar
	}

	return &HeyGenClient{
		apiKey:   apiKey,
		avatarID: avatarID,
		client: &http.Client{
			Timeout: 300 * time.Second, // Video generation can take time
		},
	}
}

// IsConfigured returns true if API key is set
func (c *HeyGenClient) IsConfigured() bool {
	return c.apiKey != ""
}

// CreateVideoRequest represents the HeyGen API request
type CreateVideoRequest struct {
	VideoInputs []VideoInput `json:"video_inputs"`
	Dimension   Dimension    `json:"dimension"`
}

// VideoInput represents a single video segment
type VideoInput struct {
	Character Character  `json:"character"`
	Voice     VideoVoice `json:"voice"`
}

// Character represents the avatar
type Character struct {
	Type     string `json:"type"`
	AvatarID string `json:"avatar_id"`
}

// VideoVoice represents the voice/audio source
type VideoVoice struct {
	Type      string `json:"type"` // "audio" for pre-generated audio
	AudioURL  string `json:"audio_url,omitempty"`
	InputText string `json:"input_text,omitempty"`
}

// Dimension represents video dimensions
type Dimension struct {
	Width  int `json:"width"`
	Height int `json:"height"`
}

// CreateVideoResponse represents the HeyGen API response
type CreateVideoResponse struct {
	Data struct {
		VideoID string `json:"video_id"`
	} `json:"data"`
	Error interface{} `json:"error"`
}

// HeyGenVideoStatus represents video status from HeyGen
type HeyGenVideoStatus struct {
	Data struct {
		Status   string `json:"status"` // processing, completed, failed
		VideoURL string `json:"video_url"`
	} `json:"data"`
}

// CreateVideo creates a video with the avatar and audio
func (c *HeyGenClient) CreateVideo(audioURL string) (*CreateVideoResponse, error) {
	if !c.IsConfigured() {
		return nil, fmt.Errorf("HeyGen API key not configured")
	}

	url := "https://api.heygen.com/v2/video/generate"

	reqBody := CreateVideoRequest{
		VideoInputs: []VideoInput{
			{
				Character: Character{
					Type:     "avatar",
					AvatarID: c.avatarID,
				},
				Voice: VideoVoice{
					Type:     "audio",
					AudioURL: audioURL,
				},
			},
		},
		Dimension: Dimension{
			Width:  1920,
			Height: 1080,
		},
	}

	jsonBody, err := json.Marshal(reqBody)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal request: %w", err)
	}

	req, err := http.NewRequest("POST", url, bytes.NewReader(jsonBody))
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-Api-Key", c.apiKey)

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

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

	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
		return nil, fmt.Errorf("HeyGen API error %d: %s", resp.StatusCode, string(body))
	}

	var result CreateVideoResponse
	if err := json.Unmarshal(body, &result); err != nil {
		return nil, fmt.Errorf("failed to parse response: %w", err)
	}

	return &result, nil
}

// GetVideoStatus checks the status of a video generation job
func (c *HeyGenClient) GetVideoStatus(videoID string) (*HeyGenVideoStatus, error) {
	if !c.IsConfigured() {
		return nil, fmt.Errorf("HeyGen API key not configured")
	}

	url := fmt.Sprintf("https://api.heygen.com/v1/video_status.get?video_id=%s", videoID)

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %w", err)
	}

	req.Header.Set("X-Api-Key", c.apiKey)

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

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

	var status HeyGenVideoStatus
	if err := json.Unmarshal(body, &status); err != nil {
		return nil, fmt.Errorf("failed to parse response: %w", err)
	}

	return &status, nil
}
