// 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 (
	"fmt"
	"net/http"
	"slices"

	"github.com/google/safehtml"
	"github.com/google/safehtml/template"
	"golang.org/x/oscar/internal/github"
	"golang.org/x/oscar/internal/htmlutil"
	"golang.org/x/oscar/internal/llm"
	"golang.org/x/oscar/internal/rules"
)

// rulesPage holds the fields needed to display the results
// of an issue rule check.
type rulesPage struct {
	CommonPage

	Params rulesParams // the raw parameters
	Result *rulesResult
	Error  error // if non-nil, the error to display instead of the result
}

type rulesResult struct {
	*github.Issue                   // the issue we're reporting on
	rules.IssueResult               // the raw result
	HTML              safehtml.HTML // issue response as HTML
}

// rulesParams holds the raw inputs to the rules form.
type rulesParams struct {
	Query string // the issue ID to lookup
}

func (g *Gaby) handleRules(w http.ResponseWriter, r *http.Request) {
	handlePage(w, g.populateRulesPage(r), rulesPageTmpl)
}

var rulesPageTmpl = newTemplate(rulesPageTmplFile, template.FuncMap{})

// populateRulesPage returns the contents of the rules page.
func (g *Gaby) populateRulesPage(r *http.Request) *rulesPage {
	pm := rulesParams{
		Query: r.FormValue(paramQuery),
	}
	p := &rulesPage{
		Params: pm,
	}
	p.setCommonPage()
	if pm.Query == "" {
		return p
	}
	proj, issue, err := parseIssueNumber(pm.Query)
	if err != nil {
		p.Error = fmt.Errorf("invalid form value %q: %w", pm.Query, err)
		return p
	}
	if proj == "" && len(g.githubProjects) > 0 {
		proj = g.githubProjects[0] // default to first project
	}
	if !slices.Contains(g.githubProjects, proj) {
		p.Error = fmt.Errorf("invalid form value (unrecognized project): %q", pm.Query)
		return p
	}
	if issue <= 0 {
		return p
	}
	// Find issue in database.
	i, err := github.LookupIssue(g.db, proj, issue)
	if err != nil {
		p.Error = fmt.Errorf("error looking up issue %q: %w", pm.Query, err)
		return p
	}

	// TODO: this llm.TextGenerator cast is kind of ugly. Redo somehow.
	rules, err := rules.Issue(r.Context(), g.embed.(llm.TextGenerator), i)
	if err != nil {
		p.Error = err
		return p
	}
	p.Result = &rulesResult{
		Issue:       i,
		IssueResult: *rules,
		HTML:        htmlutil.MarkdownToSafeHTML(rules.Response),
	}
	return p
}

func (p *rulesPage) setCommonPage() {
	p.CommonPage = CommonPage{
		ID:          rulesID,
		Description: "Generate a list of rule violations for submitted golang/go issues.",
		Styles:      []safeURL{searchID.CSS()},
		Form: Form{
			Inputs:     p.Params.inputs(),
			SubmitText: "generate",
		},
	}
}

func (pm *rulesParams) inputs() []FormInput {
	return []FormInput{
		{

			Label:       "issue",
			Type:        "int or string",
			Description: "the issue to check, as a number or URL (e.g. 1234, golang/go#1234, or https://github.com/golang/go/issues/1234)",
			Name:        safeQuery,
			Required:    true,
			Typed: TextInput{
				ID:    safeQuery,
				Value: pm.Query,
			},
		},
	}
}
