package expense

import (
	"strconv"
	"strings"
	"time"

	"gitea.frenchtouch.duckdns.org/kratisto/budget-backend/internal/account"
	"gitea.frenchtouch.duckdns.org/kratisto/budget-backend/internal/storage/dao"
	"gitea.frenchtouch.duckdns.org/kratisto/budget-backend/internal/storage/model"
	"gitea.frenchtouch.duckdns.org/kratisto/budget-backend/internal/utils"
)

type Service struct {
	db *Database
}

func (s Service) GetExpensesOfAnAccountBetween(accountId, from, to string) ([]*Expense, error) {
	expenses, err := s.db.GetExpensesOfAnAccountBetween(accountId, from, to)
	utils.GetLogger().Info(err)
	if e, ok := err.(*dao.Error); ok {
		switch e.Type {
		case dao.ErrTypeNotFound:
			return nil, &model.ErrNotFound
		default:
			return nil, &model.ErrInternalServer
		}
	} else if err != nil {
		return nil, &model.ErrInternalServer
	}

	if expenses == nil {
		return nil, &model.ErrNotFound
	}
	return expenses, nil
}

func (s Service) GetAllExpensesOfAnAccount(accountId string) ([]*Expense, error) {
	expenses, err := s.db.GetAllExpensesOfAnAccount(accountId)
	utils.GetLogger().Info(err)
	if e, ok := err.(*dao.Error); ok {
		switch e.Type {
		case dao.ErrTypeNotFound:
			return nil, &model.ErrNotFound
		default:
			return nil, &model.ErrInternalServer
		}
	} else if err != nil {
		return nil, &model.ErrInternalServer
	}

	if expenses == nil {
		return nil, &model.ErrNotFound
	}
	return expenses, nil
}

func (s Service) CreateExpense(expense *Expense) error {

	return s.db.CreateExpense(expense)
}

func (s Service) ProcessCSVFile(filedata [][]string, account *account.Account) error {
	switch account.Provider {
	case "caisse-epargne":
		return s.processCaisseEpargne(filedata, account)
	case "boursorama":
		return s.processBoursorama(filedata, account)
	case "bnp":
		return s.processBnp(filedata, account)
	default:
		return nil
	}

}

func (s Service) processCaisseEpargne(filedata [][]string, account *account.Account) error {
	for _, val := range filedata[4:] {
		expenseDate, err := time.Parse("02/01/06", val[0])
		if err != nil {
			utils.GetLogger().Info(err)
			continue
		}
		amount := val[3]
		typeExpense := "D"
		if amount == "" {
			amount = val[4]
			typeExpense = "C"
		}
		amountParsed, err := strconv.ParseFloat(strings.Trim(strings.ReplaceAll(amount, ",", "."), "+"), 32)
		if err != nil {
			utils.GetLogger().Info(err)
			continue
		}
		expense := &Expense{
			ExpenseEditable: ExpenseEditable{
				Value:       float32(amountParsed),
				Libelle:     val[2],
				TypeExpense: typeExpense,
				ExpenseDate: expenseDate,
			},
			AccountId: account.ID,
		}
		err = s.CreateExpense(expense)
		if err != nil {
			return err
		}
		utils.GetLogger().Info(val)
	}

	return nil
}

func (s Service) processBoursorama(filedata [][]string, account *account.Account) error {
	return nil
}

func (s Service) processBnp(filedata [][]string, account *account.Account) error {
	return nil
}

func NewService(database *Database) *Service {
	return &Service{db: database}
}
