package model

import "time"

type GLAccountType string

const (
	GLRevenue   GLAccountType = "revenue"
	GLCOGS      GLAccountType = "cogs"
	GLOpex      GLAccountType = "opex"
	GLCapex     GLAccountType = "capex"
	GLHeadcount GLAccountType = "headcount"
)

type BudgetVersion string

const (
	VersionOriginal  BudgetVersion = "original"
	VersionForecast1 BudgetVersion = "forecast_1"
	VersionForecast2 BudgetVersion = "forecast_2"
)

type Department struct {
	ID         int    `json:"id"`
	Code       string `json:"code"`
	Name       string `json:"name"`
	CostCenter string `json:"cost_center"`
}

type GLAccount struct {
	ID          int           `json:"id"`
	Code        string        `json:"code"`
	Description string        `json:"description"`
	Type        GLAccountType `json:"type"`
	FavourHigh  bool          `json:"favour_high"`
}

type Budget struct {
	ID           int           `json:"id"`
	FiscalYear   int           `json:"fiscal_year"`
	FiscalPeriod int           `json:"fiscal_period"`
	Version      BudgetVersion `json:"version"`
	DepartmentID int           `json:"department_id"`
	GLAccountID  int           `json:"gl_account_id"`
	Amount       float64       `json:"amount"`
	Currency     string        `json:"currency"`
	Notes        string        `json:"notes,omitempty"`
	CreatedBy    string        `json:"created_by"`
	CreatedAt    time.Time     `json:"created_at"`
	UpdatedAt    time.Time     `json:"updated_at"`
}

type CreateBudgetRequest struct {
	FiscalYear   int           `json:"fiscal_year"`
	FiscalPeriod int           `json:"fiscal_period"`
	Version      BudgetVersion `json:"version"`
	DepartmentID int           `json:"department_id"`
	GLAccountID  int           `json:"gl_account_id"`
	Amount       float64       `json:"amount"`
	Currency     string        `json:"currency"`
	Notes        string        `json:"notes"`
	CreatedBy    string        `json:"created_by"`
}

func (cBudget *CreateBudgetRequest) Valid() []string {
	var errs []string

	if cBudget.FiscalYear < 1 || cBudget.FiscalYear > 2200 {
		errs = append(errs, "fiscal_year must be between 1 and 2200")
	}
	if cBudget.FiscalPeriod < 1 || cBudget.FiscalPeriod > 12 {
		errs = append(errs, "fiscal_period must be between 1 and 12")
	}
	if cBudget.Version == "" {
		errs = append(errs, "version is required")
	}
	if cBudget.DepartmentID == 0 {
		errs = append(errs, "department_id is required")
	}
	if cBudget.GLAccountID == 0 {
		errs = append(errs, "gl_account_id is required")
	}
	if cBudget.Amount <= 0 {
		errs = append(errs, "amount must be greater than 0")
	}
	if cBudget.Currency == "" {
		errs = append(errs, "currency is required")
	}
	if cBudget.CreatedBy == "" {
		errs = append(errs, "created_by is required")
	}

	return errs
}

type UpdateBudgetRequest struct {
	ID           int           `json:"id"`
	FiscalYear   int           `json:"fiscal_year"`
	FiscalPeriod int           `json:"fiscal_period"`
	Version      BudgetVersion `json:"version"`
	DepartmentID int           `json:"department_id"`
	GLAccountID  int           `json:"gl_account_id"`
	Amount       float64       `json:"amount"`
	Currency     string        `json:"currency"`
	Notes        string        `json:"notes"`
	ChangedBy    string        `json:"created_by"`
}

