// Copyright 2022 The Fuchsia 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 (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"gopkg.in/yaml.v2"

	"go.fuchsia.dev/fuchsia/tools/staticanalysis"
)

const (
	rfcsDir      = "docs/contribute/governance/rfcs"
	tocPath      = "docs/contribute/governance/rfcs/_toc.yaml"
	rfcIndexPath = "docs/contribute/governance/rfcs/_rfcs.yaml"
	areasPath    = "docs/contribute/governance/rfcs/_areas.yaml"
)

type analyzer struct {
	checkoutDir string
}

func (a *analyzer) Analyze(_ context.Context, path string) ([]*staticanalysis.Finding, error) {
	if path == tocPath {
		return a.analyzeToc()
	}

	if path == rfcIndexPath {
		return a.analyzeRfcIndex()
	}

	if rfcId := parseRfcPath(path); rfcId != "" {
		return a.analyzeRfcFile(path, rfcId)
	}

	return nil, nil
}

var reRfcFilename = regexp.MustCompile(`^(\d{4})_.*\.md$`)

// parseRfcPath returns the RFC ID from a path that looks like an RFC, or the
// empty string otherwise.
func parseRfcPath(path string) string {
	base := filepath.Base(path)
	match := reRfcFilename.FindStringSubmatch(base)
	if match != nil {
		return match[1]
	}
	// RFC filenames will generally start with a placeholder prefix like "NNNN"
	// until they are assigned a number. Files with such a prefix should still
	// be analyzed.
	placeholderPrefix := strings.Repeat(string(base[0]), 4)
	if strings.HasPrefix(base, placeholderPrefix+"_") {
		return placeholderPrefix
	}
	return ""
}

// toc represents a subset of the schema of _toc.yaml.
type toc struct {
	Entries []*tocEntry `yaml:"toc"`
}

// tocEntry is one entry in _toc.yaml.
type tocEntry struct {
	Title   string      `yaml:"title"`
	Path    string      `yaml:"path"`
	Section []*tocEntry `yaml:"section"`
}

// analyzeToc returns findings from _toc.yaml.
func (a *analyzer) analyzeToc() ([]*staticanalysis.Finding, error) {
	file, err := os.ReadFile(filepath.Join(a.checkoutDir, tocPath))
	if err != nil {
		return nil, err
	}

	var toc toc
	if err := yaml.Unmarshal(file, &toc); err != nil {
		return []*staticanalysis.Finding{
			{
				Category: "rfcmeta/toc/failed_to_parse",
				Message:  fmt.Sprintf("Failed to parse yaml: %v", err),
				Path:     tocPath,
			},
		}, nil
	}

	var findings []*staticanalysis.Finding
	for _, entry := range flattenTocEntries(toc.Entries) {
		if entry.Title == "" {
			findings = append(findings, &staticanalysis.Finding{
				Category: "rfcmeta/toc/missing_name",
				Message:  fmt.Sprintf("An entry is missing the `title` field"),
				Path:     tocPath,
				// Don't include a line number, because searching for the empty
				// string isn't going to yield helpful results.
			})
			continue
		}

		// Ignore entries that don't look like RFCs
		titleRfcId := parseRfcTitle(entry.Title)
		if titleRfcId == "" {
			continue
		}

		// Attach findings to the line with the title, since we know it's not empty.
		lineNo := findLineContaining(file, entry.Title)

		// Ensure the path matches the RFC ID.
		expectedPathPrefix := filepath.Join("/", rfcsDir, titleRfcId+"_")
		if !strings.HasPrefix(entry.Path, expectedPathPrefix) {
			findings = append(findings, &staticanalysis.Finding{
				Category: "rfcmeta/toc/unexpected_path",
				Message: fmt.Sprintf("path for %q should begin with %q; found %q",
					entry.Title, expectedPathPrefix, entry.Path),
				Path:    tocPath,
				Line:    lineNo,
				EndLine: lineNo,
			})
		}

		// Ensure the path actually exists.
		if _, err := os.Stat(filepath.Join(a.checkoutDir, entry.Path)); errors.Is(err, os.ErrNotExist) {
			findings = append(findings, &staticanalysis.Finding{
				Category: "rfcmeta/toc/file_not_found",
				Message:  fmt.Sprintf("File %q doesn't exist", entry.Path),
				Path:     tocPath,
				Line:     lineNo,
				EndLine:  lineNo,
			})
		} else if err != nil {
			return findings, err
		}
	}
	return findings, nil
}

