package downloader

import (
	"errors"
	"io"
	"net/http"
	"os"
	"strings"

	req "github.com/levigross/grequests"
	"github.com/schollz/progressbar/v3"
)

var (
	ErrAccessDenied     = errors.New("restricted access (credentials required)")
	ErrInvalidURL       = errors.New("invalid url")
	ErrUnknownAuthority = errors.New("certificate from unknown authority")
)

type Context struct {
	Filename string
	Link     string
}

func NewContext(filename, link string) *Context {
	return &Context{
		Filename: filename,
		Link:     link,
	}
}

func (c *Context) Download() error {
	resp, err := req.Head(c.Link, nil)
	if err != nil {
		if strings.Contains(err.Error(), "no such host") {
			return ErrInvalidURL
		}
		if strings.Contains(err.Error(), "certificate signed by unknown authority") {
			return ErrUnknownAuthority
		}
		return err
	}
	defer resp.Close()
	if resp.StatusCode == http.StatusNotFound {
		return ErrInvalidURL
	}
	if resp.StatusCode == http.StatusUnauthorized {
		return ErrAccessDenied
	}
	if resp.StatusCode != http.StatusOK {
		return errors.New(resp.RawResponse.Status)
	}
	resp.Close()

	resp, err = req.Get(c.Link, nil)
	if err != nil {
		return err
	}

	var filesize int64
	if resp.RawResponse.ContentLength > -1 {
		filesize = resp.RawResponse.ContentLength
	}

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

	bar := progressbar.DefaultBytes(
		filesize,
		"downloading",
	)

	_, err = io.Copy(io.MultiWriter(destFile, bar), resp.RawResponse.Body)
	if err != nil {
		return err
	}

	return nil
}

func (c *Context) FileExists() bool {
	_, err := os.Stat(c.Filename)
	return !errors.Is(err, os.ErrNotExist)
}