// 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 main

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"slices"

	"cloud.google.com/go/firestore"
	"golang.org/x/oscar/internal/actions"
	"golang.org/x/oscar/internal/docs"
	"golang.org/x/oscar/internal/github"
)

// handleGitHubEvent handles incoming webhook requests from GitHub
// and reports whether the request was handled.
//
// If the incoming request was triggered by supported event, and sync
// is enabled, it syncs its relevant state. If changes are enabled,
// it takes relevant actions in response to the event.
//
// Otherwise, it logs the event and returns (false, nil).
//
// The supported events are:
//   - new GitHub issue (see [Gaby.handleGitHubIssueEvent])
//   - new GitHub issue comment (see [Gaby.handleGitHubIssueCommentEvent])
//
// handled is true if all appropriate syncs and actions were performed
// in response to the event, and false if the event was skipped or an
// error occurred. (handled is also false if either of [gabyFlags.enablesync]
// or [gabyFlags.enablechanges] is false.)
//
// handleGitHubEvent returns an error if any of the syncs or actions fails,
// or if the webhook request is invalid according to [github.ValidateWebhookRequest].
func (g *Gaby) handleGitHubEvent(r *http.Request, fl *gabyFlags) (handled bool, err error) {
	event, err := github.ValidateWebhookRequest(r, g.secret)
	if err != nil {
		return false, fmt.Errorf("%w: %v", errInvalidWebhookRequest, err)
	}

	if !slices.Contains(g.githubProjects, event.Project()) {
		g.slog.Warn("unexpected webhook request", "webhook_project", event.Project(), "gaby_project", g.githubProjects, "event", event)
		return false, nil
	}

	switch p := event.Payload.(type) {
	case *github.WebhookIssueEvent:
		return g.handleGitHubIssueEvent(r.Context(), p, fl)
	case *github.WebhookIssueCommentEvent:
		return g.handleGitHubIssueCommentEvent(r.Context(), p, fl)
	default:
		g.slog.Info("ignoring GitHub event", "type", event.Type, "event", event)
	}

	return false, nil
}

var errInvalidWebhookRequest = errors.New("invalid webhook request")

// handleGitHubIssueEvent handles an incoming GitHub "issue" event and
// reports whether the event was handled.
//
// If the event is a new issue, and sync is enabled, the function
// syncs the corresponding GitHub project. If changes are also enabled,
// it posts related issues and fixes the body and comments of the issue.
//
// It returns an error immediately if any of the syncs or actions fails.
//
// Otherwise, it logs the event and returns (false, nil).
func (g *Gaby) handleGitHubIssueEvent(ctx context.Context, event *github.WebhookIssueEvent, fl *gabyFlags) (handled bool, _ error) {
	if event.Action != github.WebhookIssueActionOpened {
		g.slog.Info("ignoring GitHub issue event (action is not opened)", "event", event, "action", event.Action)
		return false, nil
	}

	g.slog.Info("handling GitHub issue", "event", event)

	project := event.Repository.Project
	if fl.enablesync {
		if err := g.syncGitHubProject(ctx, project); err != nil {
			return false, err
		}
		if err := g.embedAll(ctx); err != nil {
			return false, err
		}
	}

	// Do not attempt changes unless sync is enabled and completely succeeded.
	if fl.enablechanges && fl.enablesync {
		// No need to lock; [related.Poster.Post] and [related.Poster.Run] can
		// happen concurrently.
		if err := g.relatedPoster.Post(ctx, project, event.Issue.Number); err != nil {
			return false, err
		}
		if err := g.fixGitHubIssue(ctx, project, event.Issue.Number); err != nil {
			return false, err
		}
		if err := g.labeler.LabelIssue(ctx, project, event.Issue.Number); err != nil {
			return false, err
		}
		return true, nil
	}

	return false, nil
}