func (uBudget *UpdateBudgetRequest) Valid() []string {
	var errs []string

	if uBudget.FiscalYear < 1 || uBudget.FiscalYear > 2200 {
		errs = append(errs, "fiscal_year must be between 1 and 2200")
	}
	if uBudget.FiscalPeriod < 1 || uBudget.FiscalPeriod > 12 {
		errs = append(errs, "fiscal_period must be between 1 and 12")
	}
	if uBudget.Version == "" {
		errs = append(errs, "version is required")
	}
	if uBudget.DepartmentID == 0 {
		errs = append(errs, "department_id is required")
	}
	if uBudget.GLAccountID == 0 {
		errs = append(errs, "gl_account_id is required")
	}
	if uBudget.Amount <= 0 {
		errs = append(errs, "amount must be greater than 0")
	}
	if uBudget.Currency == "" {
		errs = append(errs, "currency is required")
	}
	if uBudget.ChangedBy == "" {
		errs = append(errs, "created_by is required")
	}

	return errs
}

type Actual struct {
	ID           int       `json:"id"`
	FiscalYear   int       `json:"fiscal_year"`
	FiscalPeriod int       `json:"fiscal_period"`
	DepartmentID int       `json:"department_id"`
	GLAccountID  int       `json:"gl_account_id"`
	GLCode       string    `json:"gl_code"`
	Amount       float64   `json:"amount"`
	Currency     string    `json:"currency"`
	Source       string    `json:"source"`
	IngestedAt   time.Time `json:"ingested_at"`
}

type IngestActualsRequest struct {
	FiscalYear   int     `json:"fiscal_year"`
	FiscalPeriod int     `json:"fiscal_period"`
	DeptCode     string  `json:"dept_code"`
	GLCode       string  `json:"gl_code"`
	Amount       float64 `json:"amount"`
	Currency     string  `json:"currency"`
	Source       string  `json:"source"`
}

func (i *IngestActualsRequest) Valid() []string {
	var errs []string

	if i.FiscalYear < 1 || i.FiscalYear > 2200 {
		errs = append(errs, "fiscal_year must be between 1 and 2200")
	}
	if i.FiscalPeriod < 1 || i.FiscalPeriod > 12 {
		errs = append(errs, "fiscal_period must be between 1 and 12")
	}
	if i.DeptCode == "" {
		errs = append(errs, "dept_code is required")
	}
	if i.GLCode == "" {
		errs = append(errs, "gl_code is required")
	}
	if i.Amount <= 0 {
		errs = append(errs, "amount must be greater than 0")
	}
	if i.Currency == "" {
		errs = append(errs, "currency is required")
	}
	if i.Source == "" {
		errs = append(errs, "source is required")
	}

	return errs
}

type VarianceStatus string

const (
	StatusFavourable   VarianceStatus = "favourable"
	StatusUnfavourable VarianceStatus = "unfavourable"
	StatusOnBudget     VarianceStatus = "on_budget"
)

type VarianceLine struct {
	GLCode        string         `json:"gl_account_id"`
	GLDescription string         `json:"gl_description"`
	GLType        GLAccountType  `json:"gl_type"`
	Budget        float64        `json:"budget"`
	Actual        float64        `json:"actual"`
	VarianceAbs   float64        `json:"variance_abs"`
	VariancePct   *float64       `json:"variance_pct"`
	Status        VarianceStatus `json:"status"`
	Currency      string         `json:"currency"`
}

type VarianceReport struct {
	Department    string         `json:"department"`
	FiscalYear    int            `json:"fiscal_year"`
	FiscalPeriod  int            `json:"fiscal_period"`
	Version       BudgetVersion  `json:"version"`
	Currency      string         `json:"currency"`
	Lines         []VarianceLine `json:"lines"`
	TotalBudget   float64        `json:"total_budget"`
	TotalActual   float64        `json:"total_actual"`
	TotalVariance float64        `json:"total_variance"`
	VariancePct   *float64       `json:"total_variance_pct"`
}

type AlertThreshold struct {
	GLCode      string         `json:"gl_code"`
	Description string         `json:"description"`
	Budget      float64        `json:"budget"`
	Actual      float64        `json:"actual"`
	VariancePct float64        `json:"variance_pct"`
	Status      VarianceStatus `json:"status"`
	Department  string         `json:"department"`
}

// BudgetRow is used internally by the variance service
type BudgetRow struct {
	GLCode        string
	GLDescription string
	GLType        GLAccountType
	FavourHigh    bool
	Amount        float64
	Currency      string
}
