/*
 * Copyright 2026 Oleg Borodin <onborodin@gmail.com>
 */
package config

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	"mstore/pkg/auxx509"

	yaml "go.yaml.in/yaml/v4"
)

type Service struct {
	Address string `json:"address" yaml:"address"`
	Port    uint32 `json:"port"    yaml:"port"`
}

type Database struct {
	Basepath string `json:"basepath" yaml:"basepath"`
}

type Storage struct {
	Basepath string `json:"basepath" yaml:"basepath"`
}

type Config struct {
	Service   Service  `json:"service"            yaml:"service"`
	Database  Database `json:"database"           yaml:"database"`
	Storage   Storage  `json:"storage"            yaml:"storage"`
	AsDaemon  bool     `json:"asDaemon"           yaml:"asDaemon"`
	Logpath   string   `json:"logpath"            yaml:"logpath"`
	Runpath   string   `json:"runpath"            yaml:"runpath"`
	Version   string   `json:"version"            yaml:"version"`
	Certpath  string   `json:"certpath,omitempty" yaml:"certpath,omitempty"`
	Keypath   string   `json:"keypath,omitempty"  yaml:"keypath,omitempty"`
	X509Cert  string   `json:"-"                  yaml:"-"`
	X509Key   string   `json:"-"                  yaml:"-"`
	Datadir   string   `json:"datadir"            yaml:"datadir"`
	Hostname  string   `json:"hostname"           yaml:"hostname"`
	Hostnames []string `json:"hostnames"          yaml:"hostnames"`
	LogLimit  int64    `json:"logLimit"           yaml:"logLimit"`
	RunUser   string   `json:"runUser"            yaml:"runUser"`
}

func NewConfig() *Config {
	logfile := fmt.Sprintf("%s.log", srvname)
	logpath := filepath.Join(logdir, logfile)

	runfile := fmt.Sprintf("%s.pid", srvname)
	runpath := filepath.Join(rundir, runfile)

	//certpath := fmt.Sprintf("%s.crt", srvname)
	//certpath = filepath.Join(confdir, certpath)

	//keypath := fmt.Sprintf("%s.crt", srvname)
	//keypath = filepath.Join(confdir, keypath)

	return &Config{
		Service: Service{
			Address: "0.0.0.0",
			Port:    1025,
		},
		Database: Database{
			Basepath: datadir,
		},
		Storage: Storage{
			Basepath: datadir,
		},
		AsDaemon: false,
		Logpath:  logpath,
		Runpath:  runpath,
		Version:  version,
		Datadir:  datadir,
		//Certpath: certpath,
		//Keypath:  keypath,
		Hostnames: make([]string, 0),
		LogLimit:  1024 * 1024 * 10, // 10 Mb
		RunUser:   "daemon",
	}
}

func (conf *Config) String() string {
	confbytes, _ := yaml.Marshal(conf)
	return string(confbytes)
}

func (conf *Config) ReadConfigfile() error {
	conffile := fmt.Sprintf("%s.yaml", srvname)
	confpath := filepath.Join(confdir, conffile)

	confdata, err := ioutil.ReadFile(confpath)
	if err != nil {
		return err
	}
	err = yaml.Unmarshal(confdata, conf)
	if err != nil {
		return err
	}
	return err
}

func (conf *Config) ReadX509Cert() error {
	var err error
	if conf.Certpath != "" && conf.Keypath != "" {
		if !filepath.IsAbs(conf.Certpath) {
			conf.Certpath = filepath.Join(confdir, conf.Certpath)
		}
		certBytes, err := os.ReadFile(conf.Certpath)
		if err != nil {
			return err
		}
		if !filepath.IsAbs(conf.Keypath) {
			conf.Keypath = filepath.Join(confdir, conf.Keypath)
		}
		keyBytes, err := os.ReadFile(conf.Keypath)
		if err != nil {
			return err
		}
		conf.X509Cert = string(certBytes)
		conf.X509Key = string(keyBytes)
		return err
	}
	/*
		if conf.X509Cert != "" && conf.X509Key != "" {
			x509Cert, err := base64.StdEncoding.DecodeString(conf.X509Cert)
			if err != nil {
				return err
			}
			conf.X509Cert = string(x509Cert)
			x509Key, err := base64.StdEncoding.DecodeString(conf.X509Key)
			if err != nil {
				return err
			}
			conf.X509Key = string(x509Key)
		}
	*/
	if conf.X509Cert == "" || conf.X509Key == "" {
		if conf.Hostname == "" {
			conf.Hostname, err = os.Hostname()
			if err != nil {
				return err
			}
		}
		certBytes, keyBytes, err := auxx509.CreateSelfSignedCert(conf.Hostname, conf.Hostnames...)
		if err != nil {
			return err
		}
		conf.X509Cert = string(certBytes)
		conf.X509Key = string(keyBytes)
		return err

	}

	return err
}
