<?php
/* @desc；费用项目处理
 * @author:gilbert
 * @date:2016-06-28
 */
class Service_OtherFeeProcess {
    //属性类型
    static $attributeType = array('1'=>'固定值','2'=>'无序范围值','3'=>'有序范围值','4'=>'数据表');
    protected $_param = null;//添加保险项目的数据
    protected $_error = array();//错误信息
    protected $_date = null;
    protected $_warehouseId = null;
    protected $_code = null;

    public function __construct() {
        $this->_date = date('Y-m-d H:i:s');
    }

    protected function setParam( $param = array() ) {
        $this->_param = $this->trimParam( $param );

    }

    protected function trimParam( $param ) {
        if( is_scalar($param) ) {
            return trim($param);
        } else {
            foreach( $param as $key=>$value) {
                if( is_scalar($value) ) {
                    $param[$key] = trim($value);
                } else {
                    $param[$key] = $this->trimParam( $value );
                }
            }
            return $param;
        }
    }

    protected function setWarehouse( $warehouse ) {
        $this->_warehouseId = trim( $warehouse );
    }

    protected function setCode( $code ) {
        $this->_code = trim( $code );
    }

    //检查数据是否为空、null、未设置
    protected function checkParam( $param,$columns ) {
        $passed = true;
        foreach( $columns as $key ) {
            if( isset( $param[$key] )) {
                if( is_null( $param[$key] ) ) {
                    $passed = false;
                    break;
                } else if( is_scalar( $param[$key] ) ) {
                    if( $param[$key] === '') {
                        $passed = false;
                        break;
                    }
                }else if( is_array( $param[$key])) {
                    $passed = $this->checkParam( $param[$key], array_keys( $param[$key] ) );
                    if( !$passed )
                        break;
                }
            } else {
                $passed = false;
                break;
            }
        }
        return $passed;
    }

    public function getError() {
        return $this->_error;
    }


