<?php

/**
 * v2 账单模块
 */
namespace app\em\controller;
use app\admin\controller\Base;
use app\em\model\EmInvoice;
use app\em\model\EmInvoiceUseage;
use app\em\model\EmPayment;
use app\em\model\EmPaymentInvoice;
use app\em\model\EmPaymentInvoiceBalance;
use app\em\model\EmSettle;
use app\em\model\EmSettleInvoice;
use app\em\model\EmSettleInvoiceBalance;
use app\em\model\UseageDetail;
use think\facade\Request;
use think\facade\Session;


class Invoice extends Base
{
    //账单列表
    public function index(){
        $map=[];
        //权限检测
        $user = Session::get('user');
        if(!$user['is_admin']){
            $permissionData=check_data();
            if($permissionData){
                $map[]=$permissionData;
            }
        }
        $search_text = Request::get('search_text');
        $search_type = Request::get('search_type');
        if($search_text){
            switch ($search_type) {
                case '1':
                    $this->assign('search_text',$search_text);
                    $map[]=['inv.invoice_id','like',"%$search_text%"];
                    $this->assign('search_type',$search_type);
                    break;
                case '2':
                    $this->assign('search_text',$search_text);
                    $map[]=['station.station_name','like',"%$search_text%"];
                    $this->assign('search_type',$search_type);
                    break;
                case '3':
                    $this->assign('search_text',$search_text);
                    $map[]=['em.em_numb','like',"%$search_text%"];
                    $this->assign('search_type',$search_type);
                    break;
            }
        }else{
            $this->assign('search_type','');
            $this->assign('search_text','');
        }
        $page =Request::param('page')?Request::param('page'):1;
        $limit = Request::param('limit')?Request::param('limit'):10;

        $emInvModel = new EmInvoice;
        $data = $emInvModel->getInvoiceList($map,$page,$limit);
        foreach ( $data as $key => &$v) {
            $v['status']=parseStatus($v['status']);
        }
        $InvoiceCount = $emInvModel->getInvoiceCount($map);
        if(Request::param('page')){
            return ['code'=>0,'msg'=>'','count'=>$InvoiceCount,'data'=>$data];
        }

        return $this->fetch();
    }

    //查看账单信息
    public function detail(){
        $inv_id = Request::param('id');

        $invInfo = (new EmInvoice)->getInvoiceDetail($inv_id);
        $this->assign('inv',$invInfo);
        return $this->fetch();
    }

    //创建一个账单
    public function createInvoice($useage_id){
        $um =  (new \app\em\model\Useage)->getEmInfoByUseageId($useage_id)->toArray();
        return $this->create($um);
    }

    //创建账单
    public function create($um){
        /// 如果是普通表 则
        if($um['pricing_type'] == 1){
            return $this->createInvoiceStdType($um);
        } else if($um['pricing_type'] == 2){
            return $this->createInvoiceSpecialType($um);
        }
    }

