// Copyright 2024 The Go 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 (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"slices"
	"strings"
	"testing"
)

// NOTE: It's possible that we should elevate TestingEdit to a general
// “deferred edits” facility for use in looking at potential changes.
// On the other hand, higher-level code usually needs to know
// whether it's making changes or not, so that it can record that
// the work has been done, so normally “deferred edits” should be
// as high in the stack as possible, and the GitHub client is not.

// PostIssueComment posts a new comment with the given body (written in Markdown) on issue.
// It returns an API URL for the new comment, and a URL suitable for display.
func (c *Client) PostIssueComment(ctx context.Context, issue *Issue, changes *IssueCommentChanges) (id, url string, err error) {
	if c.divertEdits() {
		c.testMu.Lock()
		defer c.testMu.Unlock()

		c.testEdits = append(c.testEdits, &TestingEdit{
			Project:             issue.Project(),
			Issue:               issue.Number,
			IssueCommentChanges: changes.clone(),
		})
		return "", "", nil
	}

	body, err := c.post(ctx, issue.URL+"/comments", changes)
	if err != nil {
		return "", "", err
	}
	var res struct {
		APIURL     string `json:"url"`
		DisplayURL string `json:"html_url"`
	}
	if err := json.Unmarshal(body, &res); err != nil {
		return "", "", err
	}
	return res.APIURL, res.DisplayURL, nil
}

// DownloadIssue downloads the current issue JSON from the given URL
// and decodes it into an issue.
// Given an issue, c.DownloadIssue(issue.URL) fetches the very latest state for the issue.
func (c *Client) DownloadIssue(ctx context.Context, url string) (*Issue, error) {
	x := new(Issue)
	_, err := c.get(ctx, url, "", x)
	if err != nil {
		return nil, err
	}
	return x, nil
}

// DownloadIssueComment downloads the current comment JSON from the given URL
// and decodes it into an IssueComment.
// Given a comment, c.DownloadIssueComment(comment.URL) fetches the very latest state for the comment.
func (c *Client) DownloadIssueComment(ctx context.Context, url string) (*IssueComment, error) {
	x := new(IssueComment)
	_, err := c.get(ctx, url, "", x)
	if err != nil {
		return nil, err
	}
	return x, nil
}

type IssueCommentChanges struct {
	Body string `json:"body,omitempty"`
}

func (ch *IssueCommentChanges) clone() *IssueCommentChanges {
	x := *ch
	ch = &x
	return ch
}

func (ch *IssueCommentChanges) SetTitle(string) error {
	return errors.New("cannot set the title of an IssueComment")
}

func (ch *IssueCommentChanges) SetBody(s string) error {
	ch.Body = s
	return nil
}

// EditIssueComment changes the comment on GitHub to have the new body.
// It is typically a good idea to use c.DownloadIssueComment first and check
// that the live comment body matches the one obtained from the database,
// to minimize race windows.
func (c *Client) EditIssueComment(ctx context.Context, comment *IssueComment, changes *IssueCommentChanges) error {
	if c.divertEdits() {
		c.testMu.Lock()
		defer c.testMu.Unlock()

		c.testEdits = append(c.testEdits, &TestingEdit{
			Project:             comment.Project(),
			Issue:               comment.Issue(),
			Comment:             comment.CommentID(),
			IssueCommentChanges: changes.clone(),
		})
		return nil
	}

	_, err := c.patch(ctx, comment.URL, changes)
	return err
}

// An IssueChanges specifies changes to make to an issue.
// Fields that are the empty string or a nil pointer are ignored.
//
// Note that Labels is the new set of all labels for the issue,
// not labels to add. If you are adding a single label,
// you need to include all the existing labels as well.
// Labels is a *[]string so that it can be set to new([]string)
// to clear the labels.
type IssueChanges struct {
	Title  string    `json:"title,omitempty"`
	Body   string    `json:"body,omitempty"`
	State  string    `json:"state,omitempty"`
	Labels *[]string `json:"labels,omitempty"`
}

func (ch *IssueChanges) clone() *IssueChanges {
	x := *ch
	ch = &x
	if ch.Labels != nil {
		x := slices.Clone(*ch.Labels)
		ch.Labels = &x
	}
	return ch
}

func (ch *IssueChanges) SetTitle(s string) error {
	ch.Title = s
	return nil
}

func (ch *IssueChanges) SetBody(s string) error {
	ch.Body = s
	return nil
}

// EditIssue applies the changes to issue on GitHub.
func (c *Client) EditIssue(ctx context.Context, issue *Issue, changes *IssueChanges) error {
	if c.divertEdits() {
		c.testMu.Lock()
		defer c.testMu.Unlock()

		c.testEdits = append(c.testEdits, &TestingEdit{
			Project:      issue.Project(),
			Issue:        issue.Number,
			IssueChanges: changes.clone(),
		})
		return nil
	}

	_, err := c.patch(ctx, issue.URL, changes)
	return err
}

// patch is like c.get but makes a PATCH request.
// Unlike c.get, it requires authentication.
// It returns the response body on success.
func (c *Client) patch(ctx context.Context, url string, changes any) ([]byte, error) {
	return c.json(ctx, "PATCH", url, changes)
}

// post is like c.get but makes a POST request.
// Unlike c.get, it requires authentication.
// It returns the response body on success.
func (c *Client) post(ctx context.Context, url string, body any) ([]byte, error) {
	return c.json(ctx, "POST", url, body)
}

// json is the general PATCH/POST implementation.
// It returns the response body on success.
func (c *Client) json(ctx context.Context, method, url string, body any) ([]byte, error) {
	js, err := json.Marshal(body)
	if err != nil {
		return nil, err
	}

	auth, ok := c.secret.Get("api.github.com")
	if !ok && !testing.Testing() {
		return nil, fmt.Errorf("no secret for api.github.com")
	}
	user, pass, _ := strings.Cut(auth, ":")

Redo:
	req, err := http.NewRequestWithContext(ctx, method, url, bytes.NewReader(js))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json; charset=utf-8")
	req.SetBasicAuth(user, pass)
	resp, err := c.http.Do(req)
	if err != nil {
		return nil, err
	}
	data, err := io.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		return nil, fmt.Errorf("reading body: %v", err)
	}
	if c.rateLimit(resp) {
		goto Redo
	}
	if resp.StatusCode/10 != 20 { // allow 200, 201, maybe others
		// Include body as part of error; don't return it separately.
		return nil, fmt.Errorf("%s\n%s", resp.Status, data)
	}
	return data, nil
}
