package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
	"time"

	"golang.org/x/crypto/ssh"
)

type CommandState string

type CommandStatus struct {
	Command string       `json:"command"`
	State   CommandState `json:"state"`
}

type Status struct {
	Commit   *Commit         `json:"commit"`
	Commands []CommandStatus `json:"commands"`
}

type Server struct {
	l           sync.Locker
	agentMode   bool
	port        int
	appId       string
	service     string
	id          string
	ready       bool
	cmd         *exec.Cmd
	repoAddr    string
	branch      string
	rootDir     string
	signer      ssh.Signer
	appDir      string
	runCommands []Command
	self        string
	managerAddr string
	logs        *Log
	currDir     string
	status      *Status
}

func NewServer(agentMode bool, port int, appId, service, id, repoAddr, branch, rootDir string, signer ssh.Signer, appDir string, runCommands []Command, self string, manager string) *Server {
	return &Server{
		l:           &sync.Mutex{},
		agentMode:   agentMode,
		port:        port,
		ready:       false,
		appId:       appId,
		service:     service,
		id:          id,
		repoAddr:    repoAddr,
		branch:      branch,
		rootDir:     rootDir,
		signer:      signer,
		appDir:      appDir,
		runCommands: runCommands,
		self:        self,
		managerAddr: manager,
		logs:        &Log{},
		currDir:     "",
		status:      nil,
	}
}

func (s *Server) Start() error {
	http.HandleFunc("/update", s.handleUpdate)
	http.HandleFunc("/ready", s.handleReady)
	http.HandleFunc("/logs", s.handleLogs)
	if s.managerAddr != "" && s.appId != "" {
		go s.pingManager()
	}
	if err := s.run(); err != nil {
		return err
	}
	return http.ListenAndServe(fmt.Sprintf(":%d", s.port), nil)
}

func (s *Server) handleLogs(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, s.logs.Contents())
}

func (s *Server) handleReady(w http.ResponseWriter, r *http.Request) {
	s.l.Lock()
	defer s.l.Unlock()
	if s.ready {
		fmt.Fprintln(w, "ok")
	} else {
		http.Error(w, "not ready", http.StatusInternalServerError)
	}
}

func (s *Server) handleUpdate(w http.ResponseWriter, r *http.Request) {
	fmt.Println("update")
	s.l.Lock()
	s.ready = false
	s.l.Unlock()
	fmt.Fprintf(s.logs, "!!! dodo: Reloading service\n")
	if err := s.run(); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	s.l.Lock()
	s.ready = true
	s.l.Unlock()
}

type command struct {
	cmd string
	env []string
}

