package main

import (
	"database/sql"
	"fmt"
	"log"
	"os"

	_ "github.com/denisenkom/go-mssqldb"
)

func main() {
	// Load DB connection settings from environment (set in docker‑compose)
	server := os.Getenv("DB_SERVER")
	user := os.Getenv("DB_USER")
	password := os.Getenv("DB_PASSWORD")
	dbName := os.Getenv("DB_NAME")

	if server == "" || user == "" || password == "" || dbName == "" {
		log.Fatalf("One or more DB environment variables are missing")
	}

	// Build the connection string for go‑mssqldb
	connStr := fmt.Sprintf("sqlserver://%s:%s@%s?database=%s", user, password, server, dbName)

	// Open a connection pool
	db, err := sql.Open("sqlserver", connStr)
	if err != nil {
		log.Fatalf("sql.Open failed: %v", err)
	}
	defer db.Close()

	// Verify the connection works
	if err = db.Ping(); err != nil {
		log.Fatalf("cannot ping database: %v", err)
	}
	fmt.Println("✅ Connected to MSSQL")

	// -----------------------------------------------------------------
	// 1️⃣ Insert a new customer via the stored procedure sp_InsertCustomer
	// -----------------------------------------------------------------
	var newCustID int
	insertCustSQL := `
INSERT INTO dbo.Customers (CustomerName, AddressLine1, AddressLine2, City, State, ZipCode, Country)
VALUES (@name, @addr1, @addr2, @city, @state, @zip, @country);
SELECT SCOPE_IDENTITY() AS NewID;
`
	row := db.QueryRow(insertCustSQL,
		sql.Named("name", "Acme Corp"),
		sql.Named("addr1", "123 Main St"),
		sql.Named("addr2", nil),
		sql.Named("city", "New York"),
		sql.Named("state", "NY"),
		sql.Named("zip", "10001"),
		sql.Named("country", "USA"),
	)
	if err = row.Scan(&newCustID); err != nil {
		log.Fatalf("Insert customer failed: %v", err)
	}
	fmt.Printf("🆕 Inserted Customer ID: %d\n", newCustID)

	// -----------------------------------------------------------------
	// 2️⃣ Insert a contact for the new customer via sp_InsertContact
	// -----------------------------------------------------------------
	var newContactID int
	insertContactSQL := `
INSERT INTO dbo.Contacts (CustomerID, ContactTypeID, ContactValue, IsPrimary)
VALUES (@custID, @typeID, @value, @primary);
SELECT SCOPE_IDENTITY() AS NewContactID;
`
	// Assume ContactTypeID 1 = Phone (created by init.sql)
	row = db.QueryRow(insertContactSQL,
		sql.Named("custID", newCustID),
		sql.Named("typeID", 1),
		sql.Named("value", "555‑1234"),
		sql.Named("primary", 1),
	)
	if err = row.Scan(&newContactID); err != nil {
		log.Fatalf("Insert contact failed: %v", err)
	}
	fmt.Printf("📞 Inserted Contact ID: %d\n", newContactID)

	// -----------------------------------------------------------------
	// 3️⃣ Retrieve the customer via sp_GetCustomer
	// -----------------------------------------------------------------
	var custName, addr1, addr2, city, state, zip, country string
	getCustSQL := `EXEC dbo.sp_GetCustomer @CustomerID = @id`
	err = db.QueryRow(getCustSQL, sql.Named("id", newCustID)).Scan(
		&newCustID, &custName, &addr1, &addr2, &city, &state, &zip, &country, &sql.NullTime{}, &sql.NullTime{})
	if err != nil {
		log.Fatalf("Get customer failed: %v", err)
	}
	fmt.Printf("🔎 Fetched Customer: %s, %s, %s\n", custName, city, state)

	// -----------------------------------------------------------------
	// 4️⃣ List contacts for the customer via sp_GetContactsByCustomer
	// -----------------------------------------------------------------
	fmt.Println("📄 Contacts for the customer:")
	rows, err := db.Query(`EXEC dbo.sp_GetContactsByCustomer @CustomerID = @id`, sql.Named("id", newCustID))
	if err != nil {
		log.Fatalf("Get contacts failed: %v", err)
	}
	defer rows.Close()
	for rows.Next() {
		var contactID, custID, ctID int
		var value string
		var isPrimary bool
		var typeName string
		if err = rows.Scan(&contactID, &custID, &ctID, &value, &isPrimary, &sql.NullTime{}, &sql.NullTime{}, &typeName); err != nil {
			log.Fatalf("Scanning contacts: %v", err)
		}
		fmt.Printf("- %s (%s) Primary:%v\n", value, typeName, isPrimary)
	}
	if err = rows.Err(); err != nil {
		log.Fatalf("Row iteration error: %v", err)
	}

	// -----------------------------------------------------------------
	// 5️⃣ Update the customer name via sp_UpdateCustomer
	// -----------------------------------------------------------------
	_, err = db.Exec(`EXEC dbo.sp_UpdateCustomer
    @CustomerID = @id,
    @CustomerName = @name,
    @AddressLine1 = @addr1,
    @AddressLine2 = @addr2,
    @City = @city,
    @State = @state,
    @ZipCode = @zip,
    @Country = @country`,
		sql.Named("id", newCustID),
		sql.Named("name", "Acme Corp – Updated"),
		sql.Named("addr1", "123 Main St"),
		sql.Named("addr2", nil),
		sql.Named("city", "New York"),
		sql.Named("state", "NY"),
		sql.Named("zip", "10001"),
		sql.Named("country", "USA"),
	)
	if err != nil {
		log.Fatalf("Update customer failed: %v", err)
	}
	fmt.Println("✏️ Updated customer name")

	// -----------------------------------------------------------------
	// 6️⃣ Delete the contact and the customer (cleanup)
	// -----------------------------------------------------------------
	_, err = db.Exec(`EXEC dbo.sp_DeleteContact @ContactID = @cid`, sql.Named("cid", newContactID))
	if err != nil {
		log.Fatalf("Delete contact failed: %v", err)
	}
	fmt.Println("🗑️ Deleted contact")

	_, err = db.Exec(`EXEC dbo.sp_DeleteCustomer @CustomerID = @cid`, sql.Named("cid", newCustID))
	if err != nil {
		log.Fatalf("Delete customer failed: %v", err)
	}
	fmt.Println("🗑️ Deleted customer")

	fmt.Println("✅ All CRUD operations completed successfully")
}
