// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT

package forgejo

import (
	"context"
	"fmt"
	"strings"

	"code.forgejo.org/f3/gof3/v3/f3"
	"code.forgejo.org/f3/gof3/v3/id"
	f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
	"code.forgejo.org/f3/gof3/v3/tree/generic"

	forgejo_sdk "code.forgejo.org/f3/gof3/v3/forges/forgejo/sdk"
)

type organizations struct {
	container
}

func (o *organizations) listOrganizationsPage(ctx context.Context, page int) []*forgejo_sdk.Organization {
	pageSize := o.getPageSize()

	var organizationFounds []*forgejo_sdk.Organization
	var err error
	organizationFounds, _, err = o.getClient().ListOrgs(forgejo_sdk.ListOrgsOptions{
		ListOptions: forgejo_sdk.ListOptions{Page: page, PageSize: pageSize},
	})
	if err != nil {
		panic(fmt.Errorf("error while listing organizations: %v", err))
	}

	return organizationFounds
}

func (o *organizations) ListPage(ctx context.Context, page int) generic.ChildrenSlice {
	return f3_tree.ConvertListed(ctx, o.GetNode(), f3_tree.ConvertToAny(o.listOrganizationsPage(ctx, page)...)...)
}

func (o *organizations) GetIDFromName(ctx context.Context, name string) id.NodeID {
	organization, resp, err := o.getClient().GetOrg(name)
	if resp.StatusCode == 404 {
		return id.NilID
	}
	if err != nil {
		if strings.Contains(err.Error(), "organization not found") {
			return id.NilID
		}
		panic(fmt.Errorf("organization %v %w", o, err))
	}
	return id.NewNodeID(organization.ID)
}

func (o *organizations) getNameFromID(ctx context.Context, i int64) string {
	o.Trace("%d", i)
	node := o.GetNode()
	nodeID := id.NewNodeID(i)
	organization := node.GetChild(nodeID)
	if organization != generic.NilNode {
		return organization.ToFormat().(*f3.Organization).Name
	}

	o.Trace("look for %d", i)
	for page := 1; ; page++ {
		organizations := o.listOrganizationsPage(ctx, page)
		if len(organizations) == 0 {
			break
		}
		o.Trace("look for %d page %d", i, page)
		for _, organization := range organizations {
			o.Trace("look for %d page %d organization %v", i, page, organization)
			if organization.ID == i {
				return organization.UserName
			}
		}
	}
	o.Trace("no organization found for id %d", i)
	return ""
}

func newOrganizations() generic.NodeDriverInterface {
	return &organizations{}
}