// rfcIndexEntry represents a subset of the schema for entries in _rfcs.yaml.
type rfcIndexEntry struct {
	Name  string   `yaml:"name"`
	Title string   `yaml:"title"`
	File  string   `yaml:"file"`
	Areas []string `yaml:"area"`
}

// analyzeRfcIndex returns findings from _rfcs.yaml.
func (a *analyzer) analyzeRfcIndex() ([]*staticanalysis.Finding, error) {
	file, err := os.ReadFile(filepath.Join(a.checkoutDir, rfcIndexPath))
	if err != nil {
		return nil, err
	}

	var index []*rfcIndexEntry
	if err := yaml.Unmarshal(file, &index); err != nil {
		return []*staticanalysis.Finding{
			{
				Category: "rfcmeta/index/failed_to_parse",
				Message:  fmt.Sprintf("Failed to parse yaml: %v", err),
				Path:     rfcIndexPath,
			},
		}, nil
	}

	var findings []*staticanalysis.Finding
	for _, rfc := range index {
		if rfc.Name == "" {
			findings = append(findings, &staticanalysis.Finding{
				Category: "rfcmeta/index/missing_name",
				Message:  fmt.Sprintf("An entry is missing the `name` field"),
				Path:     rfcIndexPath,
				// Don't include a line number, because searching for the empty
				// string isn't going to yield helpful results.
			})
			continue
		}

		rfcId := parseRfcTitle(rfc.Name)

		// Display findings on the line with the name, because we at least know
		// it's non-empty.
		lineNo := findLineContaining(file, rfc.Name)
		if rfcId == "" {
			findings = append(findings, &staticanalysis.Finding{
				Category: "rfcmeta/index/invalid_name",
				Message: fmt.Sprintf(
					"RFC name %q should look like \"RFC-1234\"", rfc.Title),
				Path:    rfcIndexPath,
				Line:    lineNo,
				EndLine: lineNo,
			})
			continue
		}

		// RFC-0000 is the template, so it's special. Skip the other checks.
		if rfcId == "0000" {
			continue
		}

		// Check that the "area" field is not empty.
		if len(rfc.Areas) == 0 {
			findings = append(findings, &staticanalysis.Finding{
				Category: "rfcmeta/index/missing_area",
				Message: fmt.Sprintf("Include an 'area' for this RFC. Options are listed in //%s",
					areasPath),
				Path:    rfcIndexPath,
				Line:    lineNo,
				EndLine: lineNo,
			})
		}

		// Check that the "area" field refers to known areas.
		knownAreas := a.loadAreas()
		for _, area := range rfc.Areas {
			if !knownAreas[area] {
				findings = append(findings, &staticanalysis.Finding{
					Category: "rfcmeta/index/unknown_area",
					Message: fmt.Sprintf("area %q is not listed in //%s",
						area, areasPath),
					Path:    rfcIndexPath,
					Line:    lineNo,
					EndLine: lineNo,
				})
			}
		}

		// Check that the path looks right.
		if !strings.HasPrefix(rfc.File, rfcId+"_") {
			findings = append(findings, &staticanalysis.Finding{
				Category: "rfcmeta/index/unexpected_path",
				Message: fmt.Sprintf("path for %q should begin with %q; found %q",
					rfc.Name, rfcId+"_", rfc.File),
				Path:    rfcIndexPath,
				Line:    lineNo,
				EndLine: lineNo,
			})
		}

		// ... and that there's a real file there.
		if _, err := os.Stat(filepath.Join(a.checkoutDir, rfcsDir, rfc.File)); errors.Is(err, os.ErrNotExist) {
			findings = append(findings, &staticanalysis.Finding{
				Category: "rfcmeta/index/file_not_found",
				Message: fmt.Sprintf("file %q does not exist",
					filepath.Join(rfcsDir, rfc.File)),
				Path:    rfcIndexPath,
				Line:    lineNo,
				EndLine: lineNo,
			})
		} else if err != nil {
			return findings, err
		}
	}
	return findings, nil
}

