package com.ecep.contract.cloud.u8.ctx;

import java.time.Instant;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;

import org.hibernate.Hibernate;
import org.springframework.util.StringUtils;

import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import com.ecep.contract.cloud.old.OldVersionService;
import com.ecep.contract.ds.company.service.CompanyService;
import com.ecep.contract.ds.vendor.service.CompanyVendorEntityService;
import com.ecep.contract.ds.vendor.service.CompanyVendorService;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.CompanyVendor;
import com.ecep.contract.model.CompanyVendorEntity;
import com.ecep.contract.model.VendorCatalog;

import lombok.Setter;

public class VendorCtx extends AbstractYongYouU8Ctx {
    private static final String AUTO_CREATE_VENDOR_AFTER = "cloud.u8.auto-create-vendor-after";
    @Setter
    private CompanyVendorService companyVendorService;
    @Setter
    private CompanyCtx companyCtx;
    @Setter
    private ContractCtx contractCtx;
    @Setter
    private CompanyBankAccountCtx companyBankAccountCtx;

    public CompanyCtx getCompanyCtx() {
        if (companyCtx == null) {
            companyCtx = new CompanyCtx();
            companyCtx.from(this);
        }
        return companyCtx;
    }

    ContractCtx getContractCtx() {
        if (contractCtx == null) {
            contractCtx = new ContractCtx();
            contractCtx.from(this);
        }
        return contractCtx;
    }

    CompanyBankAccountCtx getCompanyBankAccountCtx() {
        if (companyBankAccountCtx == null) {
            companyBankAccountCtx = new CompanyBankAccountCtx();
            companyBankAccountCtx.from(this);
        }
        return companyBankAccountCtx;
    }

    /**
     * 更新供应商相关项（相关项是 U8 系统中的 Vendor 表数据，因为同一个公司有多个相关项，因此需要一个一对多的关系来处理）详情
     *
     * @param item     供应商相关项
     * @param unitCode 供应商相关项编码
     * @param holder   消息
     */
    public CompanyVendorEntity updateVendorEntityDetailByCode(CompanyVendorEntity item, String unitCode, MessageHolder holder) {
        if (applyEntityDetail(item, repository.findVendorByVendCode(unitCode), holder)) {
            item = save(item);
        }
        return item;
    }

