package main

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"time"

	"github.com/google/uuid"
	"github.com/urfave/cli/v2"
)

var (
	version = "dev"
	commit  = "none"
	date    = "unknown"
)

func main() {
	cli.VersionFlag = &cli.BoolFlag{Name: "version"}

	app := cli.App{
		Name:    "gpaste",
		Version: fmt.Sprintf("gpaste %s-%s (%s)", version, commit, date),
		Flags: []cli.Flag{
			&cli.StringFlag{
				Name:  "config",
				Usage: "Path to config-file.",
			},
		},
		Commands: []*cli.Command{
			{
				Name:      "upload",
				Usage:     "Upload file(s)",
				ArgsUsage: "FILE [FILE]...",
				Flags: []cli.Flag{
					&cli.StringFlag{
						Name:  "url",
						Usage: "Base url of gpaste server",
					},
				},
				Action: ActionUpload,
			},
		},
	}

	app.Run(os.Args)
}

func ActionUpload(c *cli.Context) error {
	url := fmt.Sprintf("%s/api/file", c.String("url"))
	client := &http.Client{}
	// TODO: Change timeout
	ctx, cancel := context.WithTimeout(c.Context, 10*time.Minute)
	defer cancel()

	buf := &bytes.Buffer{}
	mw := multipart.NewWriter(buf)

	for _, arg := range c.Args().Slice() {
		f, err := os.Open(arg)
		if err != nil {
			return err
		}
		defer f.Close()
		fw, err := mw.CreateFormFile(uuid.Must(uuid.NewRandom()).String(), arg)
		if err != nil {
			return err
		}
		if _, err := io.Copy(fw, f); err != nil {
			return err
		}
	}
	mw.Close()
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, buf)
	req.Header.Add("Content-Type", mw.FormDataContentType())
	if err != nil {
		return err
	}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	var expectedResp []struct {
		Message string `json:"message"`
		ID      string `json:"id"`
		URL     string `json:"url"`
	}

	decoder := json.NewDecoder(resp.Body)
	if err := decoder.Decode(&expectedResp); err != nil {
		return fmt.Errorf("error decoding response: %w", err)
	}

	for _, r := range expectedResp {
		fmt.Printf("Uploaded file %s\n", r.ID)
	}
	return nil
}