func (s *Server) run() error {
	newDir := s.appDir
	commands := []command{}
	if !s.agentMode {
		var err error
		newDir, err = os.MkdirTemp(s.appDir, "code-*")
		if err != nil {
			return err
		}
	}
	if s.repoAddr != "" {
		commit, err := CloneRepositoryBranch(s.repoAddr, s.branch, s.rootDir, s.signer, newDir)
		if err != nil {
			fmt.Fprintf(s.logs, "!!! dodo: Failed to clone repository\n")
			s.status = &Status{
				Commit: nil,
			}
			return err
		}
		fmt.Fprintf(s.logs, "!!! dodo: Successfully cloned repository %s\n", commit.Hash)
		s.status = &Status{
			Commit:   commit,
			Commands: []CommandStatus{},
		}
	} else {
		s.status = &Status{
			Commit:   nil,
			Commands: []CommandStatus{},
		}
	}
	if s.agentMode {
		if _, err := os.Stat(filepath.Join(newDir, ".git")); err != nil && os.IsNotExist(err) {
			commands = append(commands, command{cmd: "git config --global user.name dodo"})
			s.status.Commands = append(s.status.Commands, CommandStatus{
				Command: commands[len(commands)-1].cmd,
				State:   "waiting",
			})
			commands = append(commands, command{cmd: "git config --global user.email dodo@dodo.cloud"})
			s.status.Commands = append(s.status.Commands, CommandStatus{
				Command: commands[len(commands)-1].cmd,
				State:   "waiting",
			})
			commands = append(commands, command{cmd: "git init ."})
			s.status.Commands = append(s.status.Commands, CommandStatus{
				Command: commands[len(commands)-1].cmd,
				State:   "waiting",
			})
			commands = append(commands, command{cmd: "echo \"TODO: Describe project\" > README.md"})
			s.status.Commands = append(s.status.Commands, CommandStatus{
				Command: commands[len(commands)-1].cmd,
				State:   "waiting",
			})
			commands = append(commands, command{cmd: "git add README.md"})
			s.status.Commands = append(s.status.Commands, CommandStatus{
				Command: commands[len(commands)-1].cmd,
				State:   "waiting",
			})
			commands = append(commands, command{cmd: "git commit -m \"init\""})
			s.status.Commands = append(s.status.Commands, CommandStatus{
				Command: commands[len(commands)-1].cmd,
				State:   "waiting",
			})
		}
	}
	for _, c := range s.runCommands {
		args := []string{c.Bin}
		args = append(args, c.Args...)
		cmd := strings.Join(args, " ")
		commands = append(commands, command{cmd, c.Env})
		s.status.Commands = append(s.status.Commands, CommandStatus{
			Command: cmd,
			State:   "waiting",
		})
	}
	logM := io.MultiWriter(os.Stdout, s.logs)
	for i, c := range commands {
		if i > 0 {
			s.status.Commands[i-1].State = "success"
		}
		cmd := &exec.Cmd{
			Dir:    filepath.Join(newDir, s.rootDir),
			Path:   "/bin/sh",
			Args:   []string{"/bin/sh", "-c", c.cmd},
			Env:    append(os.Environ(), c.env...),
			Stdout: logM,
			Stderr: logM,
		}
		cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
		fmt.Printf("Running: %s\n", c)
		fmt.Fprintf(s.logs, "!!! dodo: Running: %s\n", c)
		s.status.Commands[i].State = "running"
		if i < len(commands)-1 {
			if err := cmd.Run(); err != nil {
				return err
			}
		} else {
			if s.cmd != nil {
				// TODO(gio): make this point configurable
				if err := s.kill(); err != nil {
					return err
				}
				if s.currDir != "" && !s.agentMode {
					if err := os.RemoveAll(s.currDir); err != nil {
						return err
					}
				}
			}
			if err := cmd.Start(); err != nil {
				return err
			}
			s.cmd = cmd
		}
	}
	s.currDir = newDir
	return nil
}

type pingReq struct {
	Id      string  `json:"id"`
	Service string  `json:"service"`
	Address string  `json:"address"`
	Status  *Status `json:"status,omitempty"`
	Logs    string  `json:"logs"`
}

func (s *Server) pingManager() {
	defer func() {
		go func() {
			time.Sleep(5 * time.Second)
			s.pingManager()
		}()
	}()
	buf, err := json.Marshal(pingReq{
		Id:      s.id,
		Service: s.service,
		Address: fmt.Sprintf("http://%s:%d", s.self, s.port),
		Status:  s.status,
		Logs:    s.logs.Contents(),
	})
	if err != nil {
		return
	}
	registerWorkerAddr := fmt.Sprintf("%s/api/project/%s/workers", s.managerAddr, s.appId)
	resp, err := http.Post(registerWorkerAddr, "application/json", bytes.NewReader(buf))
	if err != nil {
		fmt.Println(err)
	} else {
		// check resp code
		io.Copy(os.Stdout, resp.Body)
	}
}

func (s *Server) kill() error {
	if s.cmd == nil {
		return nil
	}

	err := syscall.Kill(-s.cmd.Process.Pid, syscall.SIGKILL)
	if err != nil {
		return err
	}
	// NOTE(gio): No need to check err as we just killed the process
	s.cmd.Wait()
	s.cmd = nil
	return nil
}
