<?php
namespace app\adminVue\controller;

use think\facade\Db;

/** Four mini-program record books. No models with write hooks or write actions. */
class V2HrRecords extends V2Base
{
    private function definition()
    {
        $definitions=[
            'safety'=>['onsite_safe_list','create_date','id,eid,ename,team,area,create_date,issue_desc,action,owner,due_date,status,update'],
            'outplant'=>['common_outplant','create_time','id,owner,ownerType,dpt,create_time,reason,out_time,back_time,checkType,backType,express,expressCode,img,mark,apv1,apv1_time,apv1_mark,apv2,apv2_time,apv2_mark,apv3,apv3_time,apv3_mark,status,on_check,check_time,return_status'],
            'newcomers'=>['member_newcomer','create_time','id,name,phone,supplier,creator,create_time'],
            'exams'=>['member_newcomer_score','exam_date','id,ename,phone,score,status,exam_date,item_type,type'],
            'meals'=>['common_meal_list','meal_date','id,dpt,owner,title,meal_date,meal1,meal2,meal3,meal4,mark,status,update'],
            'collection'=>['common_meal_sign','meal_date','id,eid,ename,item,itemMark,mark,meal_date,num,phone,type,visitor_id,create_time,check_time,check_aid,status']
        ];
        $kind=$this->request->get('kind','');
        if (!is_string($kind) || !isset($definitions[$kind])) $this->fail('记录类型无效');
        return array_merge([$kind],$definitions[$kind]);
    }

    private function number($key,$default,$max=2147483647,$min=1)
    {
        $value=$this->request->get($key,$default);
        if (!is_scalar($value) || !preg_match('/^[0-9]+$/D',(string)$value) || (float)$value<$min || (float)$value>$max) $this->fail('数字参数无效');
        return (int)$value;
    }

    private function day($value)
    {
        if (!is_string($value)) $this->fail('日期格式无效');
        $date=\DateTimeImmutable::createFromFormat('!Y-m-d',$value,new \DateTimeZone('Asia/Shanghai'));
        if (!$date || $date->format('Y-m-d')!==$value || $value<'2000-01-01' || $value>'2099-12-31') $this->fail('日期格式无效');
        return $date;
    }

