package main

import (
	"database/sql"
	"log"
	"os"
	"path/filepath"
	"strings"

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

type Simulation struct {
	ID        int      `json:"id"`
	Name      string   `json:"name"`
	Resources []string `json:"resources"`
	CreatedAt  string   `json:"created_at"`
	Config     *string  `json:"config"`
	SearchTime *float64 `json:"search_time"`
	TotalTime  *float64 `json:"total_time"`
	TotalSizeBytes int64 `json:"total_size_bytes"`
}

var db *sql.DB

func initDBConnection() {
	var err error
	db, err = sql.Open("sqlite3", "./sim-link.db")
	if err != nil {
		log.Fatal(err)
	}

	createTableSQL := `CREATE TABLE IF NOT EXISTS simulations (
		"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
		"name" TEXT UNIQUE,
		"config" TEXT,
		"created_at" DATETIME DEFAULT CURRENT_TIMESTAMP
	);`
	_, err = db.Exec(createTableSQL)
	if err != nil {
		log.Fatal(err)
	}

	db.Exec("ALTER TABLE simulations ADD COLUMN config TEXT") // Ignore error if exists
	db.Exec("ALTER TABLE simulations ADD COLUMN search_time REAL") // Ignore error if exists
	db.Exec("ALTER TABLE simulations ADD COLUMN total_time REAL") // Ignore error if exists

	createResourcesTableSQL := `CREATE TABLE IF NOT EXISTS resources (
		"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
		"simulation_id" INTEGER,
		"filename" TEXT,
		FOREIGN KEY(simulation_id) REFERENCES simulations(id)
	);`
	_, err = db.Exec(createResourcesTableSQL)
	if err != nil {
		log.Fatal(err)
	}
}

func syncResults() {
	resultsDir := "../results"
	if _, err := os.Stat(resultsDir); os.IsNotExist(err) {
		log.Println("Results directory does not exist, skipping sync")
		return
	}

	entries, err := os.ReadDir(resultsDir)
	if err != nil {
		log.Println("Error reading results directory:", err)
		return
	}

	for _, entry := range entries {
		if entry.IsDir() {
			simName := entry.Name()
			simID := insertSimulation(simName)

			// Read subfiles
			subFiles, err := os.ReadDir(filepath.Join(resultsDir, simName))
			if err == nil {
				// Clear old resources for this simulation
				db.Exec("DELETE FROM resources WHERE simulation_id = ?", simID)

				// Check for already inserted to avoid dupes if both exist
				seen := make(map[string]bool)

				for _, sf := range subFiles {
					if !sf.IsDir() {
						finalName := sf.Name()
						if strings.ToLower(filepath.Ext(finalName)) == ".avi" {
							finalName = transcodeIfNeeded(filepath.Join(resultsDir, simName), finalName)
						}
						
						if !seen[finalName] {
							insertResource(simID, finalName)
							seen[finalName] = true
						}
					}
				}
			}
		}
	}
	log.Println("Database synchronized with results directory")
}

func insertSimulation(name string) int64 {
	var id int64
	err := db.QueryRow("SELECT id FROM simulations WHERE name = ?", name).Scan(&id)
	if err == sql.ErrNoRows {
		res, err := db.Exec("INSERT INTO simulations(name) VALUES(?)", name)
		if err != nil {
			log.Println("Error inserting simulation:", err)
			return 0
		}
		id, err = res.LastInsertId()
		if err != nil {
			return 0
		}
	} else if err != nil {
		log.Println("Error selecting simulation:", err)
		return 0
	}
	return id
}

func insertResource(simID int64, filename string) {
	_, err := db.Exec("INSERT INTO resources(simulation_id, filename) VALUES(?, ?)", simID, filename)
	if err != nil {
		log.Println("Error inserting resource:", err)
	}
}