    /**
     * 生成账单号
     * @return string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function getInvoiceId(){
        $inv = EmInvoice::field('id')->order('id desc,create_time desc')->find();
        if(!$inv) $id = 1;
        else $id = $inv->id + 1;
        return "ZD".date('Ymd').zero($id);
    }

    //普通读表生成账单
    public function createInvoiceStdType($uData){
        $inv = new EmInvoice();
        $inv->type = 4;
        $inv->rate = $uData['rate'];
        $inv->repo_numb = round(($uData['current_sum_numb'] - $uData['last_sum_numb']) * $uData['rate'],3);
        $inv->payment_amount = $inv->payment_balance = $inv->repo_numb * $uData['pay_price'];
        //结算信息
        $inv->settle_amount = $inv->settle_balance = $inv->repo_numb * $uData['settle_price'];
        $inv->status = '000';
        $inv->invoice_id = $this->getInvoiceId();

        //获取账户ID
        $inv->account_id = (new Account())->getAccountId($uData['em_id']);

        //保存 并且更新抄表单与账单关联表
        if($inv->save()){
            $eiu = new EmInvoiceUseage();
            $eiu->invoice_id = $inv->invoice_id;
            $eiu->useage_id = $uData['useage_id'];
            $eiu->save();
        }

        //更新电表账户
        $useage = \app\em\model\Useage::get(['useage_id' => $uData['useage_id']]);

        $account = new Account();
        $account->updateAmount($useage->em_id,$inv->payment_amount,0);

        return  $inv;
    }

    //峰谷表生成账单
    public function createInvoiceSpecialType($uData){
        $inv = new EmInvoice();
        $inv->type = 1;
        $inv->rate = $uData['rate'];

        //获取峰谷表抄表明细
        $uds = UseageDetail::where(['useage_id'=>$uData['useage_id']])->select()->toArray();

        //计算总价信息
        //需要计算4个属性 各分段上一次 档次 repo amount
        $last_numb = 0;
        $curr_numb = 0;
        $amount = 0;
        $repo_numb = 0;
        foreach ($uds as $v){
            $last_numb += $v['last_numb'];
            $curr_numb += $v['current_numb'];
            $amount += (int)($v['current_numb'] - $v['last_numb']) * $v['price'];
            $repo_numb += (int)($v['current_numb'] - $v['last_numb']);
        }

        //曝移动电量
        $inv->repo_numb = ($curr_numb - $last_numb) * $uData['rate'];

        //缴费信息
        $inv->payment_amount = $inv->payment_balance = $amount * $uData['rate'];
        //结算信息
        $inv->settle_amount = $inv->settle_balance = $repo_numb * $uData['settle_price'];
        $inv->status = '000';
        $inv->invoice_id = $this->getInvoiceId();

        $inv->account_id = (new Account())->getAccountId($uData['em_id']);

        //更新抄表单的status
        $useage =  \app\em\model\Useage::get(['useage_id'=>$uData['useage_id']]);
        $useage->status = 2;
        $useage->save();

        $inv->cert_id = $useage->photo_id;

        //保存 并且更新抄表单与账单关联表
        if($inv->save()){
            $eiu = new EmInvoiceUseage();
            $eiu->invoice_id = $inv->invoice_id;
            $eiu->useage_id = $uData['useage_id'];
            $eiu->save();
        }

        return  $inv;
    }

    public function updatePayment(){
        $data = Request::param();

        $inv = EmInvoice::get(['id'=>$data['id']]);

        if(!$inv) return json(['status'=>0,'message'=>'不存在抄表单ID,无法更新缴费金额']);

        if($data['amount'] > 0 && $inv->is_add_condition != 1){
            $inv->payment_amount = $data['amount'];
            $inv->payment_balance = $data['amount'];
            $inv->is_add_condition = 1;
        }

        if($inv->save()){
            return json(['status'=>1,'message'=>'缴费金额已经更新']);
        }
    }

    //账单合并列表
    public function mergeList(){
        $ids = Request::param('ids');

        $idsArr = [];
        if(!empty($ids)){
            $idsArr= explode('_',$ids);
        }

        $data = (new EmInvoice)->getListByInvIds($idsArr);

        $payment_amount = 0;
        $settle_amount = 0;
        foreach ($data as $v){
            $v->settle_amount = $v->settle_amount ?:0;
            $payment_amount += $v->payment_amount;
            $settle_amount += $v->settle_amount;
        }
        $this->assign('data',$data);
        $this->assign('payment_amount',$payment_amount);
        $this->assign('settle_amount',$settle_amount);
        return $this->fetch('merge_list');
    }

    /**
     * 账单触发销账,invoice_id 1:n payment_id
     * @param $account_id
     * @param $invoice_id
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @return mixed
     */
    public function writeOffFromInvoice($invoice_id,$account_id){
         //获取账单对象
        $invoice = EmInvoice::field('id,invoice_id,payment_amount,payment_balance')
            ->where('invoice_id','=',$invoice_id)->find();

        //查询关系表中与当前invoice_id相关联的payment_id
        $model = new EmPaymentInvoice;
        $payments = $model->alias('epi')->field('epi.payment_id')
            ->leftJoin(['em_payment'=>'ep'],'epi.payment_id = ep.payment_id')
            ->leftJoin(['em_payment_invoice_balance'=>'epib'],'epib.invoice_id=epi.invoice_id')
            ->where('epib.balance','>',0)
            ->where('epi.invoice_id','=',$invoice_id)->select();
        //如果没有找到记录 证明并没有形成对应关系
        if($payments->isEmpty()) {

            //查询是否有未缴费的缴费单存在
            $payments = EmPayment::field('payment_id')->where('account_id','=',$account_id)
                ->where('balance','neq',0)
                ->order('payment_id asc')
                ->select();
            if($payments->isEmpty()) {
                return '没有销账的缴费单!';
            }
        }
        $paymentIds = [];
        foreach ($payments as $payment){
            $paymentIds[] = $payment->payment_id;
        }
        $invsIds = [
            'invoice_id' => $invoice->invoice_id
        ];
        //开始销账
        return $this->writeOff($paymentIds,$invsIds);
    }

