// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"os"
	"slices"
	"strconv"
	"strings"

	"github.com/google/keep-sorted/keepsorted"
	flag "github.com/spf13/pflag"
	"golang.org/x/exp/maps"
)

type Config struct {
	id             string
	defaultOptions keepsorted.BlockOptions
	operation      operation
	modifiedLines  []keepsorted.LineRange
}

func (c *Config) FromFlags(fs *flag.FlagSet) {
	if fs == nil {
		fs = flag.CommandLine
	}

	fs.StringVar(&c.id, "id", "keep-sorted", "The identifier used to enable this tool in files.")
	if err := fs.MarkHidden("id"); err != nil {
		panic(err)
	}

	c.defaultOptions = keepsorted.DefaultBlockOptions()
	fs.Var(&blockOptionsFlag{&c.defaultOptions}, "default-options", "The options keep-sorted will use to sort. Per-block overrides apply on top of these options. Note: list options like prefix_order are not merged with per-block overrides. They are completely overridden.")

	of := &operationFlag{op: &c.operation}
	if err := of.Set("fix"); err != nil {
		panic(err)
	}
	fs.Var(of, "mode", fmt.Sprintf("Determines what mode to run this tool in. One of %q", knownModes()))

	fs.Var(&lineRangeFlag{lineRanges: &c.modifiedLines}, "lines", "Line ranges of the form \"start:end\". Only processes keep-sorted blocks that overlap with the given line ranges. Can only be used when fixing a single file. This flag can either be a comma-separated list of line ranges, or it can be specified multiple times on the command line to specify multiple line ranges.")
}

type blockOptionsFlag struct {
	opts *keepsorted.BlockOptions
}

func (f *blockOptionsFlag) String() string {
	return f.opts.String()
}

func (f *blockOptionsFlag) Set(val string) error {
	opts, err := keepsorted.ParseBlockOptions(val)
	if err != nil {
		return err
	}
	*f.opts = opts
	return nil
}

func (f *blockOptionsFlag) Type() string {
	return "options"
}

var (
	operations = map[string]operation{
		"lint": lint,
		"fix":  fix,
	}
)

func knownModes() []string {
	ms := maps.Keys(operations)
	slices.Sort(ms)
	return ms
}

type operation func(fixer *keepsorted.Fixer, filenames []string, modifiedLines []keepsorted.LineRange) (ok bool, err error)

type operationFlag struct {
	op *operation
	s  string
}

func (f *operationFlag) String() string {
	return f.s
}

func (f *operationFlag) Set(val string) error {
	op := operations[val]
	if op == nil {
		return fmt.Errorf("unknown mode %q. Valid modes: %q", val, knownModes())
	}
	f.s = val
	*f.op = op
	return nil
}

func (f *operationFlag) Type() string {
	return "mode"
}

type lineRangeFlag struct {
	lineRanges *[]keepsorted.LineRange
	changed    bool
	s          []string
}

func (f *lineRangeFlag) String() string {
	return "[" + strings.Join(f.GetSlice(), ",") + "]"
}

func (f *lineRangeFlag) Set(val string) error {
	vals := strings.Split(val, ",")
	if !f.changed {
		return f.Replace(vals)
	}

	for _, val := range vals {
		if err := f.Append(val); err != nil {
			return err
		}
	}
	return nil
}

func (f *lineRangeFlag) Type() string {
	return "line_ranges"
}

func (f *lineRangeFlag) Append(val string) error {
	f.changed = true
	lrs, err := f.parse([]string{val})
	if err != nil {
		return err
	}
	*f.lineRanges = append(*f.lineRanges, lrs...)
	f.s = append(f.s, val)
	return nil
}

func (f *lineRangeFlag) Replace(vals []string) error {
	f.changed = true
	lrs, err := f.parse(vals)
	if err != nil {
		return err
	}
	*f.lineRanges = lrs
	f.s = vals
	return nil
}

func (f *lineRangeFlag) parse(vals []string) ([]keepsorted.LineRange, error) {
	var lrs []keepsorted.LineRange
	for _, val := range vals {
		sp := strings.SplitN(val, ":", 2)
		start, err := strconv.Atoi(sp[0])
		if err != nil {
			return nil, fmt.Errorf("invalid line range %q: %w", val, err)
		}
		var end int
		if len(sp) == 1 {
			end = start
		} else {
			end, err = strconv.Atoi(sp[1])
			if err != nil {
				return nil, fmt.Errorf("invalid line range %q: %w", val, err)
			}
		}

		lrs = append(lrs, keepsorted.LineRange{Start: start, End: end})
	}
	return lrs, nil
}

func (f *lineRangeFlag) GetSlice() []string {
	return f.s
}

const (
	stdin = "-"
)

func Run(c *Config, files []string) (ok bool, err error) {
	if c.id == "" {
		return false, errors.New("id cannot be empty")
	}

	if len(files) == 0 {
		return false, errors.New("must pass one or more filenames")
	}

	if len(c.modifiedLines) > 0 && len(files) > 1 {
		return false, errors.New("cannot specify modifiedLines with more than one file")
	}

	return c.operation(keepsorted.New(c.id, c.defaultOptions), files, c.modifiedLines)
}

func fix(fixer *keepsorted.Fixer, filenames []string, modifiedLines []keepsorted.LineRange) (ok bool, err error) {
	for _, fn := range filenames {
		contents, err := read(fn)
		if err != nil {
			return false, err
		}
		if want, alreadyFixed := fixer.Fix(contents, modifiedLines); fn == stdin || !alreadyFixed {
			if err := write(fn, want); err != nil {
				return false, err
			}
		}
	}
	return true, nil
}

func lint(fixer *keepsorted.Fixer, filenames []string, modifiedLines []keepsorted.LineRange) (ok bool, err error) {
	var fs []*keepsorted.Finding
	for _, fn := range filenames {
		contents, err := read(fn)
		if err != nil {
			return false, err
		}
		fs = append(fs, fixer.Findings(fn, contents, modifiedLines)...)
	}

	if len(fs) == 0 {
		return true, nil
	}

	out := json.NewEncoder(os.Stdout)
	out.SetIndent("", "  ")
	if err := out.Encode(fs); err != nil {
		return false, fmt.Errorf("could not write findings to stdout: %w", err)
	}

	return false, nil
}

func read(fn string) (string, error) {
	if fn == stdin {
		b, err := io.ReadAll(os.Stdin)
		return string(b), err
	}

	b, err := os.ReadFile(fn)
	return string(b), err
}

func write(fn string, s string) error {
	if fn == stdin {
		_, err := os.Stdout.WriteString(s)
		return err
	}

	return os.WriteFile(fn, []byte(s), 0644)
}
