package commands

import (
	"fmt"
	"os/exec"
	"os"
	"time"
	"path/filepath"
	"datasmith/utils"
	"datasmith/templates"
)

func InitProject(name string, dbType string) {
	utils.PromptIfEmpty(&name, "Enter the name of the project: ")
	slug := utils.Slugify(name)

	// Check if datasmith.yaml already exists in the directory
	configFilePath := filepath.Join(slug, "datasmith.yaml")
	if _, err := os.Stat(configFilePath); err == nil {
		fmt.Printf("Error: A datasmith.yaml file already exists in the directory '%s'. Initialization aborted.\n", slug)
		return
	} else if !os.IsNotExist(err) {
		fmt.Printf("Error checking datasmith.yaml file: %v\n", err)
		return
	}


	if dbType == "" {
		dbType = promptForDbType()
	}

	fmt.Printf("Initializing new project structure in '%s' with database type '%s'\n", slug, dbType)

	// Create project directories
	createProjectDirs(slug)

	// Create README.md file from template
	createReadmeFile(slug, name, dbType)

	// Create CHANGELOG.md file from template
	createChangelogFile(slug)

	// Create datasmith.yaml file from template
	createConfigFile(slug, name, dbType)

	// Create an empty database.dbml file
	createDBMLFile(slug)

	// Create LICENSE.md file from template
	createLicenseFile(slug, name)

	// Create CONTRIBUTING.md file from template
	createContributingFile(slug)

	// Create .gitignore file from template
	createGitignoreFile(slug)

	// Create .dockerignore file from template
	createDockerignoreFile(slug)

	// Create Containerfile from template based on dbType
	createContainerfile(slug, dbType)

	// Create .gitlab-ci.yml file from template based on dbType
	createGitlabCiFile(slug, dbType)

	// Create generate_db_tests.sh script from template
	createGenerateDbTestsScript(slug)

	// Create sqlfluff file from template
	createSqlfluffFile(slug)
	
	// Create import-sql.sh script from template based on dbType
	createImportSqlScript(slug, dbType)

	// Create k8s/persistentvolumeclaim.template.yaml file from template
	createK8sPersistentVolumeFile(slug)

	// Create k8s/persistentvolumeclaim.template.yaml file from template
	createK8sPersistentVolumeClaimFile(slug)

	// Create k8s/service.template.yaml file from template
	createK8sServiceFile(slug)

	// Create k8s/deployment.template.yaml file from template based on dbType
	createK8sDeploymentFile(slug, dbType)

	fmt.Printf("Initialized new project structure in '%s'\n", slug)

	fmt.Println("Initializing Git repository...")
	cmd := exec.Command("git", "init", slug)
	cmd.Run()
	
}

// promptForDbType prompts the user to select a database type
func promptForDbType() string {
	options := []utils.MenuOption{
		{Display: "MySQL (default)", Value: "mysql"},
		{Display: "PostgreSQL", Value: "postgres"},
	}

	dbType, err := utils.SelectMenu(options, "Select database type:")
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(1)
	}
	return dbType
}

// createProjectDirs creates the necessary project directories
func createProjectDirs(projectName string) {
	dirs := []string{"k8s", "sql"}

	for _, dir := range dirs {
		path := filepath.Join(projectName, dir)
		if err := os.MkdirAll(path, os.ModePerm); err != nil {
			fmt.Printf("Error creating directory '%s': %v\n", path, err)
		} else {
			fmt.Printf("Created directory: %s\n", path)
		}
	}
}

// createReadmeFile creates the README.md file from template
func createReadmeFile(projectDir, projectName, dbType string) {
	data := map[string]interface{}{
		"Name":   projectName,
		"DbType": dbType,
	}

	err := templates.CreateFileFromTemplate(projectDir, "", "README.md", "README.md", data)
	if err != nil {
		fmt.Printf("Error creating README.md file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/README.md\n", projectDir)
	}
}

// createChangelogFile creates the CHANGELOG.md file from template
func createChangelogFile(projectDir string) {
	data := map[string]interface{}{
		"Date": time.Now().Format("2006-01-02"),
	}

	err := templates.CreateFileFromTemplate(projectDir, "", "CHANGELOG.md", "CHANGELOG.md", data)
	if err != nil {
		fmt.Printf("Error creating CHANGELOG.md file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/CHANGELOG.md\n", projectDir)
	}
}

// createConfigFile creates the datasmith.yaml file from template
func createConfigFile(projectDir, projectName, dbType string) {
	data := map[string]interface{}{
		"Name":      projectName,
		"CreatedAt": time.Now().Format(time.RFC3339),
		"DbType":    dbType,
	}

	err := templates.CreateFileFromTemplate(projectDir, "", "datasmith.yaml", "datasmith.yaml", data)
	if err != nil {
		fmt.Printf("Error creating datasmith.yaml file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/datasmith.yaml\n", projectDir)
	}
}

// createDBMLFile creates an empty database.dbml file in the project directory
func createDBMLFile(projectDir string) {
	dbmlFilePath := filepath.Join(projectDir, "database.dbml")
	file, err := os.Create(dbmlFilePath)
	if err != nil {
		fmt.Printf("Error creating database.dbml file: %v\n", err)
		return
	}
	defer file.Close()

	fmt.Printf("Created file: %s/database.dbml\n", projectDir)
}

// createLicenseFile creates the LICENSE.md file from template
func createLicenseFile(projectDir, projectName string) {
	data := map[string]interface{}{
		"Name": projectName,
		"Year": time.Now().Year(),
	}

	err := templates.CreateFileFromTemplate(projectDir, "", "LICENSE.md", "LICENSE.md", data)
	if err != nil {
		fmt.Printf("Error creating LICENSE.md file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/LICENSE.md\n", projectDir)
	}
}