    protected function getConfig( $warehouseId, $code, $index = array() ) {
        $config = array();
        if( empty($warehouseId) || empty($code))
            return false;

        $codes = array();
        if( is_scalar( $code ) )
            $codes = array( $code );
        else
            $codes = $code;

        $column = array('ofa_id','ofa_name','ofa_variable','ofa_value_type','fee_id');

        foreach( $codes as $code ) {
            $item = Service_OtherFee::getByField( $code, 'fee_code');
            if( empty( $item ) || $item['warehouse_id'] != $warehouseId ) {
                $config[ $code ] = false;
                continue;
            }

            $config[ $code ] = $item;

            $attribute = Service_OtherFeeAttribute::getByCondition(array('fee_id'=>$item['fee_id']),$column);
            if( empty( $attribute ) ){
                $config[ $code ]['attribute'] = array();
                continue;
            }

            foreach($attribute as $key=>$value){

                $config[ $code ]['attribute'][ $value['ofa_variable'] ]['ofa_name'] = $value['ofa_name'];
                $config[ $code ]['attribute'][ $value['ofa_variable'] ]['ofa_value_type'] = $value['ofa_value_type'];

                if( $value['ofa_value_type'] == 4 ) {
                    $configTable = Service_OtherFeeConfigTable::getByCondition( array('fee_id'=>$value['fee_id'],'ofa_id'=>$value['ofa_id']));
                    if( $configTable ) {
                        $columnData = $rowData = array();
                        foreach( $configTable as $k => $v ) {
                            $text = $v['ofct_ref_code'];
                            if( $v['ofct_ref_id'] ) {
                                $tmpRow = Service_OtherFeeAttribute::getByField($v['ofct_ref_id']);
                                $text = $tmpRow['ofa_variable'];
                            }
                            $columnData[$text][] = $v;
                        }
                        //行转列(数据表是的内容是列转行保存下来的)
                        $rows = count($configTable) / count($columnData);
                        $keys = array_keys($columnData);

                        $s = false;
                        if( isset( $index[ $code ][ $value['ofa_variable'] ] ) && $index[ $code ][ $value['ofa_variable'] ] !== '')
                            $s = array_search( $index[ $code ][ $value['ofa_variable'] ],$keys);

                        for( $i=0; $i<$rows; $i++ ) {
                            $tmpIndex = $s !== false ? $columnData[ $keys[$s] ][$i]['ofct_value'] : $i;
                            foreach($keys as $k=>$v) {
                                $rowData[ $tmpIndex ][$k] = $columnData[$v][$i]['ofct_value'];
                            }
                        }
                        $config[ $code ]['attribute'][ $value['ofa_variable'] ]['value'] = $rowData;
                    } else {
                        $config[ $code ]['attribute'][ $value['ofa_variable'] ]['value'] = array();
                    }

                } else {
                    $configRow = Service_OtherFeeConfig::getByCondition( array('fee_id'=>$value['fee_id'],'ofa_id'=>$value['ofa_id']));
                    if( empty($configRow) ) {
                        $config[ $code ]['attribute'][ $value['ofa_variable'] ]['value'] = array();
                        continue;
                    }

                    if( $value['ofa_value_type'] == 1 ) {
                        $config[ $code ]['attribute'][ $value['ofa_variable'] ]['value'] = $configRow[0]['ofc_value'];

                    } else if( $value['ofa_value_type'] == 2) {
                        $config[ $code ]['attribute'][ $value['ofa_variable'] ]['value'] = $configRow[0]['ofc_disordered_value'];

                    } else {
                        $config[ $code ]['attribute'][ $value['ofa_variable'] ]['value']['start'] = $configRow[0]['ofc_value_start'];
                        $config[ $code ]['attribute'][ $value['ofa_variable'] ]['value']['end'] = $configRow[0]['ofc_value_end'];
                        $config[ $code ]['attribute'][ $value['ofa_variable'] ]['value']['eqStart'] = $configRow[0]['ofc_value_eq_start'];
                        $config[ $code ]['attribute'][ $value['ofa_variable'] ]['value']['eqEnd'] = $configRow[0]['ofc_value_eq_end'];
                    }
                }
            }
        }
        return $config;

    }


    public function getAmount($warehouseId,$code,$param=array()) {
        $amount = false;
        $this->setWarehouse($warehouseId);
        $this->setCode($code);
        $this->setParam($param);
        switch( $this->_code ) {
            case 'GTI':
            case 'ODI':
            case 'OCI':
            case 'GRI':
                $amount = $this->getInsuranceAmount();
                break;
        }
        return $amount;
    }

