package routes

import (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"path"
	"strings"

	"git.matterlinux.xyz/Matter/website/lib"
	"git.matterlinux.xyz/Matter/website/log"
	"github.com/bigkevmcd/go-configparser"
	"github.com/gofiber/fiber/v2"
)

type Config struct {
	Redirect string `json:"redirect"`
	Image    string `json:"image"`
	Url      string `json:"url"`

	Name     string
	Desc     string
	Author   string
	Keywords string
}

func (c *Config) Load() error {
	agent := fiber.Get(c.Url)
	code, body, errs := agent.Bytes()
	if len(errs) > 0 {
		return fmt.Errorf("request to %s failed", c.Url)
	}

	if code != 200 {
		return fmt.Errorf("bad response from %s", c.Url)
	}

	parser := configparser.New()
	err := parser.ParseReader(bytes.NewReader(body))
	if err != nil {
		return fmt.Errorf("failed to parse %s: %s", c.Url, err.Error())
	}

	name, err := parser.Get("details", "name")
	if err != nil {
		return fmt.Errorf("failed get details/name: %s", c.Url)
	}

	keywords, err := parser.Get("details", "keywords")
	if err != nil {
		return fmt.Errorf("failed get details/keywords: %s", c.Url)
	}

	author, err := parser.Get("details", "author")
	if err != nil {
		return fmt.Errorf("failed get details/keywords: %s", c.Url)
	}

	desc, err := parser.Get("details", "desc")

	c.Name = name
	c.Desc = desc
	c.Author = author
	c.Keywords = strings.ReplaceAll(keywords, ",", ", ")

	if !lib.IsStringValid(c.Name) ||
		!lib.IsStringValid(c.Desc) ||
		!lib.IsStringValid(c.Author) ||
		!lib.IsStringValid(c.Keywords) {
		return fmt.Errorf("keywords or name contain illegal chars: %s", c.Url)
	}

	return nil
}

func GetConfigs() ([]Config, error) {
	var data map[string][]Config

	configs_path := path.Join(lib.CONTENT_PATH, "configs.json")
	raw, err := os.ReadFile(configs_path)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(raw, &data)
	if err != nil {
		return nil, err
	}

	if _, ok := data["list"]; !ok {
		return nil, fmt.Errorf("json data does not contain the list key")
	}

	for i := range data["list"] {
		if err = data["list"][i].Load(); err != nil {
			return nil, err
		}
	}

	return data["list"], nil
}

func GET_Configs(c *fiber.Ctx) error {
	var (
		err     error
		con     lib.Content
		configs []Config
	)

	if con, err = lib.GetContent("", "configs"); err != nil {
		log.Error("GetContent failed: %s", err.Error())
		return lib.RenderError(c, 500)
	}

	if configs, err = GetConfigs(); err != nil {
		log.Error("GetConfigs failed: %s", err.Error())
		return lib.RenderError(c, 500)
	}

	return c.Render("configs", fiber.Map{
		"content": con,
		"list":    configs,
	})
}

func GET_Config(c *fiber.Ctx) error {
	var (
		err     error
		name    string
		configs []Config
	)

	name = c.Params("name")

	if configs, err = GetConfigs(); err != nil {
		log.Error("GetConfigs failed: %s", err.Error())
		return lib.RenderError(c, 500)
	}

	for _, cur := range configs {
		if cur.Name == name || cur.Name+".git" == name {
			return c.Status(301).Redirect(cur.Redirect)
		}
	}

	return lib.RenderError(c, 404)
}
