package main

import (
	"ListaCompra/Lista"
	"database/sql"
	"encoding/json"
	"fmt"
	_ "github.com/glebarez/go-sqlite"
	_ "github.com/rs/cors"
	"golang.org/x/crypto/acme/autocert"
	"log"
	"net/http"
	"time"
)

type RespuestaProducto struct {
	Producto string `json:"producto"`
	Cantidad int    `json:"cantidad"`
}

func abrirBaseDatos() *sql.DB {

	db, err := sql.Open("sqlite", "./base_de_Datos.db")
	if err != nil {

		fmt.Println(err)

		return nil

	}
	return db

}

func iniciarServidor() {
	mux := http.NewServeMux()

	// 1. Serve static files from the local "./www" folder.
	// If you want "https://redalberto.ddns.net/index.html" to load "./www/index.html",
	// use http.StripPrefix with http.Dir("./www").
	// If you explicitly want "https://redalberto.ddns.net/www/index.html", use http.Dir(".")
	fs := http.FileServer(http.Dir("."))
	mux.Handle("/", fs)

	mux.HandleFunc("/productos", GetDatos)
	mux.HandleFunc("/insertar", InsertarProducto)

	certManager := autocert.Manager{
		Prompt:     autocert.AcceptTOS,
		HostPolicy: autocert.HostWhitelist("redalberto.ddns.net"),
		Cache:      autocert.DirCache("certs"),
	}

	servidor := &http.Server{
		Addr:      ":443",
		Handler:   mux,
		TLSConfig: certManager.TLSConfig(),
	}

	// 2. Start HTTP server on port 80 (required for ACME challenge & redirection)
	go func() {
		fmt.Println("Escuchando HTTP en puerto :80 (redirección y certs)...")
		if err := http.ListenAndServe(":80", certManager.HTTPHandler(nil)); err != nil {
			log.Fatalf("Error en servidor HTTP :80: %v", err)
		}
	}()

	// 3. Start HTTPS server on port 443
	fmt.Println("Escuchando HTTPS en puerto :443...")
	if err := servidor.ListenAndServeTLS("", ""); err != nil {
		log.Fatalf("Error en servidor HTTPS :443: %v", err)
	}
}
func InsertarProducto(w http.ResponseWriter, r *http.Request) {

	if r.Method != http.MethodPost {

		http.Error(w, "Método no permitido", http.StatusMethodNotAllowed)

		return
	}

	var paquete = RespuestaProducto{}
	err := json.NewDecoder(r.Body).Decode(&paquete)
	if err != nil {

		http.Error(w, "Cuerpo JSON no válido.", http.StatusBadRequest)

	}

	defer r.Body.Close()

	w.WriteHeader(http.StatusOK)
	w.Write([]byte(`{"estado":"correcto"}`))

	anyo := time.Now().Year()
	mes := time.Now().Month()
	dia := time.Now().Local().Day()
	hora := time.Now().Local().Hour()
	minuto := time.Now().Local().Minute()
	segundo := time.Now().Local().Second()
	nanosegundo := time.Now().Local().Nanosecond()
	ubicacion := time.Now().Location()

	listaCompra := lista.Producto{

		Fecha: time.Date(anyo, mes, dia, hora, minuto,
			segundo, nanosegundo, ubicacion),
		Nombre:   paquete.Producto,
		Cantidad: paquete.Cantidad,
	}

	lista.InsertarProducto(abrirBaseDatos(), &listaCompra)

}

func GetDatos(w http.ResponseWriter, r *http.Request) {

	if r.Method != http.MethodGet {

		http.Error(w, "Método no permitido", http.StatusMethodNotAllowed)

		return
	}

	productos, err := lista.ObtenerLista(abrirBaseDatos())
	if err != nil {
		fmt.Printf("Error al abrir la base de datos.")
	}
	wrappedData := lista.DataWrapper{

		Productos: productos,
	}

	w.Header().Set("Content-Type", "application/json")

	if err := json.NewEncoder(w).Encode(wrappedData); err != nil {

		http.Error(w, err.Error(), http.StatusInternalServerError)

	}
}

func main() {

	db, err := sql.Open("sqlite", "./base_de_Datos.db")
	if err != nil {

		fmt.Println(err)

		return

	}

	crearTabla := `CREATE TABLE IF NOT EXISTS productos (

    id INTEGER PRIMARY KEY,
    fecha DATE NOT NULL,
    nombre STRING NOT NULL,
    cantidad INTEGER NOT NULL
  ) 
  `

	productos, err := lista.ObtenerLista(db)
	if err != nil {
		fmt.Println("No se pudo obtener la lista de elementos.")

	}

	for _, elemento := range productos {

		fmt.Printf("ID: %d, Fecha: %v, Nombre: %s, Cantidad: %v\n", elemento.Id, elemento.Fecha, elemento.Nombre, elemento.Cantidad)

	}

	defer db.Close()

	fmt.Println("Conectado a la base de datos SQLite correctamente.")

	var verSQLite string

	err = db.QueryRow("select sqlite_version()").Scan(&verSQLite)
	if err != nil {

		fmt.Println(err)
		return

	}

	fmt.Printf("Versión de SQLite: %v\n", verSQLite)

	db.Exec(crearTabla)
	iniciarServidor()
}