    public function getInsuranceAmount() {
        /* 费用代码说明
         * GTI:货物运输保险
         * ODI:订单延误保险
         * OCI:订单取消保险
         * GRI:产品责任险
         */
        //amount保费 premium投保金额，detail保费明细 要注意的是，如果有错，是直接返回 初始时的 $return
        if( $this->_warehouseId === '' || $this->_code === '' ) {
            $this->_error[] = '仓库或保险为空';
            return false;
        }

        $result = $this->checkParam( $this->_param, array('insuranceRate','country','dealPrice','dealCurrency'));
        if( !$result ) {
            $this->_error[] = '费用参数不全';
            return false;
        }
        $countryId = $this->_param['country'];
        $dPrice = $this->_param['dealPrice'];
        $iRate = $this->_param['insuranceRate'];
        $dCurrency = strtoupper( $this->_param['dealCurrency'] );
        $rate = 1;

        if( $dCurrency != 'RMB') {
            $currency = Service_Currency::getByField( $dCurrency,'currency_code' );
            if( empty( $currency ) ) {
                $this->_error[] = '获取汇率失败';
                return false;
            }
            $rate = $currency['currency_rate'];
        }

        $areaCode = $this->getArea( $countryId );
        if( $areaCode == false || $areaCode === '' || is_null($areaCode)) {
            $this->_error[] = '国家未设置区域';
            return false;
        }
        //获取相关的费用代码
        $codes = $this->getInsuranceCode( $this->_code );
        //获取配置
        $config = $this->getConfig( $this->_warehouseId, $codes, array('ODI'=>array('price'=>'区域')));
        if( $config === false ) {
            $this->_error[] = '保险不可用';
            return false;
        }
        //投保金额
        $premium = sprintf( '%.2f', $dPrice * $rate * $iRate );

        $total = 0;
        $detail = array();

        foreach( $config as $code => $value ) {
            //费用代码不存在的，或没有属性的，或费用类型代码不是保险费的
            if( $value === false || empty( $value['attribute'] ) || $value['ft_code'] != 'SI') {
                $this->_error[] = '保险不可用';
                return false;
            }

            $name = $value['fee_name'];

            //判断计费类型
            if( !isset( $value['attribute']['chargeType']['value'] ) || $value['attribute']['chargeType']['value'] === '' ) {
                $this->_error[] = '费用项目['.$value['fee_name'].']未设置计费类型';
                return false;
            }

            if( $value['status'] != 1 ) {
                $detail[] = array( 'code'=>$code, 'name' => $name, 'amount' => 0, 'cost' => 0 );
                continue;
            }
            //区域收费的直接取报价表的报价
            if( $value['attribute']['chargeType']['value'] == '区域收费' ) {
                if( isset( $value['attribute']['price']['value'][$areaCode] ) ) {
                    //$tmpPrice = sprintf( '%0.2f',$value['attribute']['price']['value'][$areaCode][2] * $value['fee_discount']);
                    //配置属性时没对数据做检查的，所以这里要检查一下
                    $tmpPrice = $value['attribute']['price']['value'][$areaCode][2];
                    $cost = $value['attribute']['price']['value'][$areaCode][1];//成本
                    if( !is_numeric($tmpPrice) || !is_numeric($cost) ) {
                        $this->_error[] = '系统价格配置出错';
                        return false;
                    }
                    $tmpPrice = sprintf( '%0.2f',$tmpPrice);
                    $tmpDetail = array( 'code'=>$code, 'name' => $name, 'amount' => $tmpPrice );
                    if( isset( $this->_param['returnCost'] ) && $this->_param['returnCost'] ) {
                        $tmpDetail['cost'] = $cost;
                    }
                    $detail[] = $tmpDetail;
                    $total += $tmpPrice;
                } else {
                    $this->_error[] = '费用项目['.$value['fee_name'].']未设置区域价格';
                    return false;
                }
                //阶段收费的，费用=(投保金额/阶段金额)*阶段金额率 ，注意 投保金额/阶段金额 如果不是整数，要向上取整：2.1 => 3
            } else if( $value['attribute']['chargeType']['value'] == '阶段收费' ) {
                if( !isset( $value['attribute']['intervalAmount']['value'] )
                    || !is_numeric($value['attribute']['intervalAmount']['value'])
                    || $value['attribute']['intervalAmount']['value'] <= 0
                    || !isset( $value['attribute']['intervalRate']['value'] )
                    || !is_numeric($value['attribute']['intervalRate']['value'])
                    || $value['attribute']['intervalRate']['value'] <= 0 ) {
                    $this->_error[] = '费用项目['.$value['fee_name'].']系统设置异常';
                    return false;
                }
                $base = ceil( $premium / $value['attribute']['intervalAmount']['value'] );
                //$intervalPrice = sprintf('%.2f', $base * $value['attribute']['intervalRate']['value'] * $value['fee_discount'] );
                $intervalPrice = sprintf('%.2f', $base * $value['attribute']['intervalRate']['value'] );
                $cost = sprintf('%.2f', $premium * $value['attribute']['insuranceRate']['value']);// 成本 = 投保金额*保费费率

                $tmpDetail = array( 'code'=>$code, 'name' => $name, 'amount' => $intervalPrice );
                if( isset( $this->_param['returnCost'] ) && $this->_param['returnCost'] ) {
                    $tmpDetail['cost'] = $cost;
                }

                $detail[] =$tmpDetail;
                $total += $intervalPrice;
            }else if ($value['attribute']['chargeType']['value'] == '百分比收费') {
                if( !isset( $value['attribute']['intervalAmount']['value'] )
                    || !is_numeric($value['attribute']['intervalAmount']['value'])
                    || $value['attribute']['intervalAmount']['value'] <= 0
                    || !isset( $value['attribute']['intervalRate']['value'] )
                    || !is_numeric($value['attribute']['intervalRate']['value'])
                    || $value['attribute']['intervalRate']['value'] <= 0 ) {
                    $this->_error[] = '费用项目['.$value['fee_name'].']系统设置异常';
                    return false;
                }
                $base = sprintf('%.2f', $premium * $value['attribute']['intervalRate']['value'] * 0.01 );
                $intervalPrice = ($base > $value['attribute']['intervalAmount']['value'])?$base:sprintf('%.2f', $value['attribute']['intervalAmount']['value']);
                $detail[] = array( 'code'=>$code, 'name' => $name, 'amount' => $intervalPrice );
                $total += $intervalPrice;
            } else {
                $this->_error[] = $name.'费用项目['.$value['fee_name'].']计费类型错误';
                return false;
            }
        }

        $return = array(
            'amount' => $total,
            'premium' => $premium,
            'detail' => $detail,
            'currency' => 'RMB'
        );
        return $return;
    }

