package mysql

import (
	"context"
	"strings"

	"gorm.io/gorm"

	v1 "github.com/pingcap-inc/security/model/v1"
)

type company struct {
	db *gorm.DB
}

func newCompany(ds *datastore) *company {
	return &company{db: ds.db}
}

func (c *company) CreateCompany(_ context.Context, records []v1.Company) error {
	if len(records) == 0 {
		return nil
	}

	err := c.db.Create(records).Error

	return err
}
func (c *company) CreateCompanyOne(_ context.Context, record v1.Company) error {
	err := c.db.Create(&record).Error

	return err
}

func (c *company) ListCompany(_ context.Context) (records []v1.Company, err error) {
	err = c.db.Find(&records).Error
	return
}

func (c *company) GetCompany(_ context.Context, name, country string) (record []*v1.Company, err error) {
	pre := c.db.Where("name like ?", "%"+name+"%")
	if country != "" {
		pre = pre.Where("country = ?", country)
	}
	// pre = pre.Where("status = ?", 1)
	err = pre.Find(&record).Error
	return
}

func (c *company) GetCompanyByID(_ context.Context, id int) (record *v1.Company, err error) {
	err = c.db.Where("id = ?", id).First(&record).Error
	return
}

func (c *company) ListCompanyByStatus(_ context.Context, status int) (records []*v1.Company, err error) {
	err = c.db.Where("status = ?", status).Find(&records).Error
	return
}

func (c *company) UpdateCompanyStatus(_ context.Context, record *v1.Company) error {
	err := c.db.Save(record).Error

	return err
}

func (c *company) BatchUpdateCompanyStatus(_ context.Context, status int) error {
	// 更新所有
	err := c.db.Model(&v1.Company{}).Where("1=1").Update("status", status).Error

	return err
}

func (c *company) DeleteCompanyInformation(_ context.Context, id int) error {
	// 根据id 清除companyporblem, companysanction, companysanctionreferences, companybasic
	err := c.db.Transaction(func(tx *gorm.DB) error {
		err := tx.Where("company_id = ?", id).Delete(&v1.CompanyProblem{}).Error
		if err != nil {
			return err
		}

		err = tx.Where("company_id = ?", id).Delete(&v1.CompanySanction{}).Error
		if err != nil {
			return err
		}

		err = tx.Where("company_id = ?", id).Delete(&v1.CompanySanctionReferences{}).Error
		if err != nil {
			return err
		}

		err = tx.Where("company_id = ?", id).Delete(&v1.CompanyBasic{}).Error
		if err != nil {
			return err
		}

		// 更新status=0 reload =1
		err = tx.Model(&v1.Company{}).Where("id = ?", id).Update("status", 0).Update("is_reload", 1).Error
		if err != nil {
			return err
		}

		return nil
	})
	return err
}

func (c *company) SaveComProblem(_ context.Context, record *v1.CompanyProblem) error {
	err := c.db.Save(record).Error

	return err
}

func (c *company) ListComProblem(_ context.Context) (records []v1.CompanyProblem, err error) {
	err = c.db.Find(&records).Error
	return
}

func (c *company) GetComProblem(_ context.Context, name string) (record *v1.CompanyProblem, err error) {
	err = c.db.Where("company_name = ?", name).First(&record).Error
	return
}

func (c *company) ListSanction(_ context.Context) (records []v1.CompanySanction, err error) {
	err = c.db.Find(&records).Error
	return
}

func (c *company) CreateSanction(_ context.Context, records []v1.CompanySanction) error {
	if len(records) == 0 {
		return nil
	}

	err := c.db.Save(records).Error

	return err
}

func (c *company) SaveSanction(_ context.Context, record *v1.CompanySanction) (uint64, error) {
	err := c.db.Save(record).Error

	return record.ID, err
}

func (c *company) ListCompanyOthers(_ context.Context) (records []v1.CompanyBasic, err error) {
	err = c.db.Find(&records).Error
	return
}

