// Copyright 2024 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//  1. Redistributions of source code must retain the above copyright notice, this
//     list of conditions and the following disclaimer.
//
//  2. Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//  3. Neither the name of the copyright holder nor the names of its
//     contributors may be used to endorse or promote products derived from
//     this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package common

import (
	"context"
	"fmt"
	"log"
	"os/exec"
	"strings"
	"time"

	"dawn.googlesource.com/dawn/tools/src/container"
	"dawn.googlesource.com/dawn/tools/src/cts/query"
	"dawn.googlesource.com/dawn/tools/src/cts/result"
	"go.chromium.org/luci/auth"
	"google.golang.org/api/option"
	"google.golang.org/api/sheets/v4"
)

// Export appends the results binned by status and number of unimplemented tests to a Google Sheets document.
func Export(ctx context.Context,
	credentials auth.Options,
	sheetsID, ctsDir, node, npmPath string,
	resultsByExecutionMode result.ResultsByExecutionMode) error {
	// Create the sheets service client
	http, err := auth.NewAuthenticator(ctx, auth.InteractiveLogin, credentials).Client()
	if err != nil {
		return err
	}

	s, err := sheets.NewService(ctx, option.WithHTTPClient(http))
	if err != nil {
		return fmt.Errorf("unable to create sheets client: %w", err)
	}

	// Get the CTS statistics spreadsheet
	spreadsheet, err := s.Spreadsheets.Get(sheetsID).Do()
	if err != nil {
		return fmt.Errorf("failed to get spreadsheet: %w", err)
	}

	// Get the unimplemented tests
	unimplemented, err := GetUnimplementedTests(ctx, ctsDir, node, npmPath)
	if err != nil {
		return fmt.Errorf("failed to obtain number of unimplemented tests: %w", err)
	}

	// Generate a new set of counts of test by status
	for mode, results := range resultsByExecutionMode {
		name := string(mode) + "-data"
		// Scan the sheets of the spreadsheet (tabs at the bottom) for the sheet named `name`.
		var dataSheet *sheets.Sheet
		for _, sheet := range spreadsheet.Sheets {
			if strings.ToLower(sheet.Properties.Title) == name {
				dataSheet = sheet
				break
			}
		}
		if dataSheet == nil {
			return fmt.Errorf("failed to find sheet '%v'", name)
		}

		// Fetch the table column names
		columns, err := fetchRow[string](s, spreadsheet, dataSheet, 0)
		if err != nil {
			return err
		}

		counts := container.NewMap[string, int]()
		for _, r := range results {
			if r.Status == "Skip" {
				// Unimplemented tests are marked as 'Skip' by the CTS runner.
				// Check the unimplemented query tree to see if this should be classed as
				// 'Unimplemented' instead.
				if node := unimplemented.Get(r.Query); node != nil && node.Data != nil {
					counts[("Unimplemented")]++
					continue
				}
			}
			counts[string(r.Status)]++
		}

		{ // Report statuses that have no column
			missingColumns := container.NewSet(counts.Keys()...)
			missingColumns.RemoveAll(container.NewSet(columns...))
			for _, status := range missingColumns.List() {
				log.Println("no column for status", status)
			}
		}

		// Generate new cell data based on the table column names
		data := []any{}
		for _, column := range columns {
			switch strings.ToLower(column) {
			case "date":
				data = append(data, time.Now().UTC().Format("2006-01-02"))
			default:
				count, ok := counts[column]
				if !ok {
					log.Println("no results with status", column)
				}
				data = append(data, count)
			}
		}

		// Insert a blank row under the column header row
		if err := insertBlankRows(s, spreadsheet, dataSheet, 1, 1); err != nil {
			return err
		}

		// Add a new row to the spreadsheet
		_, err = s.Spreadsheets.Values.BatchUpdate(spreadsheet.SpreadsheetId,
			&sheets.BatchUpdateValuesRequest{
				ValueInputOption: "RAW",
				Data: []*sheets.ValueRange{{
					Range:  rowRange(1, dataSheet),
					Values: [][]any{data},
				}},
			}).Do()
		if err != nil {
			return fmt.Errorf("failed to update spreadsheet: %v\n\ndata: %+v", err, data)
		}
	}

	return nil
}

// rowRange returns a sheets range ("name!Ai:i") for the entire row with the
// given index.
func rowRange(index int, sheet *sheets.Sheet) string {
	return fmt.Sprintf("%v!A%v:%v", sheet.Properties.Title, index+1, index+1)
}

// fetchRow returns all the values in the given sheet's row.
func fetchRow[T any](srv *sheets.Service, spreadsheet *sheets.Spreadsheet, sheet *sheets.Sheet, row int) ([]T, error) {
	rng := rowRange(row, sheet)
	data, err := srv.Spreadsheets.Values.Get(spreadsheet.SpreadsheetId, rng).Do()
	if err != nil {
		return nil, fmt.Errorf("Couldn't fetch %v: %w", rng, err)
	}
	out := make([]T, len(data.Values[0]))
	for column, v := range data.Values[0] {
		val, ok := v.(T)
		if !ok {
			return nil, fmt.Errorf("cell at %v:%v was type %T, but expected type %T", row, column, v, val)
		}
		out[column] = val
	}
	return out, nil
}

// insertBlankRows inserts blank rows into the given sheet.
func insertBlankRows(srv *sheets.Service, spreadsheet *sheets.Spreadsheet, sheet *sheets.Sheet, aboveRow, count int) error {
	req := sheets.BatchUpdateSpreadsheetRequest{
		Requests: []*sheets.Request{{
			InsertRange: &sheets.InsertRangeRequest{
				Range: &sheets.GridRange{
					SheetId:       sheet.Properties.SheetId,
					StartRowIndex: int64(aboveRow),
					EndRowIndex:   int64(aboveRow + count),
				},
				ShiftDimension: "ROWS",
			}},
		},
	}
	if _, err := srv.Spreadsheets.BatchUpdate(spreadsheet.SpreadsheetId, &req).Do(); err != nil {
		return fmt.Errorf("BatchUpdate failed: %v", err)
	}
	return nil
}

// GetUnimplementedTests returns the unimplemented tests in the CTS.
// It does this by running the cmdline.ts CTS command with '--list-unimplemented webgpu:*'.
func GetUnimplementedTests(ctx context.Context, ctsDir, node, npmPath string) (*query.Tree[struct{}], error) {
	if err := InstallCTSDeps(ctx, ctsDir, npmPath); err != nil {
		return nil, err
	}

	// Run 'src/common/runtime/cmdline.ts' to obtain the full test list
	cmd := exec.CommandContext(ctx, node,
		"-e", "require('./src/common/tools/setup-ts-in-node.js');require('./src/common/runtime/cmdline.ts');",
		"--", // Start of arguments
		// src/common/runtime/helper/sys.ts expects 'node file.js <args>'
		// and slices away the first two arguments. When running with '-e', args
		// start at 1, so just inject a placeholder argument.
		"placeholder-arg",
		"--list-unimplemented",
		"webgpu:*",
	)
	cmd.Dir = ctsDir

	out, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("failed to gather unimplemented tests: %w", err)
	}

	tree, _ := query.NewTree[struct{}]()
	for _, line := range strings.Split(string(out), "\n") {
		line = strings.TrimSpace(line)
		if line != "" {
			q := query.Parse(line)
			tree.Add(q, struct{}{})
		}
	}
	return &tree, nil
}