    private function query($definition,$export=false,$detail=false)
    {
        list($kind,$table,$dateField)=$definition;$query=Db::name($table);
        if (in_array($kind,['safety','outplant'],true)) { $query->where('status','>',0); if($kind==='outplant')$query->where('type',2); }
        if ($kind==='exams') $query->where('status',1);
        if ($detail) return $query;
        if ($kind==='meals') {
            $view=$this->number('view',1,2);
            if ($view===1) $query->where('owner','>',0); else $query->whereNull('owner');
        }
        $start=$this->request->get('startDate','');$end=$this->request->get('endDate','');
        if (!is_string($start) || !is_string($end)) $this->fail('日期格式无效');
        if ($export && ($start==='' || $end==='')) $this->fail('请选择导出日期区间');
        $first=$start!==''?$this->day($start):null;$last=$end!==''?$this->day($end):null;
        if ($first && $last && $first>$last) $this->fail('开始日期不能晚于结束日期');
        if ($first) $query->where($dateField,'>=',$first->getTimestamp());
        if ($last) $query->where($dateField,'<',$last->modify('+1 day')->getTimestamp());
        if ($export) return $query;
        $keyword=$this->request->get('keyword','');
        if (!is_string($keyword) || mb_strlen($keyword)>100) $this->fail('关键词格式无效');
        $keyword=trim($keyword);
        if(in_array($kind,['safety','outplant'],true)){
            $status=$this->number('status',0,4,0);if($status)$query->where('status',$status);
            if($keyword!==''){ $like='%'.addcslashes($keyword,'%_\\').'%';$ids=Db::name('admin_user')->whereLike('truename|username',$like)->column('id');
                $query->where(function($q)use($kind,$like,$ids){$q->whereLike($kind==='safety'?'eid|ename|team|area|issue_desc':'reason|mark|expressCode',$like);if($ids){if($kind==='outplant')$q->whereOr(function($sub)use($ids){$sub->where('ownerType','<>',1)->whereIn('owner',$ids);});else $q->whereOr('owner','in',$ids);}if($kind==='outplant'){$members=Db::name('member_list')->whereLike('ename|eid',$like)->column('id');if($members)$q->whereOr(function($sub)use($members){$sub->where('ownerType',1)->whereIn('owner',$members);});}});}
            return $query;
        }$pattern='%'.addcslashes($keyword,'%_\\').'%';
        if ($kind==='meals') {
            $department=$this->number('department',0,2147483647,0);
            if ($department) $query->where('dpt',$department);
        }
        if ($kind==='collection') {
            $type=$this->number('type',0,127,0);$status=$this->number('status',0,2,0);
            if ($type) $query->where('type',$type);
            if ($status) $query->where('status',$status);
        }
        if ($keyword!=='') {
            if ($kind==='newcomers') $query->whereLike('name|phone|supplier',$pattern);
            elseif ($kind==='exams') $query->whereLike('ename|phone',$pattern);
            elseif ($kind==='meals') {
                $owners=Db::name('admin_user')->whereLike('truename|username',$pattern)->column('id');
                $query->where(function($q)use($pattern,$owners){$q->whereLike('title|mark',$pattern);if($owners)$q->whereOr('owner','in',$owners);});
            } else {
                $eids=array_merge(Db::name('admin_user')->whereLike('truename',$pattern)->column('username'),Db::name('member_list')->whereLike('ename',$pattern)->column('eid'));
                $phones=Db::name('member_newcomer')->whereLike('name',$pattern)->column('phone');
                $query->where(function($q)use($pattern,$eids,$phones){$q->whereLike('eid|ename|phone',$pattern);if($eids)$q->whereOr('eid','in',$eids);if($phones)$q->whereOr('phone','in',$phones);});
            }
        }
        return $query;
    }

    private function stamp($value,$time=true)
    {
        return (int)$value>0?(new \DateTimeImmutable('@'.(int)$value))->setTimezone(new \DateTimeZone('Asia/Shanghai'))->format($time?'Y-m-d H:i:s':'Y-m-d'):'';
    }

