<?php

/**
 * v2 结算模块
 */
namespace app\em\controller;


use app\admin\controller\Base;
use app\admin\model\ElectricMeter;
use app\em\model\EmAccount;
use app\em\model\EmCertSettle;
use app\em\model\EmInvoice;
use app\em\model\EmSettle;
use app\em\model\EmSettleInvoiceBalance;
use app\em\model\EmSettleReceipt;
use app\em\model\EmSettleInvoice;
use app\em\model\Staff;
use think\Exception;
use think\facade\Request;
use think\facade\Session;

class Settle 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');
        $settle_status = Request::get('settle_status');

        if($search_text){
            switch ($search_type) {
                case '1':
                    $this->assign('search_text',$search_text);
                    $map[]=['settle.settle_id','like',"%$search_text%"];
                    $this->assign('search_type',$search_type);
                    break;
                case '2':
                    $this->assign('search_text',$search_text);
                    $map[]=['esi.invoice_id','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;
                case '4':
                    $this->assign('search_text',$search_text);
                    $map[]=['station.station_name','like',"%$search_text%"];
                    $this->assign('search_type',$search_type);
                    break;
            }
        }else{
            $this->assign('search_type','');
            $this->assign('search_text','');
        }

        //结算状态
        if($settle_status !== ''){
            $map[]=['settle.status','=',"$settle_status"];
            $this->assign('settle_status',$settle_status);
        }else{
            $this->assign('settle_status','');
        }
        //区域
        $area_id = Request::get('area_id');
        if($area_id){
            $map[] = ['station.area_id','=',$area_id];
            $this->assign('area_id',$area_id);
        }else{
            $this->assign('area_id','');
        }

        //创建时间查询条件
        $dateStart = strtotime(Request::get('date_start'));
        $dateEnd = strtotime(Request::get('date_end'));
        //区间查询
        if( !empty($dateStart) && !empty($dateEnd) ){
            $map[] = ['settle.create_time','between',[$dateStart,$dateEnd]];
            $this->assign('date_start',Request::get('date_start'));
            $this->assign('date_end',Request::get('date_end'));
        } elseif (!empty($dateStart) && empty($dateEnd)){
            $map[] = ['settle.create_time','>',$dateStart];
            $this->assign('date_start',Request::get('date_start'));
            $this->assign('date_end','');
        } elseif (empty($dateStart) && !empty($dateEnd)){
            $map[] = ['settle.create_time','<',$dateEnd];
            $this->assign('date_end',Request::get('date_end'));
            $this->assign('date_start','');
        }else{
            $this->assign('date_start','');
            $this->assign('date_end','');
        }

        $page =Request::param('page')?Request::param('page'):1;
        $limit = Request::param('limit')?Request::param('limit'):10;
        $data = (new EmSettle())->getSettleList($map,$page,$limit);
        $PaymentCount = (new EmSettle())->getSettleCount($map);
        if(Request::param('page')){
            return ['code'=>0,'msg'=>'','count'=>$PaymentCount,'data'=>$data];
        }
        $region=new ElectricMeter();
        $this->assign('regions',getTree($region->regions()));
        return $this->fetch();
    }
    
    public function createAll(){
        $ids = Request::param('ids');

        //todo:优先锁定ids的状态,不能再次生成结算单
        //首先查询这些账单是否具备生成条件
        $eiModel = new EmInvoice();
        $invs = $eiModel->where('settle_balance','neq',0)
                        ->where(['invoice_id'=>$ids])->order('invoice_id asc')->select();

        if($invs->isEmpty()) return json(['status'=>0,'message'=>'没有满足条件的账单']);
        //过滤不可以生成结算单的账单ID
        $idsArr = [];
        foreach ($invs as $inv){
            //未生成结算或已挂起
            if($inv->settle_amount >= $inv->settle_balance){
                //是否已挂起
                $settleField = EmSettleInvoice::field('settle_id')
                                                ->where('invoice_id','=',$inv->invoice_id)
                                                ->order('create_time desc')->find();
                if($settleField){
                    //找到关联的结算单
                    $settle = EmSettle::where('settle_id','=',$settleField->settle_id)->find();

                    //如果结算单并未结算
                    if($settle->amount == 0){
                        $message = '账单号: '.$inv->invoice_id.' 已经挂起,无法生成结算单';
                        return json(['status'=>0,'message'=>$message]);
                    } else {
                        $idsArr[] = $inv->invoice_id;
                    }
                } else {
                    $idsArr[] = $inv->invoice_id;
                }
            }
        }
        $ids = $idsArr;

        //如果没有生成过结算单,则生成结算单
        //1.创建结算号
        $settleId = $this->getSettleId();
        //2.将结算号与账单号写入关联表
        $settleInvoiceArr = [];
        foreach ($ids as $inv_id){
            $settleInvoiceArr [] = [
                'settle_id' => $settleId,
                'invoice_id' => $inv_id
            ];
        }
        $model = new EmSettleInvoice();
        if(!$model->saveAll($settleInvoiceArr)){
            throw new Exception('保存账单与结算关联数据失败');
        };

        $account = (new EmAccount())->getIdByInvoiceID($settleInvoiceArr[0]['invoice_id']);

        //3.将账单数据汇总写入结算表
        $pData  = [];
        $pData['amount'] = 0;
        $pData['settle_id'] = $settleId;
        $pData['status'] = 0;
        $pData['account_id'] = $account->account_id;
        $pData['balance'] = $pData['amount'];

        if((new EmSettle())->save($pData)){
            return json(['status'=>1,'message'=>'已创建结算单']);
        } else {
            throw new Exception('创建结算单失败');
        }
    }

    //结算详情页
    public function detail(){
        $settle_id = Request::param('settle_id');

        $epModel = new EmSettle();
        //查询缴费单基本信息
        $settle = $epModel->where('settle_id','=',$settle_id)->find();

        if($settle) {
            switch ($settle->status) {
                case 0:
                    $settle->statusTitle = '未结算';
                    break;
                case 1:
                    $settle->statusTitle = '已结算 缺发票';
                    break;
                case 2:
                    $settle->statusTitle = '已上传发票';
                    break;
                case 3:
                    $settle->statusTitle = '凭证完整';
                    break;
                case 4:
                    $settle->statusTitle = '已审核';
                    break;
            }
            //查询账单信息
            $invs = $epModel->getinvsInfo($settle->settle_id);
            $this->assign('invs', $invs);

            foreach ($invs as $inv){
                if($inv->settle_balance == 0){
                    $inv->sett_amount = $inv->settle_amount;
                } else {
                    $inv->sett_amount = $inv->settle_amount - $inv->settle_balance;
                }
            }

            //实缴金额
            $amount = EmCertSettle::where('settle_id', '=', $settle_id)->sum('amount');
            //实缴金额
            if($settle->mark){
                if($settle->balance == 0){
                    $amount = $settle->amount;
                } else {
                    $amount = $settle->amount - $settle->balance;
                }
            }
            $this->assign('settle_sum_amount',$amount);
            //查询凭证信息
            $receipts = (new EmSettleReceipt)->getSettleReceiptBySettleId($settle_id);

            if (!$receipts) $receipts = [];
            foreach ($receipts as &$receipt) {
                $receipt->file_src = trim($receipt->file_src, '.');
            }
            $this->assign('receipts', $receipts);
        } else {
            $em_id = Request::param('em_id');
            $epModel->settle_id = $this->getSettleId();
            $epModel->account_id = (new Account())->getAccountId($em_id);
            $epModel->amount = $epModel->balance = $epModel->status = 0;
            $epModel->save();

            //映射变量
            $settle = $epModel;
            $settle->statusTitle = '未结算';
            $settle->staff_id = 1;
            $amount = 0;
            $this->assign('settle_sum_amount', $amount);

            //保持数据一致
            $this->assign('invs', new EmInvoice());
            $this->assign('receipts', new EmSettleReceipt());
        }
        $this->assign('settle', $settle);

        //员工列表
        $user  =  Session::get('user');
        $this->assign('staffs',(new Staff())->getStaffs($user['is_admin'],$settle->staff_id));

        return $this->fetch();
    }

    //保存结算信息
    public function store(){
        $data = Request::post();

        $certs = EmCertSettle::where('settle_id','=',$data['settle_id'])->select();
        $settleModel = EmSettle::where('settle_id','=',$data['settle_id'])->find();
        $receipts = EmSettleReceipt::where('settle_id','=',$data['settle_id'])->select();

        //判断是否已经上传缴费凭证信息
        if(!$certs->isEmpty() && !$receipts->isEmpty()){
            $amount  = 0 ;
            foreach ($certs as $cert){
                $amount += $cert->amount;
            }
            $settleModel->amount = $settleModel->balance = $amount;
            $settleModel->status = 3; //代表已经结算
        }
        else if(!$certs->isEmpty() && $receipts->isEmpty()){
            $amount  = 0 ;
            foreach ($certs as $cert){
                $amount += $cert->amount;
            }
            $settleModel->status = 1; //代表已经结算
            $settleModel->amount = $settleModel->balance = $amount;
        } else if(!$receipts->isEmpty() && $certs->isEmpty()) {
            $settleModel->status = 2;
        }
        $settleModel->staff_id = $data['staff_id'];
        $settleModel->save();
        return json(['status'=>1,'message'=>'保存结算信成功']);
    }

    //审核通过开始销账
    public function confirm(){
        $settle_id = Request::param('settle_id');

        //判断是否具备审核条件
        $amount = EmCertSettle::where('settle_id','=',$settle_id)->sum('amount');
        $settleModel = EmSettle::get(['settle_id' => $settle_id]);

        //账单实结金额保存到账单里面
        if($amount > 0 && $settleModel->status == 3) {

            $settleModel->settle_date = date('Y:m:d H:i:s',time());
            $settleModel->amount = $settleModel->balance = $amount;
            $settleModel->save();

            //销账
            $result =  (new Invoice())->writeOffFromSettle($settleModel->account_id,$settle_id);
            return json(['status'=>1,'message'=>$result]);
        }
        return json(['status'=>0,'message'=>'不满足审核条件']);
    }

    //更新结算状态
    public function updateStatus($settle_id){
        //变更为已结算
        $paymentModel = EmSettle::get(['settle_id'=>$settle_id]);
        $paymentModel->status = 1;
        $paymentModel->save();
    }

    //生成结算单号
    private function getSettleId(){
        $settle = EmSettle::field('id')->order('id desc,create_time desc')->find();
        if(!$settle) $id = 1;
        else $id = $settle->id + 1;
        return "JS".date('Ymd').zero($id);
    }

    /**
     * 结算明细
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function settleDetail(){
        $invoice_id = Request::param('invoice_id');
        $esib = EmSettleInvoiceBalance::where('invoice_id','=',$invoice_id)
            ->order('settle_id asc')->select();
        $this->assign('data',$esib);
        return $this->fetch();
    }
}