package database

import (
	"Portifolio/internal/model"
	"database/sql"
	"fmt"
	"time"

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

func GetPeriodByID(db *sql.DB, periodID int) (model.Period, error) {
	var p model.Period
	var start, end string
	err := db.QueryRow(
		`SELECT type, year, idx, start_date, end_date FROM periods WHERE id = ?`,
		periodID,
	).Scan(&p.Type, &p.Year, &p.Index, &start, &end)
	if err == sql.ErrNoRows {
		return p, fmt.Errorf("period %d not found", periodID)
	}
	if err != nil {
		return p, fmt.Errorf("get period by id: %w", err)
	}
	p.Start, _ = time.Parse("2006-01-02", start)
	p.End, _ = time.Parse("2006-01-02", end)
	return p, nil
}

func GetRevenueByPeriod(db *sql.DB, companyID int, periodID int) ([]model.Revenue, error) {
	rows, err := db.Query(
		`SELECT id, company_id, currency_id, period_id, value FROM revenue_entries WHERE company_id = ? AND period_id = ?`,
		companyID, periodID,
	)
	if err != nil {
		return nil, fmt.Errorf("query revenue by period: %w", err)
	}
	defer rows.Close()

	var revenues []model.Revenue
	for rows.Next() {
		var rc model.Revenue
		if err := rows.Scan(&rc.ID, &rc.Company, &rc.Currency, &rc.Period, &rc.Value); err != nil {
			return nil, fmt.Errorf("scan revenue row: %w", err)
		}
		revenues = append(revenues, rc)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate revenue rows: %w", err)
	}
	if len(revenues) == 0 {
		return nil, fmt.Errorf("revenue by company %d and period_id %d not found", companyID, periodID)
	}

	return revenues, nil
}

func GetRevenueByCategory(db *sql.DB, companyID int, categoryID int) ([]model.Revenue, error) {
	rows, err := db.Query(
		`SELECT id, company_id, currency_id, category_id, value FROM revenue_entries WHERE company_id = ? AND category_id = ?`,
		companyID, categoryID,
	)
	if err != nil {
		return nil, fmt.Errorf("query revenue by category: %w", err)
	}
	defer rows.Close()

	var revenues []model.Revenue
	for rows.Next() {
		var rc model.Revenue
		if err := rows.Scan(&rc.ID, &rc.Company, &rc.Currency, &rc.Category, &rc.Value); err != nil {
			return nil, fmt.Errorf("scan revenue row: %w", err)
		}
		revenues = append(revenues, rc)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate revenue rows: %w", err)
	}
	if len(revenues) == 0 {
		return nil, fmt.Errorf("revenue by company %d and category_id %d not found", companyID, categoryID)
	}

	return revenues, nil
}

func InsertRevenue(db *sql.DB, rev model.RevenueInsert) error {
	_, err := GetCompanyByID(db, rev.CompanyID)
	if err != nil {
		return err
	}

	_, err = GetCurrencyByID(db, rev.CurrencyID)
	if err != nil {
		return err
	}

	// checking if period is in db, in case not will insert
	_, err = GetPeriodByID(db, rev.Period.ID)
	if err != nil {
		err = rev.Period.Insert(db)
		if err != nil {
			return err
		}
	}
	// Getting Category, if error, trying to insert the category with the company.
	category, err := GetCategoryByName(db, rev.CompanyID, rev.CategoryName)
	if err != nil {
		err := InsertCategory(db, model.RevenueCategory{
			CompanyID: rev.CompanyID,
			ParentID:  &rev.ParentID,
			Name:      rev.CategoryName,
		})
		if err != nil {
			return err
		}

	}
	category, err = GetCategoryByName(db, rev.CompanyID, rev.CategoryName)
	if err != nil {
		return err
	}

	_, err = db.Exec(
		`INSERT INTO revenue_entries (company_id, currency_id, category_id, period_id, value)
         VALUES (?, ?, ?, ?, ?)`,
		rev.CompanyID, rev.CurrencyID, category.ID, rev.Period.ID, rev.Value,
	)
	if err != nil {
		return fmt.Errorf("insert revenue_entries: %w", err)
	}

	return nil
}
