package com.ecep.contract.vm;

import java.io.File;
import java.time.LocalDateTime;
import java.util.Objects;

import org.springframework.util.StringUtils;

import com.ecep.contract.model.Contract;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.Project;
import com.ecep.contract.model.ProjectCost;
import com.ecep.contract.util.NumberUtils;

import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleFloatProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@EqualsAndHashCode(callSuper = false)
public class ProjectCostViewModel extends IdentityViewModel<ProjectCost> implements ProjectBasedViewModel {
    /**
     * 合同对象
     */
    SimpleObjectProperty<Contract> contract = new SimpleObjectProperty<>();
    /**
     * 项目对象
     */
    SimpleObjectProperty<Project> project = new SimpleObjectProperty<>();
    /**
     * 申请日期
     */
    private SimpleObjectProperty<LocalDateTime> applyTime = new SimpleObjectProperty<>();
    /**
     * 申请人
     */
    private SimpleObjectProperty<Employee> applicant = new SimpleObjectProperty<>();
    /**
     * 审核时间
     */
    private SimpleObjectProperty<LocalDateTime> authorizationTime = new SimpleObjectProperty<>();
    /**
     * 审核文件
     */
    private SimpleObjectProperty<File> authorizationFile = new SimpleObjectProperty<>();
    /**
     * 审核人
     */
    private SimpleObjectProperty<Employee> authorizer = new SimpleObjectProperty<>();
    /**
     * 是否是标准合同文本
     */
    SimpleBooleanProperty standardPayWay = new SimpleBooleanProperty();
    /**
     * 是否是标准付款方式
     */
    SimpleBooleanProperty standardContractText = new SimpleBooleanProperty();
    /**
     * 非标准付款方式文本
     */
    SimpleStringProperty noStandardPayWayText = new SimpleStringProperty();
    /**
     * 非标准合同文本
     */
    SimpleStringProperty noStandardContractText = new SimpleStringProperty();
    /**
     * 印花税
     */
    SimpleFloatProperty stampTax = new SimpleFloatProperty();
    /**
     * 印花税金额
     */
    SimpleFloatProperty stampTaxFee = new SimpleFloatProperty();
    /**
     * 现场位置费
     */
    SimpleFloatProperty onSiteServiceFee = new SimpleFloatProperty();
    /**
     * 装配服务费
     */
    SimpleFloatProperty assemblyServiceFee = new SimpleFloatProperty();
    /**
     * 技术服务费
     */
    SimpleFloatProperty technicalServiceFee = new SimpleFloatProperty();
    /**
     * 投标服务费
     */
    SimpleFloatProperty bidServiceFee = new SimpleFloatProperty();
    /**
     * 运费
     */
    SimpleFloatProperty freightCost = new SimpleFloatProperty();
    /**
     * 保函费
     */
    SimpleFloatProperty guaranteeLetterFee = new SimpleFloatProperty();
    /**
     * 营业税及附加费
     */
    SimpleFloatProperty taxAndSurcharges = new SimpleFloatProperty();
    /**
     * 营业税及附加费金额
     */
    SimpleFloatProperty taxAndSurchargesFee = new SimpleFloatProperty();

    /**
     * 含税进项总金额
     */
    SimpleDoubleProperty inTaxAmount = new SimpleDoubleProperty();
    /**
     * 不含税进项总金额
     */
    SimpleDoubleProperty inExclusiveTaxAmount = new SimpleDoubleProperty();
    /**
     * 含税出项总金额
     */
    SimpleDoubleProperty outTaxAmount = new SimpleDoubleProperty();
    /**
     * 不含税出项总金额
     */
    SimpleDoubleProperty outExclusiveTaxAmount = new SimpleDoubleProperty();
    /**
     * 毛利率
     */
    SimpleDoubleProperty grossProfitMargin = new SimpleDoubleProperty();
    /**
     * 版本号
     */
    SimpleIntegerProperty version = new SimpleIntegerProperty();

    /**
     * 是否导入锁定，导入锁定后不允许导入
     */
    SimpleBooleanProperty importLock = new SimpleBooleanProperty(false);

    /**
     * 说明、注释
     */
    private SimpleStringProperty description = new SimpleStringProperty();