    private function present($kind,$rows)
    {
        if (!$rows) return [];
        if(in_array($kind,['safety','outplant'],true))return $this->presentEhs($kind,$rows);
        if ($kind==='newcomers' || $kind==='meals') {
            $key=$kind==='newcomers'?'creator':'owner';$ids=array_filter(array_column($rows,$key));
            $names=$ids?Db::name('admin_user')->whereIn('id',array_unique($ids))->column('truename','id'):[];
        }
        if ($kind==='meals' || $kind==='collection') $departments=Db::name('admin_org')->where('mid',0)->column('title','id');
        if ($kind==='collection') {
            $eids=array_values(array_unique(array_filter(array_column($rows,'eid'))));$people=[];$members=[];
            if ($eids) {
                foreach (Db::name('admin_user')->whereIn('username',$eids)->field('id,username,truename,dpt,status')->order('id desc')->select() as $person) {
                    $key=$person['username'];if (!isset($people[$key]) || ((int)$person['status']===1 && (int)$people[$key]['status']!==1)) $people[$key]=$person;
                }
                foreach (Db::name('member_list')->whereIn('eid',$eids)->field('id,eid,ename,status')->order('id desc')->select() as $person) {
                    $key=$person['eid'];if (!isset($members[$key]) || ((int)$person['status']===1 && (int)$members[$key]['status']!==1)) $members[$key]=$person;
                }
            }
            $phones=array_values(array_unique(array_filter(array_column($rows,'phone'))));$newcomers=[];
            if ($phones) foreach (Db::name('member_newcomer')->whereIn('phone',$phones)->field('id,phone,name,supplier,create_time')->order('create_time desc,id desc')->select() as $person) $newcomers[$person['phone']][]=$person;
            $visitors=array_filter(array_column($rows,'visitor_id'));
            $reasons=$visitors?Db::name('common_visitor_list')->whereIn('id',$visitors)->column('reason','id'):[];
            $checkers=array_filter(array_column($rows,'check_aid'));
            $checkerNames=$checkers?Db::name('admin_user')->whereIn('id',$checkers)->column('truename','id'):[];
            $types=[];$items=[];
            foreach (Db::name('admin_base')->whereIn('mid',[10,11])->field('mid,title,content')->select() as $option) {
                if ((int)$option['mid']===10) $types[(string)$option['content']]=$option['title'];else $items[(string)$option['content']]=$option['title'];
            }
        }
        $result=[];
        foreach ($rows as $row) {
            $id=(int)$row['id'];
            if ($kind==='newcomers') $record=['id'=>$id,'name'=>$row['name'],'phone'=>(string)$row['phone'],'supplier'=>$row['supplier'],'creatorName'=>$names[$row['creator']] ?? '人员已变更','createdAt'=>$this->stamp($row['create_time'])];
            elseif ($kind==='exams') $record=['id'=>$id,'name'=>$row['ename'],'phone'=>(string)$row['phone'],'score'=>(int)$row['score'],'examAt'=>$this->stamp($row['exam_date']),'paperName'=>[1=>'A卷',2=>'B卷'][(int)$row['item_type']] ?? '原值：'.$row['item_type'],'attempts'=>max(1,(int)$row['type']),'result'=>'合格'];
            elseif ($kind==='meals') $record=['id'=>$id,'departmentName'=>(int)$row['dpt']>0?($departments[$row['dpt']] ?? '部门已变更'):'汇总','ownerName'=>(int)$row['owner']>0?($names[$row['owner']] ?? '人员已变更'):'','mealDate'=>$this->stamp($row['meal_date'],false),'description'=>$row['title'],'lunch'=>$row['meal1'],'dinner'=>$row['meal2'],'supper'=>$row['meal3'],'breakfast'=>$row['meal4'],'remark'=>$row['mark'],'updatedAt'=>$this->stamp($row['update'])];
            else {
                $person=$people[$row['eid']] ?? null;$member=$members[$row['eid']] ?? null;$newcomer=null;
                foreach ($newcomers[$row['phone']] ?? [] as $candidate) if ((int)$candidate['create_time']<=(int)$row['create_time']) { $newcomer=$candidate;break; }
                $training=(int)$row['type']===1;
                $name=trim((string)$row['ename'])!==''?$row['ename']:($training?($newcomer['name'] ?? ''):($person['truename'] ?? $member['ename'] ?? ''));
                $department=$training?($newcomer['supplier'] ?? ''):($person?($departments[$person['dpt']] ?? '部门已变更'):($member?'一线员工':''));
                $remark=(int)$row['type']===3?($reasons[$row['visitor_id']] ?? $row['mark']):$row['mark'];
                $record=['id'=>$id,'mealDate'=>$this->stamp($row['meal_date'],false),'typeName'=>$types[(string)$row['type']] ?? '类型'.$row['type'],'employeeNo'=>(string)($row['eid'] ?? ''),'name'=>$name ?: '资料缺失','departmentName'=>$department,'itemName'=>$items[(string)$row['item']] ?? '餐别'.$row['item'],'itemRemark'=>$row['itemMark'],'quantity'=>(int)$row['num'],'remark'=>$remark,'createdAt'=>$this->stamp($row['create_time']),'status'=>(int)$row['status'],'statusLabel'=>[1=>'待验码',2=>'已验证'][(int)$row['status']] ?? '原值：'.$row['status'],'checkedAt'=>$this->stamp($row['check_time']),'checkerName'=>(int)$row['check_aid']>0?($checkerNames[$row['check_aid']] ?? '人员已变更'):'','phone'=>(string)($row['phone'] ?? '')];
            }
            $result[]=$record;
        }
        return $result;
    }


