package main

import (
	"database/sql"
	"embed"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"log"
	"math/rand"
	"net/http"
	"strings"

	"github.com/mattn/go-sqlite3"
)

var port = flag.Int("port", 8080, "Port to listen on")
var dbPath = flag.String("db-path", "url-shortener.db", "Path to the SQLite file")

//go:embed index.html
var indexHTML embed.FS

//go:embed static/*
var f embed.FS

type NamedAddress struct {
	Name    string
	Address string
	OwnerId string
	Active  bool
}

type Store interface {
	Create(addr NamedAddress) error
	Get(name string) (NamedAddress, error)
	UpdateStatus(name string, active bool) error
	ChangeOwner(name, ownerId string) error
	List(ownerId string) ([]NamedAddress, error)
}

type NameAlreadyTaken struct {
	Name string
}

func (er NameAlreadyTaken) Error() string {
	return fmt.Sprintf("Name '%s' is already taken", er.Name)
}

type SQLiteStore struct {
	db *sql.DB
}

func NewSQLiteStore(path string) (*SQLiteStore, error) {
	db, err := sql.Open("sqlite3", path)
	if err != nil {
		return nil, err
	}

	_, err = db.Exec(`
        CREATE TABLE IF NOT EXISTS named_addresses (
            name TEXT PRIMARY KEY,
            address TEXT,
            owner_id TEXT,
            active BOOLEAN
        )
    `)
	if err != nil {
		return nil, err
	}

	return &SQLiteStore{db: db}, nil
}

func generateRandomURL() string {
	const charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	var urlShort string
	for i := 0; i < 6; i++ {
		urlShort += string(charset[rand.Intn(len(charset))])
	}
	return urlShort
}

func (s *SQLiteStore) Create(addr NamedAddress) error {
	_, err := s.db.Exec(`
		INSERT INTO named_addresses (name, address, owner_id, active)
		VALUES (?, ?, ?, ?)
	`, addr.Name, addr.Address, addr.OwnerId, addr.Active)
	if err != nil {
		sqliteErr, ok := err.(sqlite3.Error)
		// sqliteErr.ExtendedCode and sqlite3.ErrConstraintUnique are not the same. probably some lib error.
		// had to use actual code of unique const error
		if ok && sqliteErr.ExtendedCode == 1555 {
			return NameAlreadyTaken{Name: addr.Name}
		}
		return err
	}
	return nil
}

func (s *SQLiteStore) Get(name string) (NamedAddress, error) {
	row := s.db.QueryRow("SELECT name, address, owner_id, active FROM named_addresses WHERE name = ?", name)
	namedAddress := NamedAddress{}
	err := row.Scan(&namedAddress.Name, &namedAddress.Address, &namedAddress.OwnerId, &namedAddress.Active)
	if err != nil {
		if err == sql.ErrNoRows {
			return NamedAddress{}, fmt.Errorf("No record found for name %s", name)
		}
		return NamedAddress{}, err
	}
	return namedAddress, nil
}

func (s *SQLiteStore) UpdateStatus(name string, active bool) error {
	//TODO
	_, err := s.db.Exec("UPDATE named_addresses SET active = ? WHERE name = ?", active, name)
	if err != nil {
		return err
	}
	return nil
}

func (s *SQLiteStore) ChangeOwner(name, ownerId string) error {
	//TODO
	return nil
}

func (s *SQLiteStore) List(ownerId string) ([]NamedAddress, error) {
	rows, err := s.db.Query("SELECT name, address, owner_id, active FROM named_addresses WHERE owner_id = ?", ownerId)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var namedAddresses []NamedAddress
	for rows.Next() {
		var namedAddress NamedAddress
		if err := rows.Scan(&namedAddress.Name, &namedAddress.Address, &namedAddress.OwnerId, &namedAddress.Active); err != nil {
			return nil, err
		}
		namedAddresses = append(namedAddresses, namedAddress)
	}
	return namedAddresses, nil
}

type PageVariables struct {
	NamedAddresses []NamedAddress
}