func (c *company) CreateCompanyOthers(_ context.Context, records []v1.CompanyBasic) error {
	if len(records) == 0 {
		return nil
	}

	err := c.db.Save(records).Error

	return err
}

func (c *company) ListCompanyBasic(_ context.Context) (records []v1.CompanyBasic, err error) {
	err = c.db.Find(&records).Error
	return
}

func (c *company) SaveCompanyBasic(_ context.Context, record *v1.CompanyBasic) error {
	err := c.db.Save(record).Error

	return err
}

func (c *company) GetCompanyBasicByID(_ context.Context, id int) (record *v1.CompanyBasic, err error) {
	err = c.db.Where("id = ?", id).First(&record).Error

	return
}

func (c *company) DeleteCompanyBaiscByCompanyID(_ context.Context, companyID int) error {
	err := c.db.Where("company_id = ?", companyID).Delete(&v1.CompanyBasic{}).Error

	return err
}

func (c *company) SaveSanctionReferences(_ context.Context, record []v1.CompanySanctionReferences) error {
	if len(record) == 0 {
		return nil
	}

	err := c.db.Save(record).Error

	return err
}

func (c *company) ListSanctionReferences(_ context.Context) (records []v1.CompanySanctionReferences, err error) {
	err = c.db.Find(&records).Error
	return
}

func (c *company) ListAllByCompanyIDs(_ context.Context, comIDs []uint64) (ci []*v1.CompanyProblem, cs []*v1.CompanySanction, csr []*v1.CompanySanctionReferences, co []*v1.CompanyBasic, err error) {
	err = c.db.Where("company_id IN ?", comIDs).Find(&ci).Error
	if err != nil {
		return
	}

	err = c.db.Where("company_id IN ?", comIDs).Find(&cs).Error
	if err != nil {
		return
	}

	err = c.db.Where("company_id IN ?", comIDs).Find(&csr).Error
	if err != nil {
		return
	}

	err = c.db.Where("company_id IN ?", comIDs).Find(&co).Error
	if err != nil {
		return
	}

	return
}

func (c *company) ListCompanyInfoPrincipalsContacts(_ context.Context) (records []v1.CompanyInfoPrincipalsContacts, err error) {
	err = c.db.Find(&records).Error
	return
}

func (c *company) CreateCompanyInfoPrincipalsContacts(_ context.Context, record *v1.CompanyInfoPrincipalsContacts) error {
	err := c.db.Create(record).Error

	return err
}

func (c *company) SaveUserLog(_ context.Context, record *v1.UserLog) error {
	err := c.db.Save(record).Error

	return err
}

func (c *company) DeleteAll(_ context.Context) error {

	// 物理删除数据
	err := c.db.Where("1=1").Unscoped().Delete(&v1.CompanyBasic{}).Error
	if err != nil {
		return err
	}

	err = c.db.Where("1=1").Unscoped().Delete(&v1.CompanyProblem{}).Error
	if err != nil {
		return err
	}

	err = c.db.Where("1=1").Unscoped().Delete(&v1.CompanySanction{}).Error
	if err != nil {
		return err
	}

	err = c.db.Where("1=1").Unscoped().Delete(&v1.CompanySanctionReferences{}).Error
	if err != nil {
		return err
	}

	err = c.db.Where("1=1").Unscoped().Delete(&v1.CompanyInfoPrincipalsContacts{}).Error
	if err != nil {
		return err
	}

	return nil
}

func (c *company) ListCompanyByWeb(companyName, country, from string, offset, pageSize int) (records []*v1.Company, total int64, err error) {
	tx := c.db.Model(&v1.Company{})
	if companyName != "" {
		tx = tx.Where("name like ?", "%"+companyName+"%")
	}
	if country != "" {
		tx = tx.Where("country = ?", strings.ToUpper(country))
	}
	if from != "" {
		tx = tx.Where("`from` = ?", from)
	}
	err = tx.Count(&total).Error
	if err != nil {
		return
	}

	if offset != 0 {
		tx = tx.Offset(offset)
	}
	if pageSize != 0 {
		tx = tx.Limit(pageSize)
	}

	err = tx.Find(&records).Error

	return
}

