// Copyright 2023 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package github

import (
	
	
	
)

// CopilotService provides access to the Copilot-related functions
// in the GitHub API.
//
// GitHub API docs: https://docs.github.com/en/rest/copilot/
type CopilotService service

// CopilotOrganizationDetails represents the details of an organization's Copilot for Business subscription.
type CopilotOrganizationDetails struct {
	SeatBreakdown         *CopilotSeatBreakdown `json:"seat_breakdown"`
	PublicCodeSuggestions string                `json:"public_code_suggestions"`
	CopilotChat           string                `json:"copilot_chat"`
	SeatManagementSetting string                `json:"seat_management_setting"`
}

// CopilotSeatBreakdown represents the breakdown of Copilot for Business seats for the organization.
type CopilotSeatBreakdown struct {
	Total               int `json:"total"`
	AddedThisCycle      int `json:"added_this_cycle"`
	PendingCancellation int `json:"pending_cancellation"`
	PendingInvitation   int `json:"pending_invitation"`
	ActiveThisCycle     int `json:"active_this_cycle"`
	InactiveThisCycle   int `json:"inactive_this_cycle"`
}

// ListCopilotSeatsResponse represents the Copilot for Business seat assignments for an organization.
type ListCopilotSeatsResponse struct {
	TotalSeats int64                 `json:"total_seats"`
	Seats      []*CopilotSeatDetails `json:"seats"`
}

// CopilotSeatDetails represents the details of a Copilot for Business seat.
type CopilotSeatDetails struct {
	// Assignee can either be a User, Team, or Organization.
	Assignee                interface{} `json:"assignee"`
	AssigningTeam           *Team       `json:"assigning_team,omitempty"`
	PendingCancellationDate *string     `json:"pending_cancellation_date,omitempty"`
	LastActivityAt          *Timestamp  `json:"last_activity_at,omitempty"`
	LastActivityEditor      *string     `json:"last_activity_editor,omitempty"`
	CreatedAt               *Timestamp  `json:"created_at"`
	UpdatedAt               *Timestamp  `json:"updated_at,omitempty"`
}

// SeatAssignments represents the number of seats assigned.
type SeatAssignments struct {
	SeatsCreated int `json:"seats_created"`
}

// SeatCancellations represents the number of seats cancelled.
type SeatCancellations struct {
	SeatsCancelled int `json:"seats_cancelled"`
}

func ( *CopilotSeatDetails) ( []byte) error {
	// Using an alias to avoid infinite recursion when calling json.Unmarshal
	type  CopilotSeatDetails
	var  

	if  := json.Unmarshal(, &);  != nil {
		return 
	}

	.AssigningTeam = .AssigningTeam
	.PendingCancellationDate = .PendingCancellationDate
	.LastActivityAt = .LastActivityAt
	.LastActivityEditor = .LastActivityEditor
	.CreatedAt = .CreatedAt
	.UpdatedAt = .UpdatedAt

	switch v := .Assignee.(type) {
	case map[string]interface{}:
		,  := json.Marshal(.Assignee)
		if  != nil {
			return 
		}

		if ["type"] == nil {
			return fmt.Errorf("assignee type field is not set")
		}

		if ,  := ["type"].(string);  &&  == "User" {
			 := &User{}
			if  := json.Unmarshal(, );  != nil {
				return 
			}
			.Assignee = 
		} else if ,  := ["type"].(string);  &&  == "Team" {
			 := &Team{}
			if  := json.Unmarshal(, );  != nil {
				return 
			}
			.Assignee = 
		} else if ,  := ["type"].(string);  &&  == "Organization" {
			 := &Organization{}
			if  := json.Unmarshal(, );  != nil {
				return 
			}
			.Assignee = 
		} else {
			return fmt.Errorf("unsupported assignee type %v", ["type"])
		}
	default:
		return fmt.Errorf("unsupported assignee type %T", )
	}

	return nil
}

// GetUser gets the User from the CopilotSeatDetails if the assignee is a user.
func ( *CopilotSeatDetails) () (*User, bool) { ,  := .Assignee.(*User); return ,  }

// GetTeam gets the Team from the CopilotSeatDetails if the assignee is a team.
func ( *CopilotSeatDetails) () (*Team, bool) { ,  := .Assignee.(*Team); return ,  }

// GetOrganization gets the Organization from the CopilotSeatDetails if the assignee is an organization.
func ( *CopilotSeatDetails) () (*Organization, bool) {
	,  := .Assignee.(*Organization)
	return , 
}

// GetCopilotBilling gets Copilot for Business billing information and settings for an organization.
//
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#get-copilot-seat-information-and-settings-for-an-organization
//
//meta:operation GET /orgs/{org}/copilot/billing
func ( *CopilotService) ( context.Context,  string) (*CopilotOrganizationDetails, *Response, error) {
	 := fmt.Sprintf("orgs/%v/copilot/billing", )

	,  := .client.NewRequest("GET", , nil)
	if  != nil {
		return nil, nil, 
	}

	var  *CopilotOrganizationDetails
	,  := .client.Do(, , &)
	if  != nil {
		return nil, , 
	}

	return , , nil
}

