package database

import (
	"fmt"
	"os"
	"sort"

	"github.com/pluja/pocketbase"
)

type PbClient struct {
	Client *pocketbase.Client
}

var Pb *PbClient

// InitPocketbase initializes the Pocketbase client
func InitPocketbase() error {
	// Initialize Pb if not already done
	if Pb == nil {
		Pb = &PbClient{}
	}

	// Create a new pocketbase client
	Pb.Client = pocketbase.NewClient(os.Getenv("PB_URL"),
		pocketbase.WithAdminEmailPassword(os.Getenv("PB_ADMIN_EMAIL"), os.Getenv("PB_ADMIN_PASSWORD")))

	return nil
}

// GetServices retrieves services from the pocketbase client
func (p *PbClient) GetServices(filters, sort string) ([]Service, error) {

	collection := pocketbase.CollectionSet[Service](p.Client, "services")
	params := pocketbase.ParamsList{
		Page:   1,
		Size:   200,
		Expand: "attributes",
		Fields: "*,expand.attributes.*",
	}

	if filters != "" {
		params.Filters = filters
	}

	if sort != "" {
		params.Sort = sort
	}

	response, err := collection.List(params)
	if err != nil {
		return nil, err
	}

	return response.Items, nil
}

func (p *PbClient) GetServiceByNameOrUrl(id string) (*Service, error) {
	collection := pocketbase.CollectionSet[Service](p.Client, "services")
	params := pocketbase.ParamsList{
		Page:    1,
		Size:    1,
		Fields:  "*,expand.attributes.*",
		Expand:  "attributes",
		Filters: fmt.Sprintf("((name='%v') || (urls~'%v'))", id, id),
	}

	response, err := collection.List(params)
	if err != nil {
		return nil, err
	}

	if len(response.Items) > 0 {
		service := response.Items[0]

		// Sort attributes by rating
		sort.SliceStable(service.Expand["attributes"], func(i, j int) bool {
			ratingOrder := map[string]int{
				"bad":  4,
				"warn": 3,
				"good": 2,
				"info": 1,
			}
			return ratingOrder[service.Expand["attributes"][i].Rating] > ratingOrder[service.Expand["attributes"][j].Rating]
		})
		return &service, nil
	} else {
		return nil, fmt.Errorf("Service not found.")
	}

}

func (p *PbClient) GetServiceById(id string) (*Service, error) {
	collection := pocketbase.CollectionSet[Service](p.Client, "services")
	params := pocketbase.ParamsList{
		Fields: "*,expand.attributes.*",
		Expand: "attributes",
	}

	response, err := collection.OneWithParams(id, params)
	if err != nil {
		return nil, err
	}

	return &response, nil
}

func (p *PbClient) CreateService(service Service) error {
	collection := pocketbase.CollectionSet[Service](p.Client, "services")

	_, err := collection.Create(service)
	if err != nil {
		return err
	}

	return nil
}

func (p *PbClient) UpdateService(id string, service Service) error {
	collection := pocketbase.CollectionSet[Service](p.Client, "services")

	err := collection.Update(id, service)
	if err != nil {
		return err
	}

	return nil
}

func (p *PbClient) GetAttribute(id string) (*Attribute, error) {
	collection := pocketbase.CollectionSet[Attribute](p.Client, "attributes")

	response, err := collection.One(id)
	if err != nil {
		return nil, err
	}

	return &response, nil
}

func (p *PbClient) GetAttributes(filters, sort string) ([]Attribute, error) {
	collection := pocketbase.CollectionSet[Attribute](p.Client, "attributes")
	params := pocketbase.ParamsList{
		Page: 1,
		Size: 250,
	}

	if filters != "" {
		params.Filters = filters
	}

	if sort != "" {
		params.Sort = sort
	}

	response, err := collection.List(params)
	if err != nil {
		return nil, err
	}

	return response.Items, nil
}

func (p *PbClient) CreateAttribute(attribute Attribute) error {
	collection := pocketbase.CollectionSet[Attribute](p.Client, "attributes")

	_, err := collection.Create(attribute)
	if err != nil {
		return err
	}

	return nil
}

func (p *PbClient) GetAnnouncement() *Announcement {
	collection := pocketbase.CollectionSet[Announcement](p.Client, "announcements")
	params := pocketbase.ParamsList{
		Page:    1,
		Size:    1,
		Filters: "active=true",
	}

	response, err := collection.List(params)
	if err != nil {
		return nil
	}

	if len(response.Items) < 1 {
		return nil
	}

	return &response.Items[0]
}
