package crud_lawsuit_status_types

import (
	"context"
	"errors"
	"fmt"
	"github.com/ManyakRus/starter/micro"
	"github.com/ManyakRus/starter/postgres_gorm"
	"gitlab.aescorp.ru/dsp_dev/claim/sync_service/pkg/db/constants"
	"gitlab.aescorp.ru/dsp_dev/claim/sync_service/pkg/object_model/entities/lawsuit_status_types"
	"time"
	"github.com/ManyakRus/starter/contextmain"
	"gitlab.aescorp.ru/dsp_dev/claim/sync_service/pkg/db/crud_functions"
)

// TableName - имя таблицы в БД Postgres
const TableName string = "lawsuit_status_types"

// Crud_DB - объект для CRUD операций через БД
type Crud_DB struct {
}

// Read - находит запись в БД по ID
func (crud Crud_DB) Read(m *lawsuit_status_types.LawsuitStatusType) error {
	var err error

	ctxMain := contextmain.GetContext()
	ctx, ctxCancelFunc := context.WithTimeout(ctxMain, time.Second*time.Duration(constants.TIMEOUT_DB_SECONDS))
	defer ctxCancelFunc()

	err = crud.Read_ctx(ctx, m)
	return err
}

// Read_ctx - находит запись в БД по ID
func (crud Crud_DB) Read_ctx(ctx context.Context, m *lawsuit_status_types.LawsuitStatusType) error {
	var err error

	if micro.ContextDone(ctx) == true {
		err = context.Canceled
		return err
	}

	id := int64(m.ID)

	db := postgres_gorm.GetConnection()
	db.WithContext(ctx)

	tx := db.First(m, id)
	err = tx.Error
	if err != nil {
		err = fmt.Errorf("Read() id: %v, error: %v", id, err)
	}

	return err
}

// Save - записывает новый или существующий объект в базу данных
func (crud Crud_DB) Save(m *lawsuit_status_types.LawsuitStatusType) error {
	ctxMain := contextmain.GetContext()
	ctx, ctxCancelFunc := context.WithTimeout(ctxMain, time.Second*time.Duration(constants.TIMEOUT_DB_SECONDS))
	defer ctxCancelFunc()

	err := crud.Save_ctx(ctx, m)
	return err
}

// Save_ctx - записывает новый или существующий объект в базу данных
func (crud Crud_DB) Save_ctx(ctx context.Context, m *lawsuit_status_types.LawsuitStatusType) error {
	var err error
	if micro.ContextDone(ctx) == true {
		err = context.Canceled
		return err
	}

	is_create := !micro.BoolFromInt64(int64(m.ID))
	err = crud.create_update_ctx(ctx, m, is_create)
	return err
}

// Update - записывает существующий объект в базу данных
func (crud Crud_DB) Update(m *lawsuit_status_types.LawsuitStatusType) error {
	ctxMain := contextmain.GetContext()
	ctx, ctxCancelFunc := context.WithTimeout(ctxMain, time.Second*time.Duration(constants.TIMEOUT_DB_SECONDS))
	defer ctxCancelFunc()

	err := crud.Update_ctx(ctx, m)
	return err
}

// Update_ctx - записывает существующий объект в базу данных
func (crud Crud_DB) Update_ctx(ctx context.Context, m *lawsuit_status_types.LawsuitStatusType) error {
	var err error
	if micro.ContextDone(ctx) == true {
		err = context.Canceled
		return err
	}

	err = crud.create_update_ctx(ctx, m, false)
	return err
}

// Create - записывает новый объект в базу данных
func (crud Crud_DB) Create(m *lawsuit_status_types.LawsuitStatusType) error {
	ctxMain := contextmain.GetContext()
	ctx, ctxCancelFunc := context.WithTimeout(ctxMain, time.Second*time.Duration(constants.TIMEOUT_DB_SECONDS))
	defer ctxCancelFunc()

	err := crud.Create_ctx(ctx, m)
	return err
}

// Create_ctx - записывает новый объект в базу данных
func (crud Crud_DB) Create_ctx(ctx context.Context, m *lawsuit_status_types.LawsuitStatusType) error {
	var err error
	if micro.ContextDone(ctx) == true {
		err = context.Canceled
		return err
	}

	err = crud.create_update_ctx(ctx, m, true)
	return err
}

// create_update - записывает объект в базу данных
func (crud Crud_DB) create_update(m *lawsuit_status_types.LawsuitStatusType, is_create bool) error {
	var err error

	ctxMain := contextmain.GetContext()
	ctx, ctxCancelFunc := context.WithTimeout(ctxMain, time.Second*time.Duration(constants.TIMEOUT_DB_SECONDS))
	defer ctxCancelFunc()

	err = crud.create_update_ctx(ctx, m, is_create)
	return err
}