// analyzeRfcIndex returns findings from the markdown file itself for an RFC.
// `rfcId` should be the RFC's 4-character ID, parsed out of `path`.
func (a *analyzer) analyzeRfcFile(path string, rfcId string) ([]*staticanalysis.Finding, error) {
	var findings []*staticanalysis.Finding

	// Check if the `rfcId` looks like a placeholder, i.e., it's 4 copies of the
	// same character.
	//
	// If you're here because we got to RFC-1111, greetings from the past!
	if rfcId == strings.Repeat(string(rfcId[0]), 4) {
		finding := &staticanalysis.Finding{
			Category: "rfcmeta/file/placeholder_id",
			Message: fmt.Sprintf(
				"RFC filename begins with %q. Replace it with the RFC number before submitting.",
				rfcId),
			Path: path,
		}
		findings = append(findings, finding)
	}

	// Check if it's in the table of contents.
	if !a.tocContainsPath(path) {
		findings = append(findings, &staticanalysis.Finding{
			Category: "rfcmeta/file/not_in_toc",
			Message:  "No matching entry in _toc.yaml",
			Path:     path,
		})
	}

	// Check if it's in the RFC index.
	if !a.rfcIndexContainsPath(path) {
		findings = append(findings, &staticanalysis.Finding{
			Category: "rfcmeta/file/not_in_index",
			Message:  "RFC is not listed in _rfcs.yaml",
			Path:     path,
		})
	}

	loadedFile, err := os.ReadFile(filepath.Join(a.checkoutDir, path))
	if err != nil {
		return findings, err
	}
	file := strings.Split(string(loadedFile), "\n")

	// Look for the `set rfcid =` tag.
	findings = append(findings, analyzeSetRfcIdTag(path, rfcId, file)...)

	return findings, nil
}

// tocContainsPath returns true if an entry corresponding to `path` was found in
// the table of contents. Any error encountered while reading or parsing
// `_toc.yaml` counts as "not finding the path", and this function will return
// false.
func (a *analyzer) tocContainsPath(path string) bool {
	b, err := os.ReadFile(filepath.Join(a.checkoutDir, tocPath))
	if err != nil {
		return false
	}

	var toc toc
	if err := yaml.Unmarshal(b, &toc); err != nil {
		return false
	}

	for _, entry := range flattenTocEntries(toc.Entries) {
		if entry.Path == filepath.Join("/", path) {
			return true
		}
	}
	return false
}

// rfcIndexContainsPath returns true if an entry corresponding to `path` was
// found in the RFC metadata index. Any error encountered while reading or
// parsing `_rfcs.yaml` counts as "not finding the path", and this function will
// return false.
func (a *analyzer) rfcIndexContainsPath(path string) bool {
	b, err := os.ReadFile(filepath.Join(a.checkoutDir, rfcIndexPath))
	if err != nil {
		return false
	}

	rfcIndex := []*rfcIndexEntry{}
	if err = yaml.Unmarshal(b, &rfcIndex); err != nil {
		return false
	}

	for _, r := range rfcIndex {
		if r.File == filepath.Base(path) {
			return true
		}
	}
	return false
}

