package api

import (
	"context"
	"regexp"
	"strconv"
	"time"

	"deevirt.fr/compute/cmd/compute_api/proto"
	"deevirt.fr/compute/pkg/config"
	clientv3 "go.etcd.io/etcd/client/v3"
)

type Domain struct {
	Config *config.Config
	Etcd   *clientv3.Client
	proto.UnimplementedDomainServer
}

func (d *Domain) List(ctx context.Context, in *proto.DomainListAllRequest) (*proto.DomainListAllResponse, error) {
	var domains = []*proto.DomainListResponse{}

	ctx_etcd, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	resp, _ := d.Etcd.Get(ctx_etcd, "/cluster/"+d.Config.ClusterID+"/domain", clientv3.WithPrefix(), clientv3.WithKeysOnly())
	cancel()

	re := regexp.MustCompile(`domain/(?P<domainID>[a-zA-Z1-9-]+)$`)

	for _, data := range resp.Kvs {
		key := string(data.Key[:])

		if re.MatchString(key) {
			matches := re.FindStringSubmatch(key)
			index := re.SubexpIndex("domainID")

			domain, _ := d.Get(context.Background(), &proto.DomainListRequest{
				DomainId: matches[index],
			})

			domains = append(domains, domain)
		}
	}

	return &proto.DomainListAllResponse{
		Domains: domains,
	}, nil
}

func (d *Domain) Get(ctx context.Context, in *proto.DomainListRequest) (*proto.DomainListResponse, error) {
	ctx_etcd, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	resp_config, _ := d.Etcd.Get(ctx_etcd, "/cluster/"+d.Config.ClusterID+"/domain/"+in.DomainId)
	resp_state, _ := d.Etcd.Get(ctx_etcd, "/cluster/"+d.Config.ClusterID+"/domain/"+in.DomainId+"/state")
	cancel()

	state, _ := strconv.ParseInt(string(resp_state.Kvs[0].Value), 10, 64)

	return &proto.DomainListResponse{
		DomainId: in.DomainId,
		Config:   string(resp_config.Kvs[0].Value),
		State:    state,
	}, nil
}

func (d *Domain) Create(ctx context.Context, in *proto.DomainCreateRequest) (*proto.DomainCreateResponse, error) {
	ctx_etcd, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	resp_config, _ := d.Etcd.Get(ctx_etcd, "/cluster/"+d.Config.ClusterID)
	cancel()

	println(string(resp_config.Kvs[0].Value))

	/*if d.Config.LibvirtTLS {
		libvirt_uri := "qemu+tls://"++"/system"
	}
	conn, err := libvirt.NewConnect("qemu:///system")
	if err != nil {
		log.Println("Connexion Error")
	}
	defer conn.Close()*/

	/*

			async def Create(self, request, context):
		        yield domain_pb2.DomainCreateResponse(progress=40)
		        async with Libvirt() as libvirt:
		            if await libvirt.define(request.config.decode()):
		                yield domain_pb2.DomainCreateResponse(progress=100)
		            else:
		                context.set_code(grpc.StatusCode.ALREADY_EXISTS)

	*/

	return &proto.DomainCreateResponse{}, nil
}
