package shell

import (
	"Portifolio/internal/database"
	"Portifolio/internal/model"
	"bufio"
	"database/sql"
	"fmt"
	"strconv"
	"strings"
)

func promptInt(scanner *bufio.Scanner, label string) (int, error) {
	fmt.Print(label)
	scanner.Scan()
	v, err := strconv.Atoi(strings.TrimSpace(scanner.Text()))
	if err != nil {
		return 0, fmt.Errorf("invalid %s", label)
	}
	return v, nil
}

func promptFloat(scanner *bufio.Scanner, label string) (float64, error) {
	fmt.Print(label)
	scanner.Scan()
	v, err := strconv.ParseFloat(strings.TrimSpace(scanner.Text()), 64)
	if err != nil {
		return 0, fmt.Errorf("invalid %s", label)
	}
	return v, nil
}

func promptString(scanner *bufio.Scanner, label string) string {
	fmt.Print(label)
	scanner.Scan()
	return strings.TrimSpace(scanner.Text())
}

func promptPeriod(scanner *bufio.Scanner) (model.Period, error) {
	periodType := strings.ToUpper(promptString(scanner, "  Period type (Q/H/Y): "))
	year, err := promptInt(scanner, "  Year: ")
	if err != nil {
		return model.Period{}, err
	}

	switch periodType {
	case "Y":
		return model.FullYearPeriod(year), nil
	case "Q", "H":
		label := map[string]string{"Q": "  Index (1-4): ", "H": "  Index (1-2): "}[periodType]
		idx, err := promptInt(scanner, label)
		if err != nil {
			return model.Period{}, err
		}
		if periodType == "Q" {
			return model.QuarterPeriod(year, idx), nil
		}
		return model.HalfYearPeriod(year, idx), nil
	default:
		return model.Period{}, fmt.Errorf("invalid period type: %s", periodType)
	}
}

func AddRevenue(scanner *bufio.Scanner, db *sql.DB) {
	companyID, err := promptInt(scanner, "  Company ID: ")
	if err != nil {
		fmt.Println("  ✗", err)
		return
	}
	// checking if company exits
	_, err = database.GetCompanyByID(db, companyID)
	if err != nil {
		fmt.Println("No company by that id:", err)
		return
	}
	currencyID, err := promptInt(scanner, "  Currency ID: ")
	if err != nil {
		fmt.Println("  ✗", err)
		return
	}
	period, err := promptPeriod(scanner)
	if err != nil {
		fmt.Println("  ✗", err)
		return
	}
	category := promptString(scanner, "  Category name: ")

	var parentID *int
	parentStr := promptString(scanner, "  Parent category ID (leave blank for root): ")
	if parentStr != "" {
		pid, err := strconv.Atoi(parentStr)
		if err != nil {
			fmt.Println("  ✗ Invalid parent ID")
			return
		}
		parentID = &pid
	}

	value, err := promptFloat(scanner, "  Value: ")
	if err != nil {
		fmt.Println("  ✗", err)
		return
	}

	rev := model.RevenueInsert{
		CompanyID:    companyID,
		CurrencyID:   currencyID,
		CategoryName: category,
		ParentID:     *parentID,
		Period:       period,
		Value:        value,
	}

	err = database.InsertRevenue(db, rev)
	if err != nil {
		fmt.Println("  ✗ Error:", err)
		return
	}
	fmt.Printf("  ✓ Revenue added: %s = %.2f (%s)\n", category, value, period.String())
}

func ListRevenue(scanner *bufio.Scanner, db *sql.DB) {
	companyID, err := promptInt(scanner, "  Company ID: ")
	if err != nil {
		fmt.Println("  ✗", err)
		return
	}
	period, err := promptPeriod(scanner)
	if err != nil {
		fmt.Println("  ✗", err)
		return
	}

	entries, err := database.GetRevenueByPeriod(db, companyID, period.ID)
	if err != nil {
		fmt.Println("  ✗ Error:", err)
		return
	}

	fmt.Printf("\n  %-20s %12s\n", "CATEGORY", "VALUE")
	fmt.Println("  " + strings.Repeat("-", 34))
	for _, e := range entries {
		fmt.Printf("  %-20s %12.2f\n", e.Category, e.Value)
	}
}
