<?php
namespace app\mobile\controller;

use think\facade\Db;
use think\facade\Filesystem;
use think\facade\Log;

class OmsNightBus extends OmsBase
{
    public function messageItems($account,$since,\app\mobile\service\MessageInbox $inbox) {
        if(!$inbox->allowsSource($this))$this->fail('接口不存在',404);
        $now=$this->now();$today=strtotime(date('Y-m-d',$now));$items=[];
        foreach(Db::name('common_night_bus')->where('eid',$account['username'])->where('status','>',0)->where('eff_date','>=',$since)->select()->toArray() as $row){
            $start=(int)$row['eff_date']+21*3600+45*60;$end=$start+3600;$fields=['乘车日期'=>date('Y-m-d',$row['eff_date']),'路线'=>(int)$row['item']===1?'两江名居':'三溪口'];$route='/pages/night-bus/index?tab=records';
            if((int)$row['status']===1 && $now>=$start && $now<=$end)$items[]=\app\mobile\service\MessageInbox::item('night-bus',$row['id'],'confirm','乘车待拍照确认','待拍照确认',$fields,$route,'pending',$start,$end);
            if((int)$row['status']===2)$items[]=\app\mobile\service\MessageInbox::item('night-bus',$row['id'],'confirm','乘车拍照确认已完成','已确认',$fields,$route,'done',$start);
        }return $items;
    }
    protected function now() { return time(); }
    private function employee($account) {
        $eid = (string)$account['username'];
        if (!ctype_digit($eid) || (float)$eid > 2147483647) $this->fail('当前账号未设置有效工号，无法申请班车', 403);
        return $eid;
    }
    private function locked($eid, $action) {
        $database = $this->app->config->get('database.connections.' . $this->app->config->get('database.default') . '.database');
        $key = 'oms-bus:' . sha1($database . ':' . $eid);
        $result = Db::query('SELECT GET_LOCK(?, 5) AS acquired', [$key]);
        if ((int)$result[0]['acquired'] !== 1) $this->fail('操作正在处理中，请稍后重试', 503);
        try { return $action(); } finally { Db::query('SELECT RELEASE_LOCK(?)', [$key]); }
    }
    private function ownRecord($eid) {
        $id = $this->request->post('id');
        if (!is_scalar($id) || !preg_match('/^[1-9][0-9]{0,9}$/', (string)$id)) $this->fail('申请编号不正确');
        $row = Db::name('common_night_bus')->where('id', $id)->where('eid', $eid)->where('status', '>', 0)->find();
        if (!$row) $this->fail('申请不存在或已撤回', 404);
        if ((int)$row['status'] !== 1) $this->fail('已确认乘车，无法重复操作');
        return $row;
    }
    protected function savePhoto() {
        $file = $this->request->file('image');
        if (!$file instanceof \think\file\UploadedFile || !$file->isValid() || $file->getSize() > 5 * 1024 * 1024) $this->fail('请选择不超过 5MB 的乘车照片');
        $extensions = ['image/jpeg'=>'jpg', 'image/png'=>'png', 'image/webp'=>'webp'];
        $mime = $file->getMime();
        if (!isset($extensions[$mime]) || !@getimagesize($file->getPathname())) $this->fail('请上传 JPG、PNG 或 WebP 图片');
        $folder = 'wx_upload/' . date('Ymd', $this->now()) . '/bus_img';
        $path = Filesystem::disk('public')->putFileAs($folder, $file, bin2hex(random_bytes(16)) . '.' . $extensions[$mime]);
        if (!$path) $this->fail('照片保存失败，请稍后重试', 503);
        return '/storage/' . str_replace('\\', '/', $path);
    }
    protected function notifyApplication($id, $eid) {
        // 沿用旧版服务号通知，不影响已经保存成功的申请。
        try {
            $template = ['touser'=>'200216', 'template_id'=>'3Huxw6Ptdx15igJrOWwJ2OhlRmqX15AKwDdI5cK-ZOE', 'data'=>[
                'keyword1'=>['value'=>$id, 'color'=>'#FF0000'],
                'keyword2'=>['value'=>'晚10点加班车申请', 'color'=>'#FF0000'],
                'keyword3'=>['value'=>'晚10点加班车申请', 'color'=>'#FF0000'],
                'keyword4'=>['value'=>$eid, 'color'=>'#FF0000'],
                'keyword5'=>['value'=>date('Y-m-d,H:i:s', $this->now()), 'color'=>'#FF0000'],
            ]];
            $result = (new \wx\wxMsg())->send_msg_eid(json_encode($template));
            if ((string)$result !== '0') Log::warning('oms night bus notification failed');
        } catch (\Throwable $exception) { Log::warning('oms night bus notification unavailable'); }
    }
    public function records() {
        return $this->guarded(function () {
            $this->requireMethod('GET'); $eid = $this->employee($this->current());
            $page = $this->request->get('page', '1');
            if (!is_scalar($page) || !preg_match('/^[1-9][0-9]{0,5}$/', (string)$page)) $this->fail('页码不正确');
            $page = (int)$page; $pageSize = 10;
            $query = Db::name('common_night_bus')->where('eid', $eid)->where('status', '>', 0);
            $total = (clone $query)->count();
            $rows = $query->field('id,eff_date,item,status,img')->order('eff_date desc,id desc')->limit(($page - 1) * $pageSize, $pageSize)->select()->toArray();
            foreach ($rows as &$row) {
                $date = (int)$row['eff_date']; $pending = (int)$row['status'] === 1;
                $row['canCancel'] = $pending && $this->now() <= $date + 17 * 3600;
                $row['canConfirm'] = $pending && $this->now() >= $date + 21 * 3600 + 45 * 60 && $this->now() <= $date + 22 * 3600 + 45 * 60;
                $row['eff_date'] = date('Y-m-d', $date); $row['id'] = (int)$row['id']; $row['item'] = (int)$row['item']; $row['status'] = (int)$row['status'];
            }
            unset($row);
            return json(['code'=>0, 'message'=>'成功', 'data'=>['items'=>$rows, 'total'=>$total, 'page'=>$page, 'pageSize'=>$pageSize]]);
        });
    }
    public function apply() {
        return $this->guarded(function () {
            $this->requireMethod('POST'); $eid = $this->employee($this->current());
            $text = $this->requiredText('date', 10); $route = $this->request->post('item');
            $date = \DateTimeImmutable::createFromFormat('!Y-m-d', $text, new \DateTimeZone('Asia/Shanghai'));
            if (!$date || $date->format('Y-m-d') !== $text || !is_scalar($route) || !in_array((string)$route, ['1','2'], true)) $this->fail('请选择有效日期和路线');
            $id = $this->locked($eid, function () use ($eid, $date, $route) {
                if ($this->now() > $date->getTimestamp() + 17 * 3600) $this->fail('超时无法申请，当日 17:00 截止');
                if (Db::name('common_night_bus')->where(['eid'=>$eid, 'eff_date'=>$date->getTimestamp(), 'status'=>1])->find()) $this->fail('当日已申请');
                return Db::name('common_night_bus')->insertGetId(['eid'=>$eid, 'eff_date'=>$date->getTimestamp(), 'item'=>(int)$route, 'status'=>1, 'update'=>$this->now()]);
            });
            $this->notifyApplication($id, $eid);
            return json(['code'=>0, 'message'=>'申请成功', 'data'=>['id'=>(int)$id]]);
        });
    }
    public function cancel() {
        return $this->guarded(function () {
            $this->requireMethod('POST'); $eid = $this->employee($this->current());
            $this->locked($eid, function () use ($eid) {
                $row = $this->ownRecord($eid);
                if ($this->now() > (int)$row['eff_date'] + 17 * 3600) $this->fail('超时无法撤回，当日 17:00 截止');
                Db::name('common_night_bus')->where('id', $row['id'])->where('eid', $eid)->where('status', 1)->update(['status'=>0]);
            });
            return json(['code'=>0, 'message'=>'撤回成功', 'data'=>null]);
        });
    }
    public function confirm() {
        return $this->guarded(function () {
            $this->requireMethod('POST'); $eid = $this->employee($this->current());
            $this->locked($eid, function () use ($eid) {
                $row = $this->ownRecord($eid); $date = (int)$row['eff_date'];
                if ($this->now() < $date + 21 * 3600 + 45 * 60 || $this->now() > $date + 22 * 3600 + 45 * 60) $this->fail('非乘车确认时间，请在 21:45–22:45 拍照确认');
                $path = $this->savePhoto();
                try { Db::name('common_night_bus')->where('id', $row['id'])->where('eid', $eid)->where('status', 1)->update(['status'=>2, 'img'=>$path]); }
                catch (\Throwable $exception) { Filesystem::disk('public')->delete(substr($path, strlen('/storage/'))); throw $exception; }
            });
            return json(['code'=>0, 'message'=>'乘车确认完成', 'data'=>null]);
        });
    }
    public function summary()
    {
        return $this->guarded(function () {
            $this->requireMethod('GET');
            $today = new \DateTimeImmutable('today', new \DateTimeZone('Asia/Shanghai'));
            $counts = Db::name('common_night_bus')->where('status', '>', 0)
                ->whereBetween('eff_date', [$today->getTimestamp(), $today->modify('+6 days')->getTimestamp()])
                ->field('eff_date,item,COUNT(*) AS total')->group('eff_date,item')->select()->toArray();
            $days = [];
            for ($i = 0; $i < 7; $i++) {
                $date = $today->modify('+' . $i . ' days');
                $days[$date->getTimestamp()] = ['date'=>$date->format('Y-m-d'), 'liangjiang'=>0, 'sanxikou'=>0];
            }
            foreach ($counts as $row) {
                $timestamp = (int)$row['eff_date'];
                $route = [1=>'liangjiang', 2=>'sanxikou'][(int)$row['item']] ?? null;
                if (isset($days[$timestamp]) && $route) $days[$timestamp][$route] = (int)$row['total'];
            }
            return json(['code'=>0, 'message'=>'成功', 'data'=>['days'=>array_values($days), 'minimumPassengers'=>15]]);
        });
    }
}