    @Override
    protected void updateFrom(ProjectCost v) {
        super.updateFrom(v);
        getContract().set(v.getContract());
        getProject().set(v.getProject());
        getApplicant().set(v.getApplicant());
        getApplyTime().set(v.getApplyTime());
        getAuthorizer().set(v.getAuthorizer());
        getAuthorizationTime().set(v.getAuthorizationTime());

        if (StringUtils.hasText(v.getAuthorizationFile())) {
            File file = new File(v.getAuthorizationFile());
            getAuthorizationFile().set(file);
        } else {
            getAuthorizationFile().set(null);
        }

        getStandardPayWay().set(v.isStandardPayWay());
        getStandardContractText().set(v.isStandardContractText());
        getNoStandardPayWayText().set(v.getNoStandardPayWayText());
        getNoStandardContractText().set(v.getNoStandardContractText());
        getStampTax().set(v.getStampTax());
        getStampTaxFee().set(v.getStampTaxFee());
        getOnSiteServiceFee().set(v.getOnSiteServiceFee());
        getAssemblyServiceFee().set(v.getAssemblyServiceFee());
        getTechnicalServiceFee().set(v.getTechnicalServiceFee());
        getBidServiceFee().set(v.getBidServiceFee());
        getFreightCost().set(v.getFreightCost());
        getGuaranteeLetterFee().set(v.getGuaranteeLetterFee());
        getTaxAndSurcharges().set(v.getTaxAndSurcharges());
        getTaxAndSurchargesFee().set(v.getTaxAndSurchargesFee());
        getInTaxAmount().set(v.getInTaxAmount());
        getInExclusiveTaxAmount().set(v.getInExclusiveTaxAmount());
        getOutTaxAmount().set(v.getOutTaxAmount());
        getOutExclusiveTaxAmount().set(v.getOutExclusiveTaxAmount());
        getGrossProfitMargin().set(v.getGrossProfitMargin());
        getVersion().set(v.getVersion());
        getDescription().set(v.getDescription());
        getImportLock().set(v.isImportLock());
    }