    private function presentEhs($kind,$rows)
    {
        $names=Db::name('admin_user')->column('truename','id');$departments=Db::name('admin_org')->where('mid',0)->column('title','id');
        $ids=array_column($rows,'id');$images=[];$materials=[];
        if($kind==='safety')foreach(Db::name('img_list')->where(['mid'=>6,'status'=>1])->whereIn('mark',$ids)->field('id,mark')->select()as$image)$images[$image['mark']][]=['id'=>(int)$image['id']];
        else foreach(Db::name('common_outplant_material')->whereIn('n_id',$ids)->field('id,n_id,item,type,name,unit,num,mark,img')->order('id')->select()as$material)$materials[$material['n_id']][]=$material;
        $members=$kind==='outplant'?Db::name('member_list')->whereIn('id',array_column($rows,'owner'))->column('ename','id'):[];
        $users=$kind==='outplant'?Db::name('admin_user')->whereIn('id',array_column($rows,'owner'))->column('dpt','id'):[];
        $result=[];
        foreach($rows as$r){
            $id=(int)$r['id'];$status=(int)$r['status'];
            if($kind==='safety')$record=['id'=>$id,'employeeNo'=>(string)$r['eid'],'name'=>$r['ename'],'team'=>$r['team'],'area'=>$r['area'],'createdAt'=>$this->stamp($r['create_date']),'description'=>$r['issue_desc'],'action'=>$r['action'],'ownerName'=>$names[$r['owner']]??'','dueDate'=>$this->stamp($r['due_date'],false),'updatedAt'=>$this->stamp($r['update']),'status'=>$status,'statusLabel'=>[1=>'待分配',2=>'进行中',3=>'待确认',4=>'已完成'][$status]??'状态'.$status,'images'=>$images[$id]??[]];
            else{
                $flow=[];for($i=1;$i<=3;$i++)if($r['apv'.$i]>0)$flow[]=($names[$r['apv'.$i]]??'人员已变更').' / '.($this->stamp($r['apv'.$i.'_time'])?:'待审批').' / '.($r['apv'.$i.'_mark']??'');
                $record=['id'=>$id,'ownerName'=>(int)$r['ownerType']===1?($members[$r['owner']]??'人员已变更'):($names[$r['owner']]??'人员已变更'),'departmentName'=>(int)$r['ownerType']===1?'生产部':($departments[$users[$r['owner']]??0]??'部门已变更'),'createdAt'=>$this->stamp($r['create_time']),'reason'=>$r['reason'],'outAt'=>$this->stamp($r['out_time']),'backAt'=>$this->stamp($r['back_time']),'checkType'=>[1=>'正常',2=>'预审批',3=>'紧急审批'][(int)$r['checkType']]??'原值：'.$r['checkType'],'backType'=>[1=>'不返厂',2=>'返厂'][(int)$r['backType']]??'原值：'.$r['backType'],'expressCode'=>$r['expressCode'],'remark'=>$r['mark'],'approvalFlow'=>implode("\n",$flow),'checkerName'=>$names[$r['on_check']]??'','checkedAt'=>$this->stamp($r['check_time']),'returnStatus'=>$r['return_status'],'status'=>$status,'statusLabel'=>[1=>'一级审批中',2=>'二级审批中',3=>'三级审批中',4=>'已通过'][$status]??'状态'.$status,'images'=>$r['img']?[['id'=>$id]]:[],'materials'=>$materials[$id]??[]];
            }
            $result[]=$record;
        }
        return $result;
    }
    public function exportImage()
    {
        $kind=$this->definition()[0];$id=$this->number('imageId',0);
        if($kind==='safety'){$image=Db::name('img_list')->where(['id'=>$id,'mid'=>6,'status'=>1])->field('mark,img')->find();$valid=$image?Db::name('onsite_safe_list')->where('id',$image['mark'])->where('status','>',0)->find():null;$path=$image['img']??'';}
        elseif($kind==='outplant' && $this->request->get('source','')==='material'){$material=Db::name('common_outplant_material')->where('id',$id)->field('n_id,img')->find();$valid=$material?Db::name('common_outplant')->where(['id'=>$material['n_id'],'type'=>2])->where('status','>',0)->find():null;$path=$material['img']??'';}
        elseif($kind==='outplant'){$valid=Db::name('common_outplant')->where(['id'=>$id,'type'=>2])->where('status','>',0)->find();$path=$valid['img']??'';}else $this->fail('图片类型无效');
        $path=str_replace('\\','/',(string)$path);if(!$valid||strpos($path,'/storage/')!==0||strpos($path,'..')!==false)$this->fail('图片不存在',404);
        $root=realpath($this->app->getRootPath().'public/storage/');$file=$root?realpath($root.'/'.substr($path,9)):false;
        if(!$file||strpos($file,$root.DIRECTORY_SEPARATOR)!==0||!is_file($file))$this->fail('本地缺少图片文件，请同步 storage 图片目录',404);
        if(filesize($file)>5*1024*1024)$this->fail('图片超过5MB');$info=@getimagesize($file);if(!$info||!in_array($info['mime'],['image/jpeg','image/png','image/webp'],true))$this->fail('图片格式不支持');
        return json(['code'=>0,'msg'=>'','data'=>['dataUrl'=>'data:'.$info['mime'].';base64,'.base64_encode(file_get_contents($file))]]);
    }

