<?php
namespace app\adminVue\controller;
use think\facade\Db;
use app\mobile\service\OutplantApprovers;

class V2OutplantSettings extends V2Base
{
    private function requireManager() {
        if ((int)$this->actor['rightid']<=98) $this->fail('仅rightid>98的账号可以设置审批人员',403);
    }
    private function version($rows) { return hash_hmac('sha256',json_encode($rows),$this->requestToken()); }
    private function kind($method) {
        $kind=$this->request->$method('kind','finance');
        if (!is_string($kind) || !in_array($kind,['finance','scrap','managers'],true)) $this->fail('设置类型不正确');
        return $kind;
    }
    private function number($value) {
        if ((!is_int($value) && !is_string($value)) || !($id=OutplantApprovers::personId($value))) $this->fail('编号不正确');
        return $id;
    }
    private function people($ids) {
        $departments=Db::name('admin_org')->where('mid',0)->column('title','id');
        $people=Db::name('admin_user')->where('status',1)->field('id,username,truename,dpt')->order('truename,id')->select()->toArray(); $found=[];
        foreach ($people as &$p) {
            $p['id']=(int)$p['id'];$found[]=$p['id'];$p['departmentName']=$departments[$p['dpt']] ?? '未设置部门';$p['disabled']=false;
        } unset($p);
        foreach (array_diff(array_unique($ids),$found) as $id) if ($id>0) $people[]=['id'=>$id,'username'=>'','truename'=>'已离职或不存在（ID '.$id.'）','departmentName'=>'','disabled'=>true];
        return $people;
    }
    private function departmentState($department) {
        $state=OutplantApprovers::managerState($department);$state['version']=$this->version($state['snapshot']);unset($state['snapshot']);return $state;
    }
    public function index() {
        $this->requireManager();$kind=$this->kind('get');
        if ($kind==='managers') {
            $departments=Db::name('admin_org')->where('mid',0)->field('id,title')->order('id')->select()->toArray();$list=[];
            foreach ($departments as $department) $list[]=$this->departmentState($department);
            return json(['code'=>0,'msg'=>'','data'=>['departments'=>$list,'people'=>$this->people(array_column($list,'proxyId'))]]);
        }
        $rows=Db::name('admin_base')->where('mid',$kind==='finance'?20:21)->order('id')->select()->toArray();
        $raw=array_map([OutplantApprovers::class,'personId'],array_column($rows,'title'));$ids=array_values(array_unique(array_filter($raw)));
        $issue=in_array(0,$raw,true) || count($raw)!==count($ids) || ($kind==='scrap' && count($rows)>1) ? '原配置存在无效或重复数据，请核对后保存当前选择' : '';
        return json(['code'=>0,'msg'=>'','data'=>['personIds'=>$ids,'people'=>$this->people($ids),'version'=>$this->version($rows),'issue'=>$issue]]);
    }
    private function replaceRows($rows,$newRows) {
        // MyISAM表锁内先插入再删除；普通写入失败时保留原配置。
        $created=[];
        try {
            foreach ($newRows as $row) $created[]=Db::name('admin_base')->insertGetId($row);
            if ($rows) Db::name('admin_base')->whereIn('id',array_column($rows,'id'))->delete();
        } catch (\Throwable $error) {
            if ($created) Db::name('admin_base')->whereIn('id',$created)->delete();
            throw $error;
        }
    }
    public function save() {
        $this->requireManager();$kind=$this->kind('post');$version=$this->request->post('version');
        if (!is_string($version) || !preg_match('/^[a-f0-9]{64}$/D',$version)) $this->fail('请重新打开审批人员设置');
        $ids=[];$departmentId=0;
        if ($kind==='managers') {
            $departmentId=$this->number($this->request->post('departmentId'));$raw=$this->request->post('proxyId');
            $ids=($raw===0 || $raw==='0' || $raw==='') ? [] : [$this->number($raw)];
        } else {
            $raw=$this->request->post('personIds');
            if (!is_array($raw) || !$raw || count($raw)>($kind==='scrap'?1:100)) $this->fail($kind==='scrap'?'请选择一名废品审批人员':'请至少选择一名财务审批人员');
            foreach ($raw as $value) $ids[]=$this->number($value);
            if (count(array_unique($ids))!==count($ids)) $this->fail('审批人员不能重复');sort($ids,SORT_NUMERIC);
        }
        $config=config('database.connections.'.config('database.default'));$prefix=$config['prefix'];
        if (!preg_match('/^[a-zA-Z0-9_]*$/D',$prefix)) $this->fail('数据库配置无效',500);
        $pdo=Db::connect()->getConnection()->getPdo();$locked=false;
        try {
            $pdo->exec('LOCK TABLES '.$prefix.'admin_base WRITE, '.$prefix.'admin_user READ, '.$prefix.'admin_org READ');$locked=true;
            if ((int)Db::name('admin_user')->where(['id'=>$this->actor['id'],'status'=>1])->value('rightid')<=98) $this->fail('设置权限已变化，请刷新页面',403);
            if ($ids && Db::name('admin_user')->whereIn('id',$ids)->where('status',1)->count()!==count($ids)) $this->fail('所选人员已离职或不存在，请重新选择');
            if ($kind==='managers') {
                $department=Db::name('admin_org')->where(['id'=>$departmentId,'mid'=>0])->field('id,title')->find();
                if (!$department) $this->fail('部门不存在，请刷新');
                $state=OutplantApprovers::managerState($department);
                if (!hash_equals($this->version($state['snapshot']),$version)) $this->fail('部门经理或代理配置已变化，请重新加载',409);
                $this->replaceRows($state['snapshot'][2],$ids ? [['mid'=>22,'title'=>(string)$departmentId,'content'=>(string)$ids[0],'mark'=>'物品出厂部门经理代理']] : []);
                $data=$this->departmentState($department);
            } else {
                $mid=$kind==='finance'?20:21;$rows=Db::name('admin_base')->where('mid',$mid)->order('id')->select()->toArray();
                if (!hash_equals($this->version($rows),$version)) $this->fail('审批人员配置已变化，请重新加载',409);
                $newRows=[];foreach ($ids as $id) $newRows[]=['mid'=>$mid,'title'=>(string)$id,'content'=>'','mark'=>$kind==='finance'?'物品出厂财务审批人员':'物品出厂废品审批人员'];
                $this->replaceRows($rows,$newRows);$data=['personIds'=>$ids,'version'=>$this->version(Db::name('admin_base')->where('mid',$mid)->order('id')->select()->toArray())];
            }
        } finally { if ($locked) $pdo->exec('UNLOCK TABLES'); }
        return json(['code'=>0,'msg'=>'审批人员设置已保存','data'=>$data]);
    }
}
