package laravel

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
)

// GithubToken is Laravel's response to a per-repo installation-token mint.
type GithubToken struct {
	OK            bool           `json:"ok"`
	Token         string         `json:"token"`
	ExpiresAt     string         `json:"expires_at"`
	CloneURL      string         `json:"clone_url"`
	LastPushedSHA string         `json:"last_pushed_sha"`
	Error         string         `json:"error"`
	Copyright     *CopyrightMark `json:"copyright"` // plan-gated attribution; nil = White Label
}

// CopyrightMark is the plan-gated attribution Laravel wants embedded in the
// pushed source (nil when the project owner's plan has White Label).
type CopyrightMark struct {
	HTML    string `json:"html"`    // badge injected before </body>
	Comment string `json:"comment"` // source comment banner
}

// MintGithubToken asks Laravel for a fresh per-repo, ~1h installation token for
// the project mapped to the builder session id. X-Server-Key authed.
func (c *Client) MintGithubToken(sessionID string) (GithubToken, error) {
	body, _ := json.Marshal(map[string]string{"session_id": sessionID})
	req, err := http.NewRequest(http.MethodPost, c.baseURL+"/api/github/token", bytes.NewReader(body))
	if err != nil {
		return GithubToken{}, err
	}
	req.Header.Set("Content-Type", "application/json")
	c.setHeaders(req)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return GithubToken{}, err
	}
	defer func() { _ = resp.Body.Close() }()
	if resp.StatusCode >= 500 {
		return GithubToken{}, fmt.Errorf("github token endpoint HTTP %d", resp.StatusCode)
	}
	var out GithubToken
	if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
		return GithubToken{}, err
	}
	return out, nil
}

// ReportGithubPush records the new HEAD sha after a successful push so future
// builds can detect external divergence. Best-effort.
func (c *Client) ReportGithubPush(sessionID, sha string) error {
	body, _ := json.Marshal(map[string]string{"session_id": sessionID, "sha": sha})
	req, err := http.NewRequest(http.MethodPost, c.baseURL+"/api/github/pushed", bytes.NewReader(body))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	c.setHeaders(req)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return err
	}
	defer func() { _ = resp.Body.Close() }()
	if resp.StatusCode >= 400 {
		return fmt.Errorf("github pushed endpoint HTTP %d", resp.StatusCode)
	}
	return nil
}
