package database

import (
	"database/sql"
	"log"
	"medi-wol/internal/models"
	"time"

	_ "modernc.org/sqlite"
)

// DB ist die Datenbankverbindung
type DB struct {
	*sql.DB
}

// InitDB initialisiert die Datenbank und erstellt die Tabellen
func InitDB() (*DB, error) {
	db, err := sql.Open("sqlite", "./medi-wol.db")
	if err != nil {
		return nil, err
	}

	// Tabelle erstellen
	createTableSQL := `
	CREATE TABLE IF NOT EXISTS pcs (
		id INTEGER PRIMARY KEY AUTOINCREMENT,
		name TEXT NOT NULL,
		mac TEXT NOT NULL UNIQUE,
		ip TEXT NOT NULL,
		created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
		updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
	);`

	_, err = db.Exec(createTableSQL)
	if err != nil {
		return nil, err
	}

	// Füge IP-Spalte hinzu, falls sie nicht existiert
	_, err = db.Exec("ALTER TABLE pcs ADD COLUMN ip TEXT DEFAULT ''")
	if err != nil {
		// Spalte existiert bereits, ignorieren
	}

	log.Println("Datenbank erfolgreich initialisiert")
	return &DB{db}, nil
}

// GetAllPCs holt alle PCs aus der Datenbank
func (db *DB) GetAllPCs() ([]models.PC, error) {
	rows, err := db.Query("SELECT id, name, mac, ip, created_at, updated_at FROM pcs ORDER BY name")
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var pcs []models.PC
	for rows.Next() {
		var pc models.PC
		err := rows.Scan(&pc.ID, &pc.Name, &pc.MAC, &pc.IP, &pc.CreatedAt, &pc.UpdatedAt)
		if err != nil {
			return nil, err
		}
		pcs = append(pcs, pc)
	}

	return pcs, nil
}

// CreatePC erstellt einen neuen PC-Eintrag
func (db *DB) CreatePC(name, mac, ip string) (*models.PC, error) {
	now := time.Now()
	result, err := db.Exec(
		"INSERT INTO pcs (name, mac, ip, created_at, updated_at) VALUES (?, ?, ?, ?, ?)",
		name, mac, ip, now, now,
	)
	if err != nil {
		return nil, err
	}

	id, err := result.LastInsertId()
	if err != nil {
		return nil, err
	}

	return &models.PC{
		ID:        int(id),
		Name:      name,
		MAC:       mac,
		IP:        ip,
		CreatedAt: now,
		UpdatedAt: now,
	}, nil
}

// UpdatePC aktualisiert einen bestehenden PC-Eintrag
func (db *DB) UpdatePC(id int, name, mac, ip string) (*models.PC, error) {
	now := time.Now()
	_, err := db.Exec(
		"UPDATE pcs SET name = ?, mac = ?, ip = ?, updated_at = ? WHERE id = ?",
		name, mac, ip, now, id,
	)
	if err != nil {
		return nil, err
	}

	return &models.PC{
		ID:        id,
		Name:      name,
		MAC:       mac,
		IP:        ip,
		UpdatedAt: now,
	}, nil
}

// DeletePC löscht einen PC-Eintrag
func (db *DB) DeletePC(id int) error {
	_, err := db.Exec("DELETE FROM pcs WHERE id = ?", id)
	return err
}

// GetPCByID holt einen PC anhand der ID
func (db *DB) GetPCByID(id int) (*models.PC, error) {
	var pc models.PC
	err := db.QueryRow(
		"SELECT id, name, mac, ip, created_at, updated_at FROM pcs WHERE id = ?",
		id,
	).Scan(&pc.ID, &pc.Name, &pc.MAC, &pc.IP, &pc.CreatedAt, &pc.UpdatedAt)

	if err != nil {
		return nil, err
	}

	return &pc, nil
}
