package esr

import (
	"os"
	"path/filepath"
)

var indexHtml = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="color-scheme" content="light dark">
  <title>Application</title>
  {{ css }}
</head>
<body>
  <div id="app"></div>
  {{ livereload }}
  {{ js }}
</body>
</html>`

var defaultConfig = `bundle: true
platform: browser
format: esm
sourcemap: true
outdir: public

watch:
  paths: ['src/**/*.{ts,tsx,js,jsx,css,scss,html}', 'public/index.html']

serve:
  html: public/index.html
  port: 1234

build:
  minify: true
  minifyWhitespace: true
  minifyIdentifiers: true
  sourcemap: false

run:
  runtime: bun
  sourcemap: false

jsx: automatic
jsxFactory: React.createElement
`

func CreateDefaultPackageJson() string {
	cwd, err := os.Getwd()
	if err != nil {
		Die("failed to get current working directory: %v", err)
	}

	return `{
  "name": "` + filepath.Base(cwd) + `",
  "version": "0.0.1",
  "scripts": {
    "serve": "esr --serve src/index.ts",
    "build": "esr --build src/index.ts",
    "build:watch": "esr --build --watch src/index.ts",
    "run": "esr --run src/index.ts",
    "run:watch": "esr --run --watch src/index.ts"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}`
}

// InitProject initializes a new project in the current working directory.
// It ensures the directory is empty before proceeding. The function creates
// essential directories and files required for the project, including:
// - A 'public' directory with an 'index.html' file.
// - A 'src' directory with an 'index.ts' file.
// - Configuration files such as '.esr.yml', 'package.json', 'tsconfig.json', 
//   and '.prettierrc' with default settings.
// If any step fails, the function calls Die with an appropriate error message.
func InitProject() {
	cwd, err := os.Getwd()
	if err != nil {
		Die("failed to get current working directory: %v", err)
	}

	cwdFiles, err := os.ReadDir(cwd)
	if err != nil {
		Die("failed to read current working directory: %v", err)
	}

	if len(cwdFiles) > 0 {
		Die("current working directory is not empty")
	}

	publicDir := filepath.Join(cwd, "public")
	if err := os.MkdirAll(publicDir, 0755); err != nil {
		Die("failed to create public directory: %v", err)
	}

	indexHtmlPath := filepath.Join(publicDir, "index.html")
	if err := os.WriteFile(indexHtmlPath, []byte(indexHtml), 0644); err != nil {
		Die("failed to write index.html: %v", err)
	}

	srcDir := filepath.Join(cwd, "src")
	if err := os.MkdirAll(srcDir, 0755); err != nil {
		Die("failed to create src directory: %v", err)
	}

	indexTsPath := filepath.Join(srcDir, "index.ts")
	if err := os.WriteFile(indexTsPath, []byte("console.log('Hello, world!')\n"), 0644); err != nil {
		Die("failed to write index.ts: %v", err)
	}

	esrYmlPath := filepath.Join(cwd, ".esr.yml")
	if err := os.WriteFile(esrYmlPath, []byte(defaultConfig), 0644); err != nil {
		Die("failed to write .esr.yml: %v", err)
	}

	packageJsonPath := filepath.Join(cwd, "package.json")
	if err := os.WriteFile(packageJsonPath, []byte(CreateDefaultPackageJson()), 0644); err != nil {
		Die("failed to write package.json: %v", err)
	}

	tsconfigJsonPath := filepath.Join(cwd, "tsconfig.json")
	if err := os.WriteFile(tsconfigJsonPath, []byte(`{
  "compilerOptions": {
    "module": "ES2022",
    "target": "ESNext",
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "node"
  }
}`), 0644); err != nil {
		Die("failed to write tsconfig.json: %v", err)
	}

	prettierRcPath := filepath.Join(cwd, ".prettierrc")
	if err := os.WriteFile(prettierRcPath, []byte(`{
  "printWidth": 80,
  "semi": true,
  "singleQuote": false,
  "tabWidth": 2
}`), 0644); err != nil {
		Die("failed to write .prettierrc: %v", err)
	}
}
