package main

import (
	"encoding/json"
	"fmt"
	"os"
	"strings"
	"time"

	"git.tilde.town/tildetown/town/models"
	"git.tilde.town/tildetown/town/signup"
	"git.tilde.town/tildetown/town/stats"
	"git.tilde.town/tildetown/town/towndb"
	"github.com/AlecAivazis/survey/v2"
)

// this is basically a pile of scripts. no hope is to be found here. this is
// dirty, one off code stored in case any useful patterns are worth extracting
// or for copypasta fodder.

func confirmContinue(msg string) {
	var serr error
	var conf bool
	if serr = survey.AskOne(&survey.Confirm{
		Message: msg,
		Default: false,
	}, &conf); serr != nil {
		os.Exit(2)
	}
	if !conf {
		os.Exit(1)
	}
}

type jsonSignup struct {
	Created  float64
	Email    string
	Username string
	Reasons  string
	Plans    string
	Referral string
	Socials  string
	Notes    string
}

func main() {
	db, err := towndb.ConnectDB()
	if err != nil {
		panic(err)
	}

	lol, err := os.ReadFile("/town/var/users.json")
	if err != nil {
		panic(err)
	}

	td, err := stats.Stats()
	if err != nil {
		panic(err)
	}

	lines := strings.Split(string(lol), "\n")
	errs := []error{}
	signups := make([]jsonSignup, len(lines))
	for i, l := range lines {
		l = strings.TrimSpace(l)
		if l == "" {
			continue
		}
		s := jsonSignup{}
		err := json.Unmarshal([]byte(l), &s)
		if err != nil {
			fmt.Printf("%s %s", l, err.Error())
			errs = append(errs, err)
		} else {
			signups[i] = s
		}
	}
	if len(errs) > 0 {
		confirmContinue(fmt.Sprintf("%d errors found deserializing; continue?", len(errs)))
	}

	ttbirth, err := time.Parse("2006-01-02 3:04pm", "2014-10-11 11:49pm")
	if err != nil {
		panic(err)
	}

	me := towndb.TownUser{
		Created:  ttbirth,
		Username: "vilmibm",
		Emails:   []string{"vilmibm@protonmail.com"},
		State:    towndb.StateActive,
		IsAdmin:  true,
	}
	err = me.Insert(db)
	if err != nil {
		panic(err)
	}

	notFound := []jsonSignup{}
	found := []jsonSignup{}
	for _, su := range signups {
		fl := len(found)
		for _, u := range td.Users {
			if su.Username == u.Username {
				found = append(found, su)
				break
			}
		}
		if len(found) == fl {
			notFound = append(notFound, su)
		}
	}
	if len(notFound) > 0 {
		confirmContinue(fmt.Sprintf("%d of those were not found. continue?", len(notFound)))
	}

	for _, su := range found {
		var emails []string
		if su.Email != "" {
			emails = []string{su.Email}
		}

		u := towndb.TownUser{
			Created:  time.Unix(int64(su.Created), 0),
			Emails:   emails,
			Username: su.Username,
			State:    towndb.StateActive,
		}
		if err = u.Insert(db); err != nil {
			confirmContinue(fmt.Sprintf("%#v led to error %s; continue?", u, err.Error()))
		}

		if su.Notes != "" {
			note := towndb.AdminNote{
				Created:  time.Time{},
				AuthorID: me.ID,
				Content:  su.Notes,
				UserID:   u.ID,
			}
			if err = note.Insert(db); err != nil {
				confirmContinue(fmt.Sprintf("%#v led to error %s; continue?", note, err.Error()))
			}
		}
	}
}

func importSignups() {
	lol, err := os.ReadFile("/town/var/signups.json")
	if err != nil {
		panic(err)
	}

	db, err := signup.ConnectDB()
	if err != nil {
		panic(err)
	}

	lines := strings.Split(string(lol), "\n")
	errs := []error{}
	signups := make([]jsonSignup, len(lines))
	for i, l := range lines {
		l = strings.TrimSpace(l)
		if l == "" {
			continue
		}
		s := jsonSignup{}
		err := json.Unmarshal([]byte(l), &s)
		if err != nil {
			fmt.Printf("%s %s", l, err.Error())
			errs = append(errs, err)
		} else {
			signups[i] = s
		}
	}
	if len(errs) > 0 {
		confirmContinue(fmt.Sprintf("%d errors found deserializing; continue?", len(errs)))
	}

	for _, s := range signups {
		ts := models.TownSignup{
			Created: time.Unix(int64(s.Created), 0),
			Email:   s.Email,
			How:     s.Referral,
			Why:     s.Reasons + "\n" + s.Plans,
			Links:   s.Socials,
		}
		if err = ts.Insert(db); err != nil {
			confirmContinue(fmt.Sprintf("%#v led to error %s; continue?", ts, err.Error()))
		}

		if s.Notes != "" {
			note := models.SignupNote{
				Created:  time.Now(),
				Author:   "IMPORT",
				Content:  s.Notes,
				SignupID: ts.ID,
			}
			if err = note.Insert(db); err != nil {
				confirmContinue(fmt.Sprintf("%#v led to error %s; continue?", ts, err.Error()))
			}
		}
	}
}
