package service

import (
	"context"
	"fmt"

	"Engine/internal/database"
	"Engine/internal/model"
)

type ReportService struct {
	repo *database.ReportRepo
}

func NewReportService(repo *database.ReportRepo) *ReportService {
	return &ReportService{repo: repo}
}

type PnLFilter struct {
	FiscalYear   int
	FiscalPeriod int
	DeptCode     string
	Version      model.BudgetVersion
}

func (s *ReportService) CreatePnL(ctx context.Context, f PnLFilter) (*model.PnLReport, error) {
	// fetch all five GL type buckets in parallel would be nicer, but keeping
	// it simple and sequential matches the rest of your codebase style.

	revenue, err := s.repo.GetGLRevenueActuals(ctx, f.FiscalYear, f.FiscalPeriod, f.DeptCode)
	if err != nil {
		return nil, fmt.Errorf("CreatePnL: revenue actuals: %w", err)
	}

	cogs, err := s.repo.GetGLCOGSActuals(ctx, f.FiscalYear, f.FiscalPeriod, f.DeptCode)
	if err != nil {
		return nil, fmt.Errorf("CreatePnL: cogs actuals: %w", err)
	}

	opex, err := s.repo.GetGLOpexActuals(ctx, f.FiscalYear, f.FiscalPeriod, f.DeptCode)
	if err != nil {
		return nil, fmt.Errorf("CreatePnL: opex actuals: %w", err)
	}

	headcount, err := s.repo.GetGLHeadcountActuals(ctx, f.FiscalYear, f.FiscalPeriod, f.DeptCode)
	if err != nil {
		return nil, fmt.Errorf("CreatePnL: headcount actuals: %w", err)
	}

	capex, err := s.repo.GetGLCapexActuals(ctx, f.FiscalYear, f.FiscalPeriod, f.DeptCode)
	if err != nil {
		return nil, fmt.Errorf("CreatePnL: capex actuals: %w", err)
	}

	report := &model.PnLReport{
		Department:   f.DeptCode,
		FiscalYear:   f.FiscalYear,
		FiscalPeriod: f.FiscalPeriod,
		Version:      f.Version,
		Currency:     "DKK",
		Revenue:      toSection(revenue),
		COGS:         toSection(cogs),
		Opex:         toSection(opex),
		Headcount:    toSection(headcount),
		Capex:        toSection(capex),
	}

	report.GrossProfit = report.Revenue.Total - report.COGS.Total
	report.EBIT = report.GrossProfit - report.Opex.Total - report.Headcount.Total
	report.NetIncome = report.EBIT - report.Capex.Total

	return report, nil
}

// toSection sums the rows and packages them into a PnLSection.
func toSection(rows []model.GLAmountRow) model.PnLSection {
	s := model.PnLSection{Lines: rows}
	for _, r := range rows {
		s.Total += r.Amount
	}
	return s
}
