package db

import (
	"context"

	"go.uber.org/zap/zapcore"
)

type Account struct {
	ID                   int    `json:"id" db:"id"`
	AWSAccountID         string `json:"aws_account_id" db:"aws_account_id"`
	Label                string `json:"label" db:"label"`
	ServiceID            int    `json:"service_id" db:"service_id"`
	CloudformationStatus string `json:"cloudformation_status" db:"cloudformation_status"`
}

func (a Account) Editable() AccountEditable {
	return AccountEditable{
		Label:                a.Label,
		AWSAccountID:         a.AWSAccountID,
		CloudformationStatus: a.CloudformationStatus,
	}
}

func (a Account) MarshalLogObject(enc zapcore.ObjectEncoder) error {
	enc.AddInt("id", a.ID)
	enc.AddString("awsAccountID", a.AWSAccountID)
	enc.AddString("label", a.Label)
	enc.AddInt("serviceID", a.ServiceID)
	enc.AddString("cloudformationStatus", a.CloudformationStatus)
	return nil
}

type AccountEditable struct {
	Label                string
	AWSAccountID         string
	CloudformationStatus string
}

func (a AccountEditable) MarshalLogObject(enc zapcore.ObjectEncoder) error {
	enc.AddString("awsAccountID", a.AWSAccountID)
	enc.AddString("label", a.Label)
	return nil
}

type AccountsDB interface {
	AccountCreate(ctx context.Context, account *Account) (int, error)

	AccountUpdate(ctx context.Context, id int, accountEditable *AccountEditable) (int, error)
	AccountUpdateCloudformationStatus(ctx context.Context, id int, cloudformationStatus string) (int, error)
	AccountDelete(ctx context.Context, id int) error

	Accounts(ctx context.Context) ([]*Account, error)
	AccountByID(ctx context.Context, id int) (*Account, error)
	AccountsByServiceID(ctx context.Context, serviceID int) ([]*Account, error)
	AccountByServiceIDAndAWSAccount(ctx context.Context, serviceID int, awsAccount string) (*Account, error)
}

// Have an array of account struct alias for logging purposes
type AccountsEditable []*AccountEditable

func (a AccountsEditable) MarshalLogArray(enc zapcore.ArrayEncoder) error {
	for _, acctEditable := range a {
		if err := enc.AppendObject(acctEditable); err != nil {
			return err
		}
	}
	return nil
}