    public function index()
    {
        $definition=$this->definition();$page=$this->number('page',1,1000000);$limit=$this->number('limit',15,100);$query=$this->query($definition);$total=(clone $query)->count();
        return json(['code'=>0,'msg'=>'','data'=>['list'=>$this->present($definition[0],$query->field($definition[3])->order('id desc')->page($page,$limit)->select()->toArray()),'total'=>$total]]);
    }

    public function options()
    {
        $definition=$this->definition();$data=['today'=>(new \DateTimeImmutable('now',new \DateTimeZone('Asia/Shanghai')))->format('Y-m-d'),'departments'=>[],'types'=>[]];
        if ($definition[0]==='meals') $data['departments']=Db::name('admin_org')->where('mid',0)->field('id,title')->order('id')->select()->toArray();
        if ($definition[0]==='collection') {
            $values=Db::name('common_meal_sign')->distinct(true)->column('type');$types=Db::name('admin_base')->where('mid',10)->column('title','content');
            foreach (array_unique(array_merge(array_keys($types),$values)) as $value) $data['types'][]=['value'=>(int)$value,'label'=>$types[$value] ?? '类型'.$value];
        }
        return json(['code'=>0,'msg'=>'','data'=>$data]);
    }

    public function detail()
    {
        $definition=$this->definition();$row=$this->query($definition,false,true)->where('id',$this->number('id',0))->field($definition[3])->find();
        if (!$row) $this->fail('记录不存在或不在当前查询范围',404);
        return json(['code'=>0,'msg'=>'','data'=>$this->present($definition[0],[$row])[0]]);
    }

    public function export()
    {
        $definition=$this->definition();$query=$this->query($definition,true);
        $upper=$this->request->get('upperId','')===''?(int)(clone $query)->max('id'):$this->number('upperId',0,2147483647,0);
        if (!$upper) return json(['code'=>0,'msg'=>'','data'=>['list'=>[],'total'=>0,'upperId'=>0,'nextCursor'=>null]]);
        $query->where('id','<=',$upper);$total=(clone $query)->count();
        if ($this->request->get('cursor','')!=='') $query->where('id','<',$this->number('cursor',0));
        $raw=in_array($definition[0],['safety','outplant'],true);
        $rows=$query->field($raw?'*':$definition[3])->order('id desc')->limit(201)->select()->toArray();$more=count($rows)>200;if($more)array_pop($rows);
        if($definition[0]==='outplant'&&$rows){
            $materials=[];foreach(Db::name('common_outplant_material')->whereIn('n_id',array_column($rows,'id'))->order('id')->select()as$item)$materials[$item['n_id']][]=$item;
            foreach($rows as&$row)$row['materials']=$materials[$row['id']]??[];unset($row);
        }
        return json(['code'=>0,'msg'=>'','data'=>['list'=>$raw?$rows:$this->present($definition[0],$rows),'total'=>$total,'upperId'=>$upper,'nextCursor'=>$more?(int)end($rows)['id']:null]]);
    }
}
