package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"github.com/abhinavxd/libredesk/internal/colorlog"
	"github.com/abhinavxd/libredesk/internal/dbutil"
	"github.com/abhinavxd/libredesk/internal/user"
	"github.com/jmoiron/sqlx"
	"github.com/knadh/stuffbin"
)

// Install checks if the schema is already installed, prompts for confirmation, and installs the schema if needed.
// idempotent install skips the installation if the database schema is already installed.
func install(ctx context.Context, db *sqlx.DB, fs stuffbin.FileSystem, idempotentInstall, prompt bool) error {
	schemaInstalled, err := checkSchema(db)
	if err != nil {
		log.Fatalf("error checking existing db schema: %v", err)
	}

	// Make sure the system user password is strong enough.
	password := os.Getenv("LIBREDESK_SYSTEM_USER_PASSWORD")
	if password != "" && !user.IsStrongPassword(password) && !schemaInstalled {
		log.Fatalf("system user password is not strong, %s", user.PasswordHint)
	}

	if !idempotentInstall {
		log.Println("running first time setup...")
		colorlog.Red(fmt.Sprintf("WARNING: This will wipe your entire database - '%s'", ko.String("db.database")))
	}

	if prompt {
		log.Print("Continue (y/n)? ")
		var ok string
		fmt.Scanf("%s", &ok)
		if !strings.EqualFold(ok, "y") {
			log.Fatalf("installation cancelled")
		}
	}

	if idempotentInstall {
		if schemaInstalled {
			log.Println("skipping installation as schema is already installed")
			os.Exit(0)
		}
	} else {
		log.Println("installing database schema...")
		time.Sleep(5 * time.Second)
	}

	// Install schema.
	if err := installSchema(db, fs); err != nil {
		log.Fatalf("error installing schema: %v", err)
	}

	log.Println("database schema installed successfully")

	// Create system user.
	if err := user.CreateSystemUser(ctx, password, db); err != nil {
		log.Fatalf("error creating system user: %v", err)
	}
	return nil
}

// setSystemUserPass prompts for pass and sets system user password.
func setSystemUserPass(ctx context.Context, db *sqlx.DB) {
	user.ChangeSystemUserPassword(ctx, db)
}

// checkSchema verifies if the DB schema is already installed by querying a table.
func checkSchema(db *sqlx.DB) (bool, error) {
	if _, err := db.Exec(`SELECT * FROM settings LIMIT 1`); err != nil {
		if dbutil.IsTableNotExistError(err) {
			return false, nil
		}
		return false, err
	}
	return true, nil
}

// installSchema reads the schema file and installs it in the database.
func installSchema(db *sqlx.DB, fs stuffbin.FileSystem) error {
	q, err := fs.Read("/schema.sql")
	if err != nil {
		return err
	}
	_, err = db.Exec(string(q))
	return err
}