    protected function getArea( $countryId ) {
        if( $countryId ) {
            $country = Service_Country::getByField( $countryId );
            if( empty( $country ) ||  empty ( $country['country_area']) )
                return false;
            else
                return $country['country_area'];

        }
        return false;
    }

    protected function getInsuranceCode( $code ) {
        $codes = array();
        //某些保险要连带购买
        if( $code == 'ODI') {
            $codes[] = 'GTI';
        } else if( $code == 'OCI' ) {
            $codes[] = 'GTI';
            $codes[] = 'ODI';
        } else if( $code == 'GRI' ) {
            $codes[] = 'GTI';
            $codes[] = 'ODI';
            $codes[] = 'OCI';
        }
        $codes[] = $code;
        return $codes;
    }

    /* 不明白为什么要自己编造一个ut_code,不知道other_fee表fee_unit字段吗
     *
     */
    public static function getUtCode() {
        $utCode = array(
            'CANGCHU'                       => 'PCE',
            'CHAOZHI'                       => 'PCE',
            'CHAOCHANG'                     => 'PCE',
            'CAOZUO'                        => 'PCE',
            'BAOGUAN1'                      => 'PCE',
            'TIHUO'                         => 'KG',
            'YUNSHU'                        => 'KG',
            'JIANGUANYUNSHU'               => 'KG',
            'RUKU'                           => 'KG',
            'WULIUCAOZUO'                   => 'KG',
            'PIANYUAN'                      => 'PCE',
            'WULIAO'                        => 'PCE',
            'GUANLI'                        => 'PCE',
            'FBATAX'                        => 'PCE',
            'CZBGF'                         => 'PCE',
            'Elevated Risk'                => 'KG',
            'Restricted Destination'     => 'KG',
            'POD'                           => 'PCE',
            '4PX-DUTY'                     => 'PCE',
            '4PXGFXDQ'                     => 'PCE',
            '4PXPYDQ'                      => 'PCE',
            '4PXXYMDD'                     => 'PCE',
            '4PXDDBG'                      => 'PCE',
            '4PXCCCZ'                      => 'PCE',
            'SANZU'                        => 'KG',
            'DBF'                          => 'PCE',
            'BAOGUAN'                     => 'PCE',
            'BHDPDRemoteFee'             => 'PCE',
            'GFX'                          => 'KG',
            'SXZ'                          => 'KG',
            'THPIANYUAN'                  => 'PCE',
            'THFBATAX'                    => 'PCE',
        );
        return $utCode;
    }
}