// loadAreas returns a set of strings representing the areas in
// rfcs/_areas.yaml. If this function encounters any problems while reading or
// parsing `_areas.yaml` it will return nil (i.e., an empty set).
func (a *analyzer) loadAreas() map[string]bool {
	b, err := os.ReadFile(filepath.Join(a.checkoutDir, areasPath))
	if err != nil {
		return nil
	}

	areasList := []string{}
	if err = yaml.Unmarshal(b, &areasList); err != nil {
		return nil
	}

	areasMap := make(map[string]bool)
	for _, area := range areasList {
		areasMap[area] = true
	}
	return areasMap
}

var reSetRfcIdTag = regexp.MustCompile(`(^.*set *rfcid *= *"RFC-)([^"]*)(".*$)`)

// analyzeSetRfcIdTag looks for a jinja tag like {% set rfcid = "RFC-1234" %} in
// the given file. Findings will be returned if the tag is missing, or if it
// doesn't have the correct RFC ID.
func analyzeSetRfcIdTag(path string, rfcId string, file []string) []*staticanalysis.Finding {
	for i, line := range file {
		match := reSetRfcIdTag.FindStringSubmatch(line)
		if match == nil {
			continue
		}

		if match[2] == rfcId {
			// The tag looks good.
			return nil
		}
		return []*staticanalysis.Finding{{
			Category: "rfcmeta/file/rfcid_mismatch",
			Message:  fmt.Sprintf("Filename has RFC ID %q, but the rfcid tag has ID %q", rfcId, match[2]),
			Path:     path,
			Line:     i + 1,
			EndLine:  i + 1,
			Col:      1,
			EndCol:   len(line) + 1,
			Replacements: []string{
				match[1] + rfcId + match[3],
			},
		}}
	}

	// If we made it to the end without finding the tag, complain.
	return []*staticanalysis.Finding{{
		Category: "rfcmeta/file/rfcid_tag_not_found",
		Message:  "No `{% set rfcid = \"RFC-" + rfcId + "\" %}` tag found.",
		Path:     path,
	}}
}

var reRfcTitle = regexp.MustCompile("^RFC-(....)")

// parseRfcTitle pulls the RFC ID out of a string like "RFC-1234: ...". If `s`
// doesn't look like an RFC title, it returns the empty string.
func parseRfcTitle(s string) string {
	match := reRfcTitle.FindStringSubmatch(s)
	if match == nil {
		return ""
	}
	return match[1]
}

// findLineContaining returns the 1-indexed line number of the first line
// containing `substring` in `file`. If no such line is found, it returns 0.
//
// Use of this function is mostly a hack. The yaml.v2 module discards line
// number information when parsing YAML, so we use this function to guess as to
// where the errors might be in the file. yaml.v3 supports returning an AST, so
// the "correct" thing to do would be to upgrade yaml.v2 to yaml.v3 and get the
// line numbers from the parser.
func findLineContaining(file []byte, substr string) int {
	for i, line := range bytes.Split(file, []byte{'\n'}) {
		if strings.Contains(string(line), substr) {
			return i + 1
		}
	}
	return 0
}

// flattenTocEntries flattens the table of contents by removing any nesting with
// "sections", and returning a list of the "leaf" entries.
func flattenTocEntries(toc []*tocEntry) []*tocEntry {
	var res []*tocEntry
	for _, entry := range toc {
		if len(entry.Section) != 0 {
			res = append(res, flattenTocEntries(entry.Section)...)
		} else {
			res = append(res, entry)
		}
	}
	return res
}

func mainImpl() error {
	var checkoutDir string
	flag.StringVar(&checkoutDir, "checkout-dir", "", "Path to the Fuchsia checkout root")
	flag.Parse()

	findings := []*staticanalysis.Finding{}
	paths := flag.Args()
	a := analyzer{checkoutDir: checkoutDir}
	for _, path := range paths {
		f, err := a.Analyze(context.Background(), path)
		if err != nil {
			return err
		}
		findings = append(findings, f...)
	}

	enc := json.NewEncoder(os.Stdout)
	enc.SetIndent("", "  ")
	return enc.Encode(findings)
}

func main() {
	if err := mainImpl(); err != nil {
		log.Fatal(err)
	}
}