    @Override
    public boolean copyTo(ProjectCost v) {
        boolean modified = super.copyTo(v);
        if (!Objects.equals(contract.get(), v.getContract())) {
            v.setContract(contract.get());
            modified = true;
        }
        if (!Objects.equals(project.get(), v.getProject())) {
            v.setProject(project.get());
            modified = true;
        }

        if (!Objects.equals(applicant.get(), v.getApplicant())) {
            v.setApplicant(applicant.get());
            modified = true;
        }
        if (!Objects.equals(applyTime.get(), v.getApplyTime())) {
            v.setApplyTime(applyTime.get());
            modified = true;
        }
        if (!Objects.equals(authorizer.get(), v.getAuthorizer())) {
            v.setAuthorizer(authorizer.get());
            modified = true;
        }
        if (!Objects.equals(authorizationTime.get(), v.getAuthorizationTime())) {
            v.setAuthorizationTime(authorizationTime.get());
            modified = true;
        }

        {

            File file = null;
            if (StringUtils.hasText(v.getAuthorizationFile())) {
                file = new File(v.getAuthorizationFile());
            }
            if (!Objects.equals(authorizationFile.get(), file)) {
                v.setAuthorizationFile(authorizationFile.get() == null ? null : authorizationFile.get().getAbsolutePath());
                modified = true;
            }
        }

        if (!Objects.equals(standardPayWay.get(), v.isStandardPayWay())) {
            v.setStandardPayWay(standardPayWay.get());
            modified = true;
        }
        if (!Objects.equals(standardContractText.get(), v.isStandardContractText())) {
            v.setStandardContractText(standardContractText.get());
            modified = true;
        }
        if (!Objects.equals(noStandardPayWayText.get(), v.getNoStandardPayWayText())) {
            v.setNoStandardPayWayText(noStandardPayWayText.get());
            modified = true;
        }
        if (!Objects.equals(noStandardContractText.get(), v.getNoStandardContractText())) {
            v.setNoStandardContractText(noStandardContractText.get());
            modified = true;
        }
        if (!NumberUtils.equals(stampTax.get(), v.getStampTax())) {
            v.setStampTax(stampTax.get());
            modified = true;
        }
        if (!NumberUtils.equals(stampTaxFee.get(), v.getStampTaxFee())) {
            v.setStampTaxFee(stampTaxFee.get());
            modified = true;
        }
        if (!NumberUtils.equals(onSiteServiceFee.get(), v.getOnSiteServiceFee())) {
            v.setOnSiteServiceFee(onSiteServiceFee.get());
            modified = true;
        }
        if (!NumberUtils.equals(assemblyServiceFee.get(), v.getAssemblyServiceFee())) {
            v.setAssemblyServiceFee(assemblyServiceFee.get());
            modified = true;
        }
        if (!NumberUtils.equals(technicalServiceFee.get(), v.getTechnicalServiceFee())) {
            v.setTechnicalServiceFee(technicalServiceFee.get());
            modified = true;
        }
        if (!NumberUtils.equals(bidServiceFee.get(), v.getBidServiceFee())) {
            v.setBidServiceFee(bidServiceFee.get());
            modified = true;
        }
        if (!NumberUtils.equals(freightCost.get(), v.getFreightCost())) {
            v.setFreightCost(freightCost.get());
            modified = true;
        }
        if (!NumberUtils.equals(guaranteeLetterFee.get(), v.getGuaranteeLetterFee())) {
            v.setGuaranteeLetterFee(guaranteeLetterFee.get());
            modified = true;
        }
        if (!NumberUtils.equals(taxAndSurcharges.get(), v.getTaxAndSurcharges())) {
            v.setTaxAndSurcharges(taxAndSurcharges.get());
            modified = true;
        }
        if (!NumberUtils.equals(taxAndSurchargesFee.get(), v.getTaxAndSurchargesFee())) {
            v.setTaxAndSurchargesFee(taxAndSurchargesFee.get());
            modified = true;
        }

        if (!NumberUtils.equals(inTaxAmount.get(), v.getInTaxAmount())) {
            v.setInTaxAmount(inTaxAmount.get());
            modified = true;
        }
        if (!NumberUtils.equals(inExclusiveTaxAmount.get(), v.getInExclusiveTaxAmount())) {
            v.setInExclusiveTaxAmount(inExclusiveTaxAmount.get());
            modified = true;
        }
        if (!NumberUtils.equals(outTaxAmount.get(), v.getOutTaxAmount())) {
            v.setOutTaxAmount(outTaxAmount.get());
            modified = true;
        }
        if (!NumberUtils.equals(outExclusiveTaxAmount.get(), v.getOutExclusiveTaxAmount())) {
            v.setOutExclusiveTaxAmount(outExclusiveTaxAmount.get());
            modified = true;
        }
        if (!NumberUtils.equals(grossProfitMargin.get(), v.getGrossProfitMargin())) {
            v.setGrossProfitMargin(grossProfitMargin.get());
            modified = true;
        }
        if (!NumberUtils.equals(version.get(), v.getVersion())) {
            v.setVersion(version.get());
            modified = true;
        }
        if (!Objects.equals(description.get(), v.getDescription())) {
            v.setDescription(description.get());
            modified = true;
        }
        if (!Objects.equals(importLock.get(), v.isImportLock())) {
            v.setImportLock(importLock.get());
            modified = true;
        }
        return modified;
    }

    public static ProjectCostViewModel from(ProjectCost projectCost) {
        ProjectCostViewModel viewModel = new ProjectCostViewModel();
        viewModel.update(projectCost);
        return viewModel;
    }

    public void updateGrossProfitMargin() {
        double amount = getInExclusiveTaxAmount().get();
        if (amount == 0) {
            getGrossProfitMargin().set(0);
            return;
        }
        double grossProfit = amount - getOutExclusiveTaxAmount().get() - getStampTaxFee().get() - getTaxAndSurchargesFee().get();
        getGrossProfitMargin().set(grossProfit * 100 / amount);
    }

    /**
     * 根据印花税税率更新印花税税费
     */
    public void updateStampTaxFee() {
        getStampTaxFee().set((float) (getInTaxAmount().get() * getStampTax().get() / 100));
        updateGrossProfitMargin();
    }

    public void updateTaxAndSurchargesFee() {
        double value = (getInTaxAmount().get() - getInExclusiveTaxAmount().get()) - (getOutTaxAmount().get() - getOutExclusiveTaxAmount().get());
        getTaxAndSurchargesFee().set((float) (value * getTaxAndSurcharges().get() / 100));
        updateGrossProfitMargin();
    }
}