    public boolean applyEntityDetail(CompanyVendorEntity item, Map<String, Object> map, MessageHolder holder) {
        if (map == null || map.isEmpty()) {
            holder.warn("Vendor 中未检索到供应商数据");
            return false;
        }
        String name = (String) map.get("cVenName");
        String abbName = (String) map.get("cVenAbbName");
        String venCode = (String) map.get("cVenCode");
        String classCode = (String) map.get("cVCCode");

        String createPerson = (String) map.get("cCreatePerson");
        String modifyPerson = (String) map.get("cModifyPerson");
        java.sql.Date devDate = (java.sql.Date) map.get("devDate");
        java.sql.Timestamp modifyDate = (java.sql.Timestamp) map.get("dModifyDate");
        java.sql.Timestamp createDatetime = (java.sql.Timestamp) map.get("dVenCreateDatetime");

        String bank = (String) map.get("cVenBank");
        String bankAccount = (String) map.get("cVenAccount");
        String address = (String) map.get("cVenAddress");
        String phone = (String) map.get("cVenPhone");
        String person = (String) map.get("cVenPerson");


        boolean modified = false;
        if (updateText(item::getName, item::setName, name, holder, "名称")) {
            modified = true;
        }
        if (updateText(item::getAbbName, item::setAbbName, abbName, holder, "简称")) {
            modified = true;
        }
        if (updateText(item::getCode, item::setCode, venCode, holder, "供应商编号")) {
            modified = true;
        }
        if (updateVendorCatalog(item::getCatalog, item::setCatalog, classCode, holder, "分类")) {
            modified = true;
        }
        if (updateEmployeeByName(item::getCreator, item::setCreator, createPerson, holder, "创建人")) {
            modified = true;
        }
        if (updateEmployeeByName(item::getModifier, item::setModifier, modifyPerson, holder, "修改人")) {
            modified = true;
        }
        if (updateLocalDate(item::getDevelopDate, item::setDevelopDate, devDate, holder, "开发日期")) {
            modified = true;
        }
        if (updateLocalDate(item::getModifyDate, item::setModifyDate, modifyDate, holder, "修改日期")) {
            modified = true;
        }

        if (modified) {
            LocalDate today = LocalDate.now();
            if (item.getUpdatedDate() == null || item.getUpdatedDate().isBefore(today)) {
                item.setUpdatedDate(today);
                holder.info("更新日期更新为 " + today);
            }
        }


        CompanyVendor vendor = item.getVendor();
        if (vendor == null) {
            // 如果没有关联供应商，则根据供应商名称或别名查找公司
            Company company = findOrCreateCompanyByVendorEntity(item, holder);
            if (company != null) {
                vendor = getCompanyVendorService().findByCompany(company);
                if (vendor == null) {
                    vendor = createVendorByVendorEntity(item, holder);
                    if (vendor != null) {
                        vendor.setCompany(company);
                        vendor = getCompanyVendorService().save(vendor);
                    }
                }
                if (vendor != null) {
                    item.setVendor(vendor);
                    modified = true;
                }
            }
        }
        if (vendor != null) {
            if (!Hibernate.isInitialized(vendor)) {
                vendor = getCompanyVendorService().findById(vendor.getId());
            }
            Company company = vendor.getCompany();
            if (company != null) {
                getCompanyBankAccountCtx().updateBankAccount(company, bank, bankAccount, holder.sub(item.getName()));
            }
        }
        return modified;
    }

    private boolean updateVendorCatalog(Supplier<VendorCatalog> getter, Consumer<VendorCatalog> setter, String catalogCode, MessageHolder holder, String topic) {
        VendorCatalog catalog = null;
        if (StringUtils.hasText(catalogCode)) {
            catalog = getCompanyVendorService().findCatalogByCode(catalogCode);
        }
        if (catalog == null) {
            setter.accept(null);
            holder.warn("无效" + topic + "：" + catalogCode);
            return true;
        } else {
            if (!Objects.equals(getter.get(), catalog)) {
                if (!Hibernate.isInitialized(catalog)) {
                    catalog = getCompanyVendorService().findCatalogByCode(catalogCode);
                }
                setter.accept(catalog);
                holder.info(topic + "修改为: " + catalog.getName());
                return true;
            }
        }
        return false;
    }

    /**
     * 同步供应商
     *
     * @param company 要同步的供应商企业
     * @param holder  状态输出
     * @return 是否更新了供应商信息
     */
    public boolean syncVendor(Company company, MessageHolder holder) {
        CompanyVendor companyVendor = getCompanyVendorService().findByCompany(company);
        if (companyVendor == null) {
            holder.warn("供应商未创建, 如需要请手动创建.");
            return false;
        }

        // 检索相关项
        List<CompanyVendorEntity> entities = getCompanyVendorEntityService().findAllByVendor(companyVendor);
        if (entities.isEmpty()) {
            holder.error("供应商关联任何相关项");
            return false;
        }

        boolean updated = false;
        boolean companyModified = false;

        // 更新相关项
        for (CompanyVendorEntity entity : entities) {
            if (!StringUtils.hasText(entity.getCode())) {
                holder.warn("相关项：" + entity.getCode() + " 无效，跳过");
                continue;
            }
            if (applyEntityDetail(entity, repository.findVendorByVendCode(entity.getCode()), holder)) {
                entity = getCompanyVendorEntityService().save(entity);
            }
            if (updateCompanyNameAndAbbNameByVendorEntity(company, entity, holder)) {
                companyModified = true;
            }
        }

        if (companyModified) {
            company = getCompanyService().save(company);
            updated = true;
        }

        // 更新供应商的开发日期
        if (updateVendorDevelopDate(companyVendor, entities, holder)) {
            companyVendor = getCompanyVendorService().save(companyVendor);
            updated = true;
        }

        // 同步供应商关联的合同
        for (CompanyVendorEntity entity : entities) {
            if (getContractCtx().syncByVendorEntity(companyVendor, entity, holder)) {
                updated = true;
            }
        }
        return updated;
    }

