package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	_ "github.com/mattn/go-sqlite3" // Import the SQLite3 driver
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

type Icon struct {
	Body  string `json:"body"`
	Width *int   `json:"width,omitempty"`
}

// Root Define the Root struct to represent the entire JSON structure
type Root struct {
	Prefix string          `json:"prefix"`
	Icons  map[string]Icon `json:"icons"`
	Height int             `json:"height"`
}

func main() {
	testDbPath := os.Getenv("TEST_DB_PATH")
	dbPath := os.Getenv("SQLITE_PATH")
	dbPaths := []string{testDbPath, dbPath}
	flaticonSvgDir := os.Getenv("SVG_DIR")
	//dbPath := "/Users/donov/Desktop/nkode.db"
	//dbPaths := []string{dbPath}
	//outputStr := MakeSvgFiles()
	for _, path := range dbPaths {
		MakeTables(path)
		FlaticonToSqlite(path, flaticonSvgDir)
		//SvgToSqlite(path, outputStr)
	}
}

func FlaticonToSqlite(dbPath string, svgDir string) {
	db, err := sql.Open("sqlite3", dbPath)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// Open the directory
	files, err := os.ReadDir(svgDir)
	if err != nil {
		log.Fatal(err)
	}

	for _, file := range files {
		// Check if it is a regular file (not a directory) and has a .svg extension
		if file.IsDir() || filepath.Ext(file.Name()) != ".svg" {
			continue
		}
		filePath := filepath.Join(svgDir, file.Name())

		// Read the file contents
		content, err := os.ReadFile(filePath)
		if err != nil {
			log.Println("Error reading file:", filePath, err)
			continue
		}

		// Print the file name and first few bytes of the file content
		insertSql := `
INSERT INTO svg_icon (svg)
VALUES (?)
`
		_, err = db.Exec(insertSql, string(content))
		if err != nil {
			log.Fatal(err)
		}
	}

}

func SvgToSqlite(dbPath string, outputStr string) {
	db, err := sql.Open("sqlite3", dbPath)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	lines := strings.Split(outputStr, "\n")
	insertSql := `
INSERT INTO svg_icon (svg)
VALUES (?)
`
	for _, line := range lines {
		if line == "" {
			continue
		}
		_, err := db.Exec(insertSql, line)
		if err != nil {
			log.Fatal(err)
		}
	}

}

func MakeSvgFiles() string {
	jsonFiles, err := GetAllFiles("./core/sqlite-init/json")
	if err != nil {
		log.Fatalf("Error getting JSON files: %v", err)
	}

	if len(jsonFiles) == 0 {
		log.Fatal("No JSON files found in ./json folder")
	}

	var outputStr string
	strSet := make(map[string]struct{})
	for _, filename := range jsonFiles {
		fileData, err := LoadJson(filename)
		if err != nil {
			log.Print("Error loading JSON file: ", err)
			continue
		}
		height := fileData.Height
		for name, icon := range fileData.Icons {

			width := height
			parts := strings.Split(name, "-")
			if len(parts) <= 0 {
				log.Print(name, " has no parts")
				continue
			}
			part0 := parts[0]
			_, exists := strSet[part0]
			if exists {
				continue
			}
			if icon.Width != nil {
				width = *icon.Width
			}
			strSet[part0] = struct{}{}
			if icon.Body == "" {
				continue
			}
			outputStr = fmt.Sprintf("%s<svg  viewBox=\"0 0 %d %d\" xmlns=\"http://www.w3.org/2000/svg\">%s</svg>\n", outputStr, width, height, icon.Body)
		}
	}
	return outputStr
}

func GetAllFiles(dir string) ([]string, error) {
	// Use ioutil.ReadDir to list all files in the directory
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, fmt.Errorf("unable to read directory: %v", err)
	}

	// Create a slice to hold the JSON filenames
	var jsonFiles []string

	// Loop through the files and filter out JSON files
	for _, file := range files {
		if !file.IsDir() && filepath.Ext(file.Name()) == ".json" {
			jsonFiles = append(jsonFiles, filepath.Join(dir, file.Name()))
		}
	}

	return jsonFiles, nil
}

func LoadJson(filename string) (*Root, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, fmt.Errorf("failed to read file %s: %v", filename, err)
	}

	var root Root
	err = json.Unmarshal(data, &root)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal JSON: %v", err)
	}

	return &root, nil
}

func MakeTables(dbPath string) {
	db, err := sql.Open("sqlite3", dbPath)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	createTable := `
PRAGMA journal_mode=WAL;
--PRAGMA busy_timeout = 5000;         -- Wait up to 5 seconds
--PRAGMA synchronous = NORMAL;        -- Reduce sync frequency for less locking
--PRAGMA cache_size = -16000;         -- Increase cache size (16MB)PRAGMA 

CREATE TABLE IF NOT EXISTS customer (
    id TEXT NOT NULL PRIMARY KEY
    ,max_nkode_len INTEGER NOT NULL
    ,min_nkode_len INTEGER NOT NULL
    ,distinct_sets INTEGER NOT NULL
    ,distinct_attributes INTEGER NOT NULL
    ,lock_out INTEGER NOT NULL
    ,expiration INTEGER NOT NULL
    ,attribute_values BLOB NOT NULL
    ,set_values BLOB NOT NULL
	,last_renew TEXT NOT NULL 
    ,created_at TEXT NOT NULL 
);

CREATE TABLE IF NOT EXISTS user (
	id TEXT NOT NULL PRIMARY KEY
	,email TEXT NOT NULL
--	first_name TEXT NOT NULL
--	last_name TEXT NOT NULL
	,renew INT NOT NULL
	,refresh_token TEXT
	,customer_id TEXT NOT NULL
	
-- Enciphered Passcode	
	,code TEXT NOT NULL
	,mask TEXT NOT NULL

-- Keypad Dimensions
	,attributes_per_key INT NOT NULL
	,number_of_keys INT NOT NULL

-- User Keys
	,alpha_key BLOB NOT NULL
	,set_key BLOB NOT NULL
	,pass_key BLOB NOT NULL
	,mask_key BLOB NOT NULL
	,salt BLOB NOT NULL
	,max_nkode_len INT NOT NULL

-- User Interface 
	,idx_interface BLOB NOT NULL
	,svg_id_interface BLOB NOT NULL
	
	,last_login TEXT NULL
    ,created_at TEXT
	
	,FOREIGN KEY (customer_id) REFERENCES customer(id)
	,UNIQUE(customer_id, email)
);

CREATE TABLE IF NOT EXISTS svg_icon (
	id INTEGER PRIMARY KEY AUTOINCREMENT
	,svg TEXT NOT NULL
);

`
	_, err = db.Exec(createTable)
	if err != nil {
		log.Fatal(err)
	}
}
