package main

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"time"

	cfgpkg "github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
	"github.com/mediocregopher/blog.mediocregopher.com/srv/post"
	"github.com/mediocregopher/mediocre-go-lib/v2/mctx"
	"github.com/mediocregopher/mediocre-go-lib/v2/mlog"
	"gopkg.in/yaml.v3"
)

type testData struct {
	PublishedPosts []post.Post `yaml:"published_posts"`
	Assets         map[string]string
}

func loadTestData(path string) (testData, error) {

	f, err := os.Open(path)
	if err != nil {
		return testData{}, fmt.Errorf("opening file: %w", err)
	}
	defer f.Close()

	var res testData

	if err := yaml.NewDecoder(f).Decode(&res); err != nil {
		return testData{}, fmt.Errorf("decoding file contents: %w", err)
	}

	return res, nil
}

func main() {

	ctx := context.Background()

	cfg := cfgpkg.NewBlogCfg(cfgpkg.Params{})

	var dataDir cfgpkg.DataDir
	dataDir.SetupCfg(cfg)
	defer dataDir.Close()
	ctx = mctx.WithAnnotator(ctx, &dataDir)

	testDataPath := cfg.String("test-data-path", "./test-data.yml", "File containing the data to be loaded in")

	// initialization
	err := cfg.Init(ctx)

	logger := mlog.NewLogger(nil)
	defer logger.Close()

	logger.Info(ctx, "process started")
	defer logger.Info(ctx, "process exiting")

	if err != nil {
		logger.Fatal(ctx, "initializing", err)
	}

	testDataDir := filepath.Dir(*testDataPath)

	testData, err := loadTestData(*testDataPath)
	if err != nil {
		logger.Fatal(ctx, "loading test data", err)
	}

	postDB, err := post.NewSQLDB(dataDir)
	if err != nil {
		logger.Fatal(ctx, "initializing post sql db", err)
	}
	defer postDB.Close()

	{

		postStore := post.NewStore(postDB)

		now := time.Now().Truncate(time.Hour)

		for _, post := range testData.PublishedPosts {

			ctx := mctx.Annotate(ctx,
				"postID", post.ID,
				"now", now)

			if _, err := postStore.Set(post, now); err != nil {
				logger.Fatal(ctx, "setting post", err)
			}

			logger.Info(ctx, "set post")

			now = now.Add(-1 * time.Hour)
		}

	}

	{
		assetStore := post.NewAssetStore(postDB)

		setAsset := func(assetID, assetPath string) error {
			assetFullPath := filepath.Join(testDataDir, assetPath)

			f, err := os.Open(assetFullPath)
			if err != nil {
				return fmt.Errorf("opening %q for reading: %w", assetFullPath, err)
			}
			defer f.Close()

			return assetStore.Set(assetID, f)
		}

		for assetID, assetPath := range testData.Assets {

			ctx := mctx.Annotate(ctx,
				"assetID", assetID,
				"assetPath", assetPath)

			if err := setAsset(assetID, assetPath); err != nil {
				logger.Fatal(ctx, "setting asset", err)
			}

			logger.Info(ctx, "set asset")
		}
	}
}