func renderHTML(w http.ResponseWriter, r *http.Request, tpl *template.Template, data interface{}) {
	w.Header().Set("Content-Type", "text/html")
	err := tpl.Execute(w, data)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func getLoggedInUser(r *http.Request) (string, error) {
	// TODO(dato): should make a request to get loggedin user
	return "tabo", nil
}

type Server struct {
	store Store
}

func (s *Server) Start() {
	http.Handle("/static/", http.FileServer(http.FS(f)))
	http.HandleFunc("/", s.handler)
	http.HandleFunc("/api/update/", s.toggleHandler)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", *port), nil))
}

func (s *Server) handler(w http.ResponseWriter, r *http.Request) {
	loggedInUser, err := getLoggedInUser(r)
	if err != nil {
		http.Error(w, "User Not Logged In", http.StatusUnauthorized)
		return
	}
	if r.Method == http.MethodPost {
		customName := r.PostFormValue("custom")
		address := r.PostFormValue("address")
		if !strings.HasPrefix(address, "http://") && !strings.HasPrefix(address, "https://") {
			http.Error(w, "Address must start with http:// or https://", http.StatusBadRequest)
			return
		}
		for {
			cn := customName
			if cn == "" {
				cn = generateRandomURL()
			}
			namedAddress := NamedAddress{
				Name:    cn,
				Address: address,
				OwnerId: loggedInUser,
				Active:  true,
			}
			if err := s.store.Create(namedAddress); err == nil {
				http.Redirect(w, r, "/", http.StatusSeeOther)
				return
			} else if _, ok := err.(NameAlreadyTaken); ok && customName == "" {
				continue
			} else if _, ok := err.(NameAlreadyTaken); ok && customName != "" {
				http.Error(w, "Name is already taken", http.StatusBadRequest)
				return
			} else {
				http.Error(w, "Try again later", http.StatusInternalServerError)
				return
			}
		}
	}
	// Get Name from request path for redirection
	name := strings.TrimPrefix(r.URL.Path, "/")
	if name != "" {
		namedAddress, err := s.store.Get(name)
		if err != nil {
			return
		}
		if !namedAddress.Active {
			http.Error(w, "address not found", http.StatusNotFound)
			return
		}
		http.Redirect(w, r, namedAddress.Address, http.StatusSeeOther)
		return
	}
	namedAddresses, err := s.store.List(loggedInUser)
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}
	pageVariables := PageVariables{
		NamedAddresses: namedAddresses,
	}
	indexHtmlContent, err := indexHTML.ReadFile("index.html")
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}
	tmpl, err := template.New("index").Parse(string(indexHtmlContent))
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}
	renderHTML(w, r, tmpl, pageVariables)
}

type UpdateRequest struct {
	Name   string `json:"name"`
	Active bool   `json:"active"`
}

func (s *Server) toggleHandler(w http.ResponseWriter, r *http.Request) {
	var data UpdateRequest
	if r.Method == http.MethodPost {
		loggedInUser, err := getLoggedInUser(r)
		if err != nil {
			http.Error(w, "User Not Logged In", http.StatusUnauthorized)
			return
		}
		if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
			http.Error(w, "Failed to decode JSON data", http.StatusBadRequest)
			return
		}
		namedAddress, err := s.store.Get(data.Name)
		if err != nil {
			http.Error(w, fmt.Sprintf("Failed to get named_address for name %s", data.Name), http.StatusInternalServerError)
			return
		}
		if namedAddress.OwnerId != loggedInUser {
			http.Error(w, "Invalid owner ID", http.StatusUnauthorized)
			return
		}
		if err := s.store.UpdateStatus(data.Name, data.Active); err != nil {
			http.Error(w, fmt.Sprintf("Failed to update status for name %s", data.Name), http.StatusInternalServerError)
			return
		}
	} else {
		http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
		return
	}
}

func main() {
	flag.Parse()
	db, err := NewSQLiteStore(*dbPath)
	if err != nil {
		panic(err)
	}
	s := Server{store: db}
	s.Start()
}
