package lib

import (
	"fmt"
	"strconv"
	"time"
)

type Vuln struct {
	ID       string
	Desc     string
	Source   string
	Severity string
	Package  string
	Versions string
	Status   string
	Message  string
	Author   string
	Date     string
	Updated  string
}

func ValidSeverity(s string) bool {
	switch s {
	case "Low":
		return true
	case "Medium":
		return true
	case "High":
		return true
	case "Critical":
		return true
	}
	return false
}

func (v *Vuln) StatusColor() string {
	switch v.Status {
	case "Waiting for review":
		return "blue"
	case "Ongoing review":
		return "blue"
	case "Working on a patch":
		return "blue"
	case "Won't patch":
		return "red"
	case "Patched":
		return "green"
	case "Not affected":
		return "red"
	}

	return ""
}

func GetID() string {
	now := time.Now()
	mic := strconv.FormatInt(now.UnixMicro(), 10)
	sig := GetSHA256([]byte(mic))[:5]

	return fmt.Sprintf(
		"MPSI-%s%s-%s",
		now.Format("06"), now.Format("01"), sig,
	)
}

func LoadVulns() ([]Vuln, error) {
	var vulns []Vuln

	rows, err := Db.Query("SELECT * FROM vulns")
	if err != nil {
		return vulns, err
	}
	defer rows.Close()

	for rows.Next() {
		var v Vuln
		rows.Scan(
			&v.ID, &v.Desc, &v.Source, &v.Severity,
			&v.Package, &v.Versions, &v.Status, &v.Message,
			&v.Author, &v.Date, &v.Updated)
		vulns = append(vulns, v)
	}

	return vulns, nil
}

func FindVuln(id string) (Vuln, bool) {
	var vuln Vuln

	smt, err := Db.Prepare("SELECT * FROM vulns WHERE id=?")
	if err != nil {
		return vuln, false
	}

	row := smt.QueryRow(id)
	err = row.Scan(
		&vuln.ID, &vuln.Desc, &vuln.Source, &vuln.Severity,
		&vuln.Package, &vuln.Versions, &vuln.Status, &vuln.Message,
		&vuln.Author, &vuln.Date, &vuln.Updated)
	if err != nil {
		return vuln, false
	}

	return vuln, true
}

func AddVuln(v Vuln) error {
	smt, err := Db.Prepare("INSERT INTO vulns VALUES(?,?,?,?,?,?,?,?,?,?,?)")
	if err != nil {
		return err
	}

	_, err = smt.Exec(&v.ID, &v.Desc, &v.Source, &v.Severity,
		&v.Package, &v.Versions, &v.Status, &v.Message,
		&v.Author, &v.Date, &v.Updated)
	if err != nil {
		return err
	}

	return nil
}

func UpdateVuln(v Vuln) error {
	smt, err := Db.Prepare("UPDATE vulns SET status=?, message=?, author=?, severity=?, updated=? WHERE id=?")
	if err != nil {
		return err
	}

	_, err = smt.Exec(v.Status, v.Message,
		v.Author, v.Severity, GetFTime(), v.ID)
	if err != nil {
		return err
	}

	return nil
}