    //从缴费单消账单
    public function writeOffFromPayment($account_id,$payment_id){
        //获取缴费单对象
        $payment = EmPayment::where('payment_id','=',$payment_id)->find();

        //获取关联的账单对象
        $invs =  (new EmInvoice())->alias('ei')->field('ei.invoice_id')
            ->leftJoin(['em_payment_invoice'=>'epi'],'epi.invoice_id = ei.invoice_id')
            ->where('epi.payment_id','=',$payment_id)
            ->where('ei.payment_balance','neq',0)
            ->order('ei.invoice_id asc')
            ->select();

        $invsArr = [];
        //更新缴费单状态
        if($invs->isEmpty()){
            $payment->status = 4;
            $payment->save();
            return '审核成功';
        } else {
            foreach ($invs as $inv){
                $invsArr[] = $inv->invoice_id;
            }
        }

        //查询可消的额度
        $payments_balance = (new EmInvoice)->where('invoice_id','in',$invsArr)->sum('payment_balance');

        //如果可以完全销账 则继续销账
        if($payment->balance > $payments_balance){
            $invs = (new EmInvoice())->field('invoice_id')
                ->where('account_id','=',$account_id)
                ->where('payment_balance','neq',0)
                ->order('invoice_id asc')
                ->select();
            if(!$invs->isEmpty()) {
                foreach ($invs as $inv){
                    $invsArr[] = $inv->invoice_id;
                }
            }
        }

        $paymentIds[] = $payment->payment_id;

        //处理账户金额
        return $this->writeOff($paymentIds,$invsArr);
    }

    /**
     * @param $account_id
     * @param $invoiceIds
     * @param $paymentIds
     * @return mixed
     */
    private function writeOff($paymentIds,$invoiceIds){
        //获取可销账缴费单
        $payments = EmPayment::where('payment_id','in',$paymentIds)->select();

        //获取可销账账单
        $invs = EmInvoice::where('invoice_id','in',$invoiceIds)->select();

        $result = 0;
        foreach ($payments as $key => $payment){
            if($payment->balance == 0)
                continue;
            foreach ($invs as $index => $inv) {
                $balanceMode = new EmPaymentInvoiceBalance();
                $balanceMode->payment_id = $payment->payment_id;

                if ($inv->payment_balance == 0)
                    continue;
                $balanceMode->invoice_id = $inv->invoice_id;

                //如果该缴费单可以完全消除当前账单额度
                if ($payment->balance >= $inv->payment_balance) {
                    //单笔销账多少
                    $balanceMode->balance = $inv->payment_balance;

                    //缴费额度变化
                    if(($payment->balance - $inv->payment_balance) == 0){
                        $payment->status = 4;
                    } else {
                        $payment->status = 4; //缴费部分销账
                    }
                    $payment->balance = $payment->balance - $inv->payment_balance;

                    //账单额度变化
                    $inv->payment_balance = 0;
                    //更新账户status 首字母 = 2
                    $inv->status = setInvoiceStatus($inv->status, 2);

                } else {
                    //单笔销账多少
                    $balanceMode->balance = $payment->balance;

                    //账单额度变化
                    $inv->status = setInvoiceStatus($inv->status, 1);
                    $inv->payment_balance = $inv->payment_balance - $payment->balance;
                    //缴费额度变化
                    $payment->balance = 0;
                    $payment->status = 4; //缴费已经完全销账
                }
                $model = new EmPaymentInvoice();
                if(!$model->where(['payment_id'=>$payment->payment_id,'invoice_id'=>$inv->invoice_id])->find()){
                    $model->payment_id = $payment->payment_id;
                    $model->invoice_id = $inv->invoice_id;
                    $model->save();
                }
                $result++;

                //更新账单状态
                $inv->save();
                //todo::history; 保存历史记录
                $invData = $inv->toArray();
                $invData['id'] = null;
                $invData['create_time'] = strtotime($invData['create_time']);
                $invData['update_time'] = strtotime($invData['update_time']);

                //EmInvoiceHistory::create($invData);
                unset($invs[$index]);  //从结果集中去掉无效的数据

                //更新状态
                $payment->save();
                //todo::history;保存历史记录
                $payData = $payment->toArray();
                $payData['id'] = null;
                $payData['create_time'] = strtotime($payData['create_time']);
                $payData['update_time'] = strtotime($payData['update_time']);
                $payData['pay_date'] = strtotime($payData['pay_date']);


                //EmPaymentHistory::create($payData);
                unset($payments[$key]);
                $balanceMode->isUpdate(false)->save();
            }
        }
        $msg = $result == 0 ? '已审核,没有可销账的账单.' : '已审核,成功销账 '.$result.' 笔账单.';
        return $msg;
    }