// createContributingFile creates the CONTRIBUTING.md file from template
func createContributingFile(projectDir string) {
	err := templates.CreateFileFromTemplate(projectDir, "", "CONTRIBUTING.md", "CONTRIBUTING.md", nil)
	if err != nil {
		fmt.Printf("Error creating CONTRIBUTING.md file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/CONTRIBUTING.md\n", projectDir)
	}
}

// createGitignoreFile creates the .gitignore file from template
func createGitignoreFile(projectDir string) {
	err := templates.CreateFileFromTemplate(projectDir, "", ".gitignore", "gitignore", nil)
	if err != nil {
		fmt.Printf("Error creating .gitignore file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/.gitignore\n", projectDir)
	}
}

// createDockerignoreFile creates the .dockerignore file from template
func createDockerignoreFile(projectDir string) {
	err := templates.CreateFileFromTemplate(projectDir, "", ".dockerignore", "dockerignore", nil)
	if err != nil {
		fmt.Printf("Error creating .dockerignore file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/.dockerignore\n", projectDir)
	}
}

// createContainerfile creates the Containerfile from the appropriate template
func createContainerfile(projectDir, dbType string) {
	templateFile := "Containerfile.mysql"
	if dbType == "postgres" {
		templateFile = "Containerfile.postgres"
	}

	err := templates.CreateFileFromTemplate(projectDir, "", "Containerfile", templateFile, nil)
	if err != nil {
		fmt.Printf("Error creating Containerfile: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/Containerfile\n", projectDir)
	}
}

// createGitlabCiFile creates the .gitlab-ci.yml file from the appropriate template
func createGitlabCiFile(projectDir, dbType string) {
	templateFile := "gitlab-ci.mysql.yaml"
	if dbType == "postgres" {
		templateFile = "gitlab-ci.postgres.yaml"
	}

	err := templates.CreateFileFromTemplate(projectDir, "", ".gitlab-ci.yml", templateFile, nil)
	if err != nil {
		fmt.Printf("Error creating .gitlab-ci.yml file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/.gitlab-ci.yml\n", projectDir)
	}
}

// createGenerateDbTestsScript creates the generate_db_tests.sh script from template
func createGenerateDbTestsScript(projectDir string) {
	err := templates.CreateFileFromTemplate(projectDir, "", "generate_db_tests.sh", "generate_db_tests.sh", nil)
	if err != nil {
		fmt.Printf("Error creating generate_db_tests.sh script: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/generate_db_tests.sh\n", projectDir)
	}
}

// createSqlfluffFile creates the sqlfluff configuration file from template
func createSqlfluffFile(projectDir string) {
	err := templates.CreateFileFromTemplate(projectDir, "", "sqlfluff", "sqlfluff", nil)
	if err != nil {
		fmt.Printf("Error creating sqlfluff file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/sqlfluff\n", projectDir)
	}
}

// createImportSqlScript creates the import-sql.sh script from the appropriate template
func createImportSqlScript(projectDir, dbType string) {
	templateFile := "import-sql.mysql"
	if dbType == "postgres" {
		templateFile = "import-sql.postgres"
	}

	err := templates.CreateFileFromTemplate(projectDir, "", "import-sql.sh", templateFile, nil)
	if err != nil {
		fmt.Printf("Error creating import-sql.sh script: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/import-sql.sh\n", projectDir)
	}
}

// createK8sPersistentVolumeClaimFile creates the k8s/persistentVolume.template.yaml file from template
func createK8sPersistentVolumeFile(projectDir string) {

	err := templates.CreateFileFromTemplate(projectDir, "k8s", "persistentVolume.template.yaml", "k8s/persistentVolume.template.yaml", nil)
	if err != nil {
		fmt.Printf("Error creating k8s/persistentVolume.template.yaml file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/k8s/persistentVolume.template.yaml\n", projectDir)
	}
}

// createK8sPersistentVolumeClaimFile creates the k8s/persistentVolumeClaim.template.yaml file from template
func createK8sPersistentVolumeClaimFile(projectDir string) {

	err := templates.CreateFileFromTemplate(projectDir, "k8s", "persistentVolumeClaim.template.yaml", "k8s/persistentVolumeClaim.template.yaml", nil)
	if err != nil {
		fmt.Printf("Error creating k8s/persistentVolumeClaim.template.yaml file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/k8s/persistentVolumeClaim.template.yaml\n", projectDir)
	}
}

// createK8sPerviceFile creates the k8s/service.template.yaml file from template
func createK8sServiceFile(projectDir string) {

	err := templates.CreateFileFromTemplate(projectDir, "k8s", "service.template.yaml", "k8s/service.template.yaml", nil)
	if err != nil {
		fmt.Printf("Error creating k8s/service.template.yaml file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/k8s/service.template.yaml\n", projectDir)
	}
}

// createK8sDeploymentFile creates the k8s/deployment.template.yaml file from the appropriate template
func createK8sDeploymentFile(projectDir, dbType string) {
	templateFile := "k8s/deployment.mysql.template.yaml"
	if dbType == "postgres" {
	templateFile = "k8s/deployment.postgres.template.yaml"
	}
	
	err := templates.CreateFileFromTemplate(projectDir, "k8s", "deployment.template.yaml", templateFile, nil)
	if err != nil {
		fmt.Printf("Error creating k8s/deployment.template.yaml file: %v\n", err)
	} else {
		fmt.Printf("Created file: %s/k8s/deployment.template.yaml\n", projectDir)
	}
}

// Help returns the help information for the init command
func InitHelp() string {
	return "init [name] [--type mysql|postgres] : Create a new project with the specified name and database type."
}