    private boolean updateCompanyNameAndAbbNameByVendorEntity(Company company, CompanyVendorEntity entity, MessageHolder holder) {
        CompanyService companyService = getCompanyService();
        if (company == null) {
            return false;
        }
        if (!Hibernate.isInitialized(company)) {
            company = companyService.findById(company.getId());
        }
        boolean modified = false;
        CompanyCtx companyCtx = getCompanyCtx();
        if (companyCtx.updateCompanyNameIfAbsent(company, entity.getName(), holder)) {
            modified = true;
        }
        if (companyCtx.updateCompanyAbbNameIfAbsent(company, entity.getAbbName(), holder)) {
            modified = true;
        }
        return modified;
    }

    private boolean updateVendorDevelopDate(CompanyVendor companyVendor, List<CompanyVendorEntity> entities, MessageHolder holder) {
        LocalDate developDate = null;
        for (CompanyVendorEntity entity : entities) {
            // 取最早的开发日期
            if (developDate == null || entity.getDevelopDate().isBefore(developDate)) {
                developDate = entity.getDevelopDate();
            }
        }
        return updateLocalDate(companyVendor::getDevelopDate, companyVendor::setDevelopDate, developDate, holder, "开发日期");
    }

    public CompanyVendorEntity findOrCreateByCode(String venCode, MessageHolder subHolder) {
        CompanyVendorEntityService service = getCompanyVendorEntityService();
        CompanyVendorEntity entity = service.findByCode(venCode);
        if (entity == null) {
            entity = new CompanyVendorEntity();
            entity.setCode(venCode);
            entity = service.save(entity);
            subHolder.info("创建供应商相关项: " + venCode);
        }
        return entity;
    }

    private CompanyVendor createVendorByVendorEntity(CompanyVendorEntity entity, MessageHolder holder) {
        LocalDate developDate = entity.getDevelopDate();
        if (developDate == null) {
            holder.warn(entity.getName() + " 没有设置开发日期，跳过");
            return null;
        }
        // 创建发展日期从2023年1月1日后的
        LocalDate start = LocalDate.of(2023, 1, 1);
        String autoCreateAfter = getConfService().getString(AUTO_CREATE_VENDOR_AFTER);
        if (StringUtils.hasText(autoCreateAfter)) {
            start = LocalDate.parse(autoCreateAfter);
        }
        if (developDate.isBefore(start)) {
            // start 之前的不自动创建
            holder.warn(entity.getName() + " 的发展日期 " + developDate + " 是 " + start + " 之前的, 按规定不自动创建供应商, 如有需要请手动创建");
            return null;
        }

        CompanyVendor companyVendor = new CompanyVendor();
        int nextId = SpringApp.getBean(OldVersionService.class).newCompanyVendor(entity.getName());
        companyVendor.setId(nextId);
        companyVendor.setCatalog(entity.getCatalog());
        companyVendor.setDevelopDate(developDate);
        holder.info("新供应商：" + entity.getName() + "分配编号：" + nextId);
        companyVendor.setCreated(Instant.now());
        return companyVendor;
    }


    private Company findOrCreateCompanyByVendorEntity(CompanyVendorEntity entity, MessageHolder holder) {
        String name = entity.getName();
        String abbName = entity.getAbbName();
        return getCompanyCtx().findOrCreateByNameOrAbbName(name, abbName, entity.getDevelopDate(), holder);
    }

    public CompanyVendorEntity save(CompanyVendorEntity entity) {
        return getCompanyVendorEntityService().save(entity);
    }


}