    public function writeOffFromSettle($account_id,$settle_id){
        //获取缴费单对象
        $settle = EmSettle::where('settle_id','=',$settle_id)->find();

        //获取关联的账单对象
        $invs =  (new EmInvoice())->alias('ei')->field('ei.invoice_id')
            ->leftJoin(['em_settle_invoice'=>'esi'],'esi.invoice_id = ei.invoice_id')
            ->where('esi.settle_id','=',$settle_id)
            ->where('ei.settle_balance','neq',0)
            ->order('ei.invoice_id asc')
            ->select();
        $invsArr = [];
        if(!$invs->isEmpty()) {
            foreach ($invs as $inv){
                $invsArr[] = $inv->invoice_id;
            }
        }

        //查询可消的额度
        $settles_balance = (new EmInvoice)->where('invoice_id','in',$invsArr)->sum('settle_balance');

        //如果可以完全销账 则继续销账
        if($settle->balance > $settles_balance){
            $invs = (new EmInvoice())->field('invoice_id')
                ->where('account_id','=',$account_id)
                ->where('settle_balance','neq',0)
                ->order('invoice_id asc')
                ->select();
            if(!$invs->isEmpty()) {
                foreach ($invs as $inv){
                    $invsArr[] = $inv->invoice_id;
                }
            }
        }

        $settleIds[] = $settle->settle_id;

        //处理账户金额
        return $this->writeOffSettle($settleIds,$invsArr);
    }

    private function writeOffSettle($settleIds,$invoiceIds,$associate = false){
        //获取可销账结算单
        $settles = EmSettle::where('settle_id','in',$settleIds)->select();

        //获取可销账账单
        $invs = EmInvoice::where('invoice_id','in',$invoiceIds)->select();

        $result = 0;
        foreach ($settles as $key => $settle){
            if($settle->balance == 0)
                continue;
            foreach ($invs as $index => $inv) {
                $balanceMode = new EmSettleInvoiceBalance();
                $balanceMode->settle_id = $settle->settle_id;

                if ($inv->settle_balance == 0)
                    continue;
                $balanceMode->invoice_id = $inv->invoice_id;

                //如果该结算单可以完全消除当前账单额度
                if ($settle->balance >= $inv->settle_balance) {
                    //单笔销账多少
                    $balanceMode->balance = $inv->settle_balance;

                    //结算额度变化
                    if(($settle->balance - $inv->settle_balance) == 0){
                        $settle->status = 4;
                    } else {
                        $settle->status = 4; //结算部分销账
                    }
                    $settle->balance = $settle->balance - $inv->settle_balance;

                    //账单额度变化
                    $inv->settle_balance = 0;
                    //更新账户status 首字母 = 2
                    $inv->status = setInvoiceStatus($inv->status, 2,1);

                } else {
                    //单笔销账多少
                    $balanceMode->balance = $settle->balance;

                    //账单额度变化
                    $inv->status = setInvoiceStatus($inv->status, 1,1);
                    $inv->settle_balance = $inv->settle_balance - $settle->balance;
                    //结算额度变化
                    $settle->balance = 0;
                    $settle->status = 3; //结算已经完全销账
                }

                if($associate == true){
                    $model = new EmSettleInvoice();
                    $model->settle_id = $settle->settle_id;
                    $model->invoice_id = $inv->invoice_id;
                    $model->save();
                }
                $result++;

                //更新账单状态
                $inv->save();
                //todo::history; 保存历史记录
                $invData = $inv->toArray();
                $invData['id'] = null;
                $invData['create_time'] = strtotime($invData['create_time']);
                $invData['update_time'] = strtotime($invData['update_time']);

                //EmInvoiceHistory::create($invData);
                unset($invs[$index]);  //从结果集中去掉无效的数据

                //更新状态
                $settle->save();
                //todo::history;保存历史记录
                $payData = $settle->toArray();
                $payData['id'] = null;
                $payData['create_time'] = strtotime($payData['create_time']);
                $payData['update_time'] = strtotime($payData['update_time']);
                $payData['settle_date'] = strtotime($payData['settle_date']);


                //EmSettleHistory::create($payData);
                unset($settles[$key]);
                $balanceMode->isUpdate(false)->save();
            }
        }
        $msg = $result == 0 ? '没有结算成功' : '成功结算: '.$result.'笔';
        return $msg;
    }

}