package downloader

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strconv"
)

func DownloadFile(url, filepath string, silent bool) error {
	var start int64
	if info, err := os.Stat(filepath); err == nil {
		start = info.Size()
	}

	out, err := os.OpenFile(filepath, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	defer out.Close()

	if start > 0 {
		if _, err := out.Seek(start, 0); err != nil {
			return err
		}
	}

	// HTTP request with Range header for resume
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	if start > 0 {
		req.Header.Set("Range", "bytes="+strconv.FormatInt(start, 10)+"-")
	}

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

	if resp.StatusCode == http.StatusNotFound {
		os.Exit(1)
	}

	// Get total size for progress calculation
	var total int64
	if resp.StatusCode == http.StatusPartialContent {
		contentRange := resp.Header.Get("Content-Range") // e.g., bytes 1234-9999/10000
		var sizeStr string
		fmt.Sscanf(contentRange, "bytes %*d-%*d/%s", &sizeStr)
		total, _ = strconv.ParseInt(sizeStr, 10, 64)
	} else if resp.ContentLength > 0 {
		total = start + resp.ContentLength
	}

	buf := make([]byte, 32*1024)
	var downloaded = start
	for {
		n, err := resp.Body.Read(buf)
		if n > 0 {
			if _, writeErr := out.Write(buf[:n]); writeErr != nil {
				return writeErr
			}
			downloaded += int64(n)
			if total > 0 && !silent {
				fmt.Printf("\r%.2f%%", float64(downloaded)*100/float64(total))
			}
		}
		if err != nil {
			if err == io.EOF {
				break
			}
			return err
		}
	}
	return nil
}