func (c *company) ListCompanyBasicByWeb(companyName, country string, companyID, offset, pageSize int) (records []*v1.CompanyBasic, total int64, err error) {
	tx := c.db.Model(&v1.CompanyBasic{})
	if companyName != "" {
		tx = tx.Where("company_name like ?", "%"+companyName+"%")
	}
	if country != "" {
		tx = tx.Where("country = ?", strings.ToUpper(country))
	}
	if companyID != 0 {
		tx = tx.Where("company_id = ?", companyID)
	}
	err = tx.Count(&total).Error
	if err != nil {
		return
	}

	if offset != 0 {
		tx = tx.Offset(offset)
	}
	if pageSize != 0 {
		tx = tx.Limit(pageSize)
	}

	err = tx.Find(&records).Error

	return
}

func (c *company) ListProblemByWeb(companyName string, companyID, offset, pageSize int) (records []*v1.CompanyProblem, total int64, err error) {
	tx := c.db.Model(&v1.CompanyProblem{})
	if companyName != "" {
		tx = tx.Where("company_name like ?", "%"+companyName+"%")
	}
	if companyID != 0 {
		tx = tx.Where("company_id = ?", companyID)
	}
	err = tx.Count(&total).Error
	if err != nil {
		return
	}

	if offset != 0 {
		tx = tx.Offset(offset)
	}
	if pageSize != 0 {
		tx = tx.Limit(pageSize)
	}

	err = tx.Find(&records).Error

	return
}

func (c *company) ListCompanyInfoPrincipalsContactsByWeb(companyID, offset, pageSize int) (records []*v1.CompanyInfoPrincipalsContacts, total int64, err error) {
	tx := c.db.Model(&v1.CompanyInfoPrincipalsContacts{})
	if companyID != 0 {
		tx = tx.Where("company_basic_id = ?", companyID)
	}
	err = tx.Count(&total).Error
	if err != nil {
		return
	}

	if offset != 0 {
		tx = tx.Offset(offset)
	}
	if pageSize != 0 {
		tx = tx.Limit(pageSize)
	}

	err = tx.Find(&records).Error

	return
}

func (c *company) ListSanctionByWeb(companyName, EntityID string, companyID, offset, pageSize int) (records []*v1.CompanySanction, total int64, err error) {
	tx := c.db.Model(&v1.CompanySanction{})
	if companyName != "" {
		tx = tx.Where("company_name like ?", "%"+companyName+"%")
	}
	if companyID != 0 {
		tx = tx.Where("company_id = ?", companyID)
	}
	if EntityID != "" {
		tx = tx.Where("entity_id = ?", EntityID)
	}
	err = tx.Count(&total).Error
	if err != nil {
		return
	}

	if offset != 0 {
		tx = tx.Offset(offset)
	}
	if pageSize != 0 {
		tx = tx.Limit(pageSize)
	}

	err = tx.Find(&records).Error

	return
}

func (c *company) ListReferenceByWeb(sanctionID, offset, pageSize int) (records []*v1.CompanySanctionReferences, total int64, err error) {
	tx := c.db.Model(&v1.CompanySanctionReferences{})
	if sanctionID != 0 {
		tx = tx.Where("sanction_id = ?", sanctionID)
	}
	err = tx.Count(&total).Error
	if err != nil {
		return
	}

	if offset != 0 {
		tx = tx.Offset(offset)
	}
	if pageSize != 0 {
		tx = tx.Limit(pageSize)
	}

	err = tx.Find(&records).Error

	return
}