// handleGitHubIssueCommentEvent handles an incoming GitHub "issue comment" event
// and reports whether the event was handled.
//
// If the event is a new issue comment, and sync is enabled, the function
// syncs the corresponding GitHub project. If changes are also enabled,
// it fixes the body and comments of the issue to which the comment
// was posted.
//
// It returns an error immediately if any of the syncs or actions fails.
//
// Otherwise, it logs the event and returns (false, nil).
func (g *Gaby) handleGitHubIssueCommentEvent(ctx context.Context, event *github.WebhookIssueCommentEvent, fl *gabyFlags) (handled bool, _ error) {
	if event.Action != github.WebhookIssueCommentActionCreated {
		g.slog.Info("ignoring GitHub issue comment event (action is not created)", "event", event, "action", event.Action)
		return false, nil
	}

	g.slog.Info("handling GitHub issue comment", "event", event)

	project := event.Repository.Project
	if fl.enablesync {
		if err := g.syncGitHubProject(ctx, project); err != nil {
			return false, err
		}
		// Embeddings are not needed to apply fixes.
	}

	// Do not attempt changes unless sync is enabled and completely succeeded.
	if fl.enablechanges && fl.enablesync {
		if err := g.fixGitHubIssue(ctx, project, event.Issue.Number); err != nil {
			return false, err
		}
		if err := g.spawnBisectionTask(ctx, event); err != nil {
			return false, err
		}
		return true, nil
	}

	return false, nil
}

func (g *Gaby) fixGitHubIssue(ctx context.Context, project string, issue int64) error {
	// No need to lock; [commentfix.Fixer.FixGitHubIssue] and
	// [commentfix.Fixer.Run] can happen concurrently.
	if err := g.commentFixer.LogFixGitHubIssue(ctx, project, issue); err != nil {
		return err
	}
	if err := actions.Run(ctx, g.slog, g.db); err != nil {
		return err
	}
	return nil
}

// syncGitHubProject syncs the document corpus with respect to a single
// GitHub project.
func (g *Gaby) syncGitHubProject(ctx context.Context, project string) error {
	g.db.Lock(gabyGitHubSyncLock)
	defer g.db.Unlock(gabyGitHubSyncLock)

	if err := g.github.SyncProject(ctx, project); err != nil {
		return err
	}
	docs.Sync(g.docs, g.github)
	return nil
}

// spawnBisectionTask checks if event is encoding a bisection task and,
// if so, it spawns the corresponding task.
func (g *Gaby) spawnBisectionTask(ctx context.Context, event *github.WebhookIssueCommentEvent) error {
	// TODO: access comment through db instead
	// of directly through the event?
	breq, err := parseBisectTrigger(event)
	if err != nil {
		g.slog.Error("bisect.Request trigger fail", "body", event.Comment.Body, "err", err)
		return err
	}
	if breq == nil {
		g.slog.Info("bisect.Request no trigger", "body", event.Comment.Body)
		return nil
	}

	// Check the user only after we established that
	// the comment encodes a bisection request, to
	// save time on pinging firestore.
	user := event.Comment.User.Login
	if ok, err := userAllowedBisection(ctx, user); err != nil {
		g.slog.Error("bisect.Request permission check", "err", err)
		return err
	} else if !ok {
		g.slog.Info("bisect.Request permission denied", "user", user)
		return nil
	}

	if err := g.bisect.BisectAsync(ctx, breq); err != nil {
		return err
	}
	g.slog.Info("bisect.Request trigger success", "req", fmt.Sprintf("%+v", breq))
	return nil
}

// userAllowedBisection checks if the author of the
// comment event is allowed to spawn a bisection.
func userAllowedBisection(ctx context.Context, user string) (bool, error) {
	fc, err := firestore.NewClient(ctx, flags.project)
	if err != nil {
		return false, err
	}
	doc := fc.Collection("auth").Doc("bisect-github-users")
	sn, err := doc.Get(ctx)
	if err != nil {
		return false, err
	}
	var users map[string]bool
	if err := sn.DataTo(&users); err != nil {
		return false, err
	}

	return users[user], nil
}