// create_update_ctx - записывает объект в базу данных
func (crud Crud_DB) create_update_ctx(ctx context.Context, m *lawsuit_status_types.LawsuitStatusType, is_create bool) error {
	var err error

	// log.Trace("start Save() ", TableName, " id: ", int64(m.ID))

	if micro.ContextDone(ctx) == true {
		err = context.Canceled
		return err
	}

	// проверка ID
	if is_create == true {
		if int64(m.ID) != 0 {
			TextError := fmt.Sprint("db.Save() ", TableName, " error: id !=0")
			err = errors.New(TextError)
			return err
		}
	} else if int64(m.ID) == 0 {
		TextError := fmt.Sprint("db.Save() ", TableName, " error: id =0")
		err = errors.New(TextError)
		return err
	}

	//
	db := postgres_gorm.GetConnection()
	db.WithContext(ctx)

	// заполним даты
	//Text_modified_at
	//Text_is_deleted_deleted_at
	//Text_created_at

	//колонки с null
	tx := db
	MassOmit := make([]string, 0)
	var ColumnName string

	//игнор пустых колонок
	tx = tx.Omit(MassOmit...)

	// запись
	if is_create == true {
		tx = tx.Create(&m)
	} else {
		tx = tx.Save(&m)
	}
	err = tx.Error
	if err != nil {
		return err
	}

	//запишем NULL в пустые колонки
	MapOmit := crud_functions.MapOmit_from_MassOmit(MassOmit)
	tx = db.Model(&m).Updates(MapOmit)
	err = tx.Error
	if err != nil {
		TextError := fmt.Sprint("Updates() ", TableName, " id: ", m.ID, " error: ", err)
		err = errors.New(TextError)
		return err
	}
	if err != nil {
		err = fmt.Errorf("Create_Update() id: %v, error: %v", m.ID, err)
	}

	return err
}

// Delete - записывает is_deleted = true
func (crud Crud_DB) Delete(m *lawsuit_status_types.LawsuitStatusType) error {
	var err error

	ctxMain := contextmain.GetContext()
	ctx, ctxCancelFunc := context.WithTimeout(ctxMain, time.Second*time.Duration(constants.TIMEOUT_DB_SECONDS))
	defer ctxCancelFunc()

	err = crud.Delete_ctx(ctx, m)
	return err
}

// Delete_ctx - записывает is_deleted = true
func (crud Crud_DB) Delete_ctx(ctx context.Context, m *lawsuit_status_types.LawsuitStatusType) error {
	var err error

	if micro.ContextDone(ctx) == true {
		err = context.Canceled
		return err
	}

	m2 := lawsuit_status_types.LawsuitStatusType{}
	m2.ID = m.ID
	err = crud.Read_ctx(ctx, &m2)
	if err != nil {
		return err
	}

	m2.IsDeleted = true
	m.IsDeleted = true

	err = crud.Save_ctx(ctx, &m2)
	if err != nil {
		err = fmt.Errorf("Delete() id: %v, error: %v", m.ID, err)
	}

	return err
}

// Restore - записывает is_deleted = true
func (crud Crud_DB) Restore(m *lawsuit_status_types.LawsuitStatusType) error {
	var err error

	ctxMain := contextmain.GetContext()
	ctx, ctxCancelFunc := context.WithTimeout(ctxMain, time.Second*time.Duration(constants.TIMEOUT_DB_SECONDS))
	defer ctxCancelFunc()

	err = crud.Restore_ctx(ctx, m)
	return err
}

// Restore_ctx - записывает is_deleted = true
func (crud Crud_DB) Restore_ctx(ctx context.Context, m *lawsuit_status_types.LawsuitStatusType) error {
	var err error

	if micro.ContextDone(ctx) == true {
		err = context.Canceled
		return err
	}

	m2 := lawsuit_status_types.LawsuitStatusType{}
	m2.ID = m.ID
	err = crud.Read_ctx(ctx, &m2)
	if err != nil {
		return err
	}

	m2.IsDeleted = false
	m.IsDeleted = false

	err = crud.Save_ctx(ctx, &m2)
	if err != nil {
		err = fmt.Errorf("Restore() id: %v, error: %v", m.ID, err)
	}

	return err
}

// Find_ByExtID - находит запись в БД по ext_id и connection_id
func (crud Crud_DB) Find_ByExtID(m *lawsuit_status_types.LawsuitStatusType) error {
	var err error

	if m.ExtID == 0 {
		err = errors.New("Error: ext_id =0")
		return err
	}

	//
	ctxMain := contextmain.GetContext()
	ctx, ctxCancelFunc := context.WithTimeout(ctxMain, time.Second*time.Duration(constants.TIMEOUT_DB_SECONDS))
	defer ctxCancelFunc()

	err = crud.Find_ByExtID_ctx(ctx, m)

	return err
}

// Find_ByExtID_ctx - находит запись в БД по ext_id и connection_id
func (crud Crud_DB) Find_ByExtID_ctx(ctx context.Context, m *lawsuit_status_types.LawsuitStatusType) error {
	var err error

	if micro.ContextDone(ctx) == true {
		err = context.Canceled
		return err
	}

	if m.ExtID == 0 {
		err = errors.New("Error: ExtID=0")
		return err
	}

	db := postgres_gorm.GetConnection()
	db.WithContext(ctx)

	tx := db.Where("ext_id = ?", m.ExtID).Where("connection_id = ?", m.ConnectionID).First(m)
	err = tx.Error
	if err != nil {
		err = fmt.Errorf("Find_ByExtID() id: %v, error: %v", m.ID, err)
	}

	return err
}
