package caddyhugo

import (
	"fmt"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"sort"
	"time"

	"github.com/gohugoio/hugo/hugolib"
)

type Content struct {
	Filename string
	Modtime  time.Time
	Metadata *Metadata
}

type Metadata struct {
	Title         string
	Path          string
	Date, Lastmod time.Time
}

// GetContent fetches the list of available content from the site directory. If
// possible, the return value will be enriched with metadata from Hugo.
func GetContent(siteRoot string, sites *hugolib.HugoSites) ([]Content, error) {
	var files = []Content{}

	err := filepath.Walk(path.Join(siteRoot, "content"), func(name string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if fi.IsDir() {
			return nil
		}

		name, err = filepath.Rel(siteRoot, name)
		if err != nil {
			return err
		}

		files = append(files, Content{
			Filename: name,
			Modtime:  fi.ModTime(),
		})
		return nil
	})

	sort.Slice(files, func(i, j int) bool {
		return files[i].Modtime.Before(files[j].Modtime)
	})

	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	for i, file := range files {
		fn := path.Join(siteRoot, file.Filename)
		page := sites.GetContentPage(fn)
		if page != nil {
			files[i].Metadata = &Metadata{
				Title:   page.Title(),
				Path:    file.Filename,
				Date:    page.Date(),
				Lastmod: page.Lastmod(),
			}
		}
	}

	return files, nil
}

// NewContent initializes new content with the name (title) and content type.
// If ctype is empty string, "default" is used. The return value is the filename,
// which may be modified from the title and includes the content type if other than
// default, but does not include the full directory relative to the site.
func (ch *CaddyHugo) NewContent(name, ctype string) (string, error) {
	if filepath.Ext(name) != ".md" {
		name += ".md"
	}

	if ctype == "" {
		ctype = "default"
	}

	name = docname(name)
	filename := path.Join(ctype, name)
	if ctype == "default" {
		filename = name
	}

	_, err := os.Stat(path.Join(ch.Dir, "content", filename))
	if os.IsNotExist(err) {
		cmd := exec.Command("hugo", "new", filename)
		cmd.Dir = ch.Dir
		ch.logf("running `hugo new` in %v", ch.Dir)
		out, err := cmd.CombinedOutput()
		if err != nil {
			return filename, fmt.Errorf("error running 'hugo new': %v; %v", err, string(out))
		}
	}

	ch.Build()

	return filename, nil
}