// ListCopilotSeats lists Copilot for Business seat assignments for an organization.
//
// To paginate through all seats, populate 'Page' with the number of the last page.
//
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#list-all-copilot-seat-assignments-for-an-organization
//
//meta:operation GET /orgs/{org}/copilot/billing/seats
func ( *CopilotService) ( context.Context,  string,  *ListOptions) (*ListCopilotSeatsResponse, *Response, error) {
	 := fmt.Sprintf("orgs/%v/copilot/billing/seats", )
	,  := addOptions(, )
	if  != nil {
		return nil, nil, 
	}

	,  := .client.NewRequest("GET", , nil)
	if  != nil {
		return nil, nil, 
	}

	var  *ListCopilotSeatsResponse
	,  := .client.Do(, , &)
	if  != nil {
		return nil, , 
	}

	return , , nil
}

// AddCopilotTeams adds teams to the Copilot for Business subscription for an organization.
//
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#add-teams-to-the-copilot-subscription-for-an-organization
//
//meta:operation POST /orgs/{org}/copilot/billing/selected_teams
func ( *CopilotService) ( context.Context,  string,  []string) (*SeatAssignments, *Response, error) {
	 := fmt.Sprintf("orgs/%v/copilot/billing/selected_teams", )

	 := struct {
		 []string `json:"selected_teams"`
	}{
		: ,
	}

	,  := .client.NewRequest("POST", , )
	if  != nil {
		return nil, nil, 
	}

	var  *SeatAssignments
	,  := .client.Do(, , &)
	if  != nil {
		return nil, , 
	}

	return , , nil
}

// RemoveCopilotTeams removes teams from the Copilot for Business subscription for an organization.
//
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#remove-teams-from-the-copilot-subscription-for-an-organization
//
//meta:operation DELETE /orgs/{org}/copilot/billing/selected_teams
func ( *CopilotService) ( context.Context,  string,  []string) (*SeatCancellations, *Response, error) {
	 := fmt.Sprintf("orgs/%v/copilot/billing/selected_teams", )

	 := struct {
		 []string `json:"selected_teams"`
	}{
		: ,
	}

	,  := .client.NewRequest("DELETE", , )
	if  != nil {
		return nil, nil, 
	}

	var  *SeatCancellations
	,  := .client.Do(, , &)
	if  != nil {
		return nil, , 
	}

	return , , nil
}

// AddCopilotUsers adds users to the Copilot for Business subscription for an organization
//
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#add-users-to-the-copilot-subscription-for-an-organization
//
//meta:operation POST /orgs/{org}/copilot/billing/selected_users
func ( *CopilotService) ( context.Context,  string,  []string) (*SeatAssignments, *Response, error) {
	 := fmt.Sprintf("orgs/%v/copilot/billing/selected_users", )

	 := struct {
		 []string `json:"selected_usernames"`
	}{
		: ,
	}

	,  := .client.NewRequest("POST", , )
	if  != nil {
		return nil, nil, 
	}

	var  *SeatAssignments
	,  := .client.Do(, , &)
	if  != nil {
		return nil, , 
	}

	return , , nil
}

// RemoveCopilotUsers removes users from the Copilot for Business subscription for an organization.
//
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#remove-users-from-the-copilot-subscription-for-an-organization
//
//meta:operation DELETE /orgs/{org}/copilot/billing/selected_users
func ( *CopilotService) ( context.Context,  string,  []string) (*SeatCancellations, *Response, error) {
	 := fmt.Sprintf("orgs/%v/copilot/billing/selected_users", )

	 := struct {
		 []string `json:"selected_usernames"`
	}{
		: ,
	}

	,  := .client.NewRequest("DELETE", , )
	if  != nil {
		return nil, nil, 
	}

	var  *SeatCancellations
	,  := .client.Do(, , &)
	if  != nil {
		return nil, , 
	}

	return , , nil
}

// GetSeatDetails gets Copilot for Business seat assignment details for a user.
//
// GitHub API docs: https://docs.github.com/rest/copilot/copilot-user-management#get-copilot-seat-assignment-details-for-a-user
//
//meta:operation GET /orgs/{org}/members/{username}/copilot
func ( *CopilotService) ( context.Context, ,  string) (*CopilotSeatDetails, *Response, error) {
	 := fmt.Sprintf("orgs/%v/members/%v/copilot", , )

	,  := .client.NewRequest("GET", , nil)
	if  != nil {
		return nil, nil, 
	}

	var  *CopilotSeatDetails
	,  := .client.Do(, , &)
	if  != nil {
		return nil, , 
	}

	return , , nil
}