package main

import (
	"Portifolio/internal/database"
	"Portifolio/internal/handlers"
	"Portifolio/internal/shell"
	"bufio"
	"database/sql"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"strings"

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

var db *sql.DB

func corsMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("Incoming request: %s %s from %s", r.Method, r.URL.Path, r.Header.Get("Origin"))

		w.Header().Set("Access-Control-Allow-Origin", "http://localhost:8081")
		w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")

		if r.Method == http.MethodOptions {
			w.WriteHeader(http.StatusNoContent)
			return
		}

		next.ServeHTTP(w, r)
	})
}

func main() {
	// --- CLI flags ---
	port := flag.String("port", "8080", "Port to listen on")
	host := flag.String("host", "", "Host/IP to listen on (default: all interfaces)")
	flag.Parse()

	addr := fmt.Sprintf("%s:%s", *host, *port)

	// --- Database ---
	var err error
	db, err = sql.Open("sqlite3", "./app.db?_foreign_keys=on")
	if err != nil {
		log.Fatal("Failed to open database:", err)
	}
	defer db.Close()

	if err = db.Ping(); err != nil {
		log.Fatal("Failed to connect to database:", err)
	}

	database.InitDB(db)
	fmt.Println("Connected to SQLite database")

	// --- Routes ---
	mux := http.NewServeMux()

	mux.HandleFunc("/health", handlers.HealthHandler(db))

	mux.HandleFunc("POST /trade/add", handlers.AddTradeHandler(db))
	mux.HandleFunc("GET /trade/list", handlers.GetTradeListHandler(db))
	mux.HandleFunc("GET /trade/search", handlers.GetTradeListHandler(db)) // new
	//Positions
	mux.HandleFunc("GET /positions/list", handlers.GetPositionListHandler(db))
	mux.HandleFunc("GET /positions/closed/list", handlers.GetPositionListHandler(db)) // new
	mux.HandleFunc("GET /positions/closed/search", handlers.GetTradeListHandler(db))  // new
	// Company
	mux.HandleFunc("POST /company/add", handlers.AddCompanyHandler(db))
	mux.HandleFunc("GET /company/list", handlers.GetCompaniesHandler(db))
	mux.HandleFunc("GET /company/revenue/categories", handlers.GetCompanyRevenueCategories(db))
	mux.HandleFunc("POST /company/S-O/add", handlers.GetCompaniesHandler(db)) // new
	mux.HandleFunc("GET /company/S-O/list", handlers.GetCompaniesHandler(db)) // new

	mux.HandleFunc("GET /currency/list", handlers.GetCurrenciesHandler(db))
	mux.HandleFunc("POST /currency/add", handlers.AddCurrencyHandler(db))

	mux.HandleFunc("POST /add/revenue/entry", handlers.AddRevenueEntryHandler(db))
	mux.HandleFunc("POST /api/v1/revenue/add", handlers.AddRevenueEntryHandler(db))

	// --- Start server ---
	fmt.Printf("Server running on %s\n", addr)
	go func() {
		log.Fatal(http.ListenAndServe(addr, corsMiddleware(mux)))
	}()

	runShell(db)
}

func runShell(db *sql.DB) {
	scanner := bufio.NewScanner(os.Stdin)
	fmt.Println("\nShell ready. Type 'help' for commands.")

	for {
		fmt.Print("> ")
		if !scanner.Scan() {
			break
		}

		parts := strings.Fields(scanner.Text())
		if len(parts) == 0 {
			continue
		}

		switch parts[0] {
		// Company
		case "add-company":
			shell.AddCompany(scanner, db)
		case "list-companies":
			shell.ListCompanies(db)

		// Currency
		case "add-currency":
			shell.AddCurrency(scanner, db)
		case "list-currency":
			shell.ListCurrencies(db)

		// Revenue
		case "add-revenue":
			shell.AddRevenue(scanner, db)
		case "list-revenue":
			shell.ListRevenue(scanner, db)

		case "help":
			fmt.Println("\nCommands:")
			fmt.Println("  --- Company ---")
			fmt.Println("  add-company       add a new company")
			fmt.Println("  list-companies    list all companies")
			fmt.Println("  --- Currency ---")
			fmt.Println("  add-currency      add a new currency")
			fmt.Println("  list-currency     list all currencies")
			fmt.Println("  --- Revenue ---")
			fmt.Println("  add-revenue       add a revenue entry interactively")
			fmt.Println("  list-revenue      list revenue for a company/period")
			fmt.Println("  sum-revenue       sum revenue across periods")
			fmt.Println("  --- Other ---")
			fmt.Println("  exit              quit")

		case "exit":
			fmt.Println("Bye!")
			os.Exit(0)

		default:
			fmt.Printf("Unknown command: %s. Type 'help' for commands.\n", parts[0])
		}
	}
}
