<?php
declare(strict_types=1);

namespace app\manager\controller;

use think\admin\Controller;
use think\admin\service\AdminService;

/**
 * 包名管理
 * @auth true  # 表示需要验证权限
 * @menu true  # 表示可以生成菜单
 */
class Package extends Controller
{
    /**
     * 绑定数据表
     * @var string
     */
    protected $table = 'offer_package';
    
    /**
     * 检查包名权限
     * @param int $packageId 包名ID
     * @return bool
     */
    protected function checkPackageAuth($packageId)
    {
        // 超级管理员直接放行
        if (AdminService::instance()->isSuper()) {
            return true;
        }
        
        // 检查用户是否有包名管理模块的权限
        if (!AdminService::instance()->check('package/index')) {
            return false;
        }

        // 检查具体包名权限
        $userId = AdminService::instance()->getUserId();
        $exists = $this->app->db->name('offer_package_auth')
            ->where(['package_id' => $packageId, 'user_id' => $userId])
            ->find();
            
        return !empty($exists);
    }

    /**
     * 获取当前用户可访问的包名ID列表
     */
    protected function getAuthPackageIds()
    {
        // 超级管理员可以访问所有
        if (AdminService::instance()->isSuper()) {
            return [];
        }
        
        // 如果没有包名管理模块权限，则不能访问任何包名
        if (!AdminService::instance()->check('package/index')) {
            return [-1];
        }

        // 获取用户被授权的包名列表
        $userId = AdminService::instance()->getUserId();
        $packageIds = $this->app->db->name('offer_package_auth')
            ->where(['user_id' => $userId])
            ->column('package_id');
            
        return $packageIds ?: [-1];
    }

    /**
     * 包名列表
     * @auth true  # 需要验证权限
     * @menu true  # 菜单可见
     */
    public function index()
    {

        if ($this->request->isPost()) {

            try {
                // 获取请求参数
                $page = $this->request->post('page/d', 1);
                $limit = $this->request->post('limit/d', 15);
                $where = [];
                
                // 包名搜索
                if ($package_name = $this->request->post('package_name/s', '')) {
                    $where[] = ['package_name', 'like', "%{$package_name}%"];
                }
                
                // 应用名称搜索
                if ($name = $this->request->post('name/s', '')) {
                    $where[] = ['name', 'like', "%{$name}%"];
                }
                
                // 状态筛选
                if ($status = $this->request->post('status/s', '')) {
                    $where[] = ['status', '=', $status];
                }
                
                // 创建人搜索
                if ($username = $this->request->post('username/s', '')) {
                    $where[] = ['username', 'like', "%{$username}%"];
                }
                
                // 时间范围处理
                if ($add_time = $this->request->post('add_time/s', '')) {
                    $times = explode(' - ', $add_time);
                    if (count($times) == 2) {
                        $start_time = strtotime($times[0] . ' 00:00:00');
                        $end_time = strtotime($times[1] . ' 23:59:59');
                        $where[] = ['add_time', 'between', [$start_time, $end_time]];
                    }
                }

                // 查询数据
                $query = $this->app->db->name('offer_package')->alias('p');
                
                // 非超级管理员需要进行权限过滤
                if (!AdminService::instance()->isSuper()) {
                    // 检查包名管理模块权限
                    if (!AdminService::instance()->check('package/index')) {
                        return json([
                            'code' => 0,
                            'msg' => '',
                            'count' => 0,
                            'data' => []
                        ]);
                    }
                    
                    $userId = AdminService::instance()->getUserId();
                    // 通过左连接查询有权限的包名
                    $query->leftJoin('offer_package_auth pa', 'p.id = pa.package_id')
                        ->where('pa.user_id', $userId);
                }

                // 先获取总数
                $total = $query->where($where)->count();
                
                // 分页查询数据
                $list = $query->where($where)
                    ->field('p.*')  // 只查询包名表的字段
                    ->order('p.id desc')
                    ->group('p.id')  // 防止重复数据
                    ->page($page, $limit)
                    ->select()
                    ->toArray();

                return json([
                    'code' => 0,
                    'msg' => '',
                    'count' => $total,
                    'data' => $list
                ]);
                
            } catch (\Exception $e) {
                trace("获取包名列表异常：" . $e->getMessage());
                return json([
                    'code' => 1,
                    'msg' => '获取数据失败，请稍后重试',
                    'count' => 0,
                    'data' => []
                ]);
            }
        }

     $this->fetch();
    }

    /**
     * 添加包名
     * @auth true
     * @menu true
     */
    public function add()
    {

        if ($this->request->isPost()) {
            // 开启事务
            $this->app->db->startTrans();
            try {
                $data = $this->_vali([
                    'package_name.require' => '包名不能为空！',
                    'name.require' => '应用名称不能为空！',
                    'status.require' => '状态不能为空！',
                    'status.in:0,1' => '状态值不正确！'
                ]);

                // 检查包名是否已存在
                $exists = $this->app->db->name('offer_package')
                    ->where(['package_name' => $data['package_name']])
                    ->find();
                if ($exists) {
                    $this->app->db->rollback();
                    return json(['code' => 0, 'info' => '包名已存在，请更换！']);
                }

                // 添加时间字段
                $now = time();
                $data['add_time'] = $now;
                $data['update_time'] = $now;
                $data['username'] = session('user.username') ?? '';

                // 插入包名数据
                $result = $this->app->db->name('offer_package')->insertGetId($data);
                if ($result === false) {
                    $this->app->db->rollback();
                    return json(['code' => 0, 'info' => '添加失败，请重试！']);
                }

                // 非超级管理员需要添加权限记录
                if (!AdminService::instance()->isSuper()) {
                    $authData = [
                        'package_id' => $result,
                        'user_id' => AdminService::instance()->getUserId(),
                        'create_at' => date('Y-m-d H:i:s')
                    ];
                    $authResult = $this->app->db->name('offer_package_auth')->insert($authData);
                    if ($authResult === false) {
                        $this->app->db->rollback();
                        return json(['code' => 0, 'info' => '添加权限记录失败！']);
                    }
                }

                $this->app->db->commit();
                sysoplog('积分墙列表', '添加成功');

                return json(['code' => 1, 'info' => '添加成功！']);
            } catch (\Exception $e) {
                $this->app->db->rollback();
                trace("添加包名异常：" . $e->getMessage());
                return json(['code' => 0, 'info' => '系统异常，请稍后重试！']);
            }
        }
    }

    /**
     * 编辑包名
     * @auth true
     * @menu true
     */
    public function edit()
    {
        if ($this->request->isPost()) {
            try {
                $data = $this->_vali([
                    'id.require' => '记录ID不能为空！',
                    'package_name.require' => '包名不能为空！',
                    'name.require' => '应用名称不能为空！',
                    'status.require' => '状态不能为空！',
                    'status.in:0,1' => '状态值不正确！'
                ]);

                // 检查权限
                if (!$this->checkPackageAuth($data['id'])) {
                    return json(['code' => 0, 'info' => '您没有操作此包名的权限！']);
                }
                
                // 检查包名是否已存在（排除当前记录）
                $exists = $this->app->db->name('offer_package')
                    ->where('package_name', $data['package_name'])
                    ->where('id', '<>', $data['id'])
                    ->find();
                if ($exists) {
                    return json(['code' => 0, 'info' => '包名已存在，请更换！']);
                }

                // 更新时间
                $data['update_time'] = time();
                $data['username'] = session('user.username') ?? '';

                $result = $this->app->db->name('offer_package')
                    ->where(['id' => $data['id']])
                    ->update($data);
                if ($result === false) {
                    return json(['code' => 0, 'info' => '更新失败，请重试！']);
                }
                sysoplog('积分墙列表', '更新成功');

                return json(['code' => 1, 'info' => '更新成功！']);
            } catch (\Exception $e) {
                trace("编辑包名异常：" . $e->getMessage());
                return json(['code' => 0, 'info' => '系统异常，请稍后重试！']);
            }
        }
    }

    /**
     * 删除包名
     * @auth true
     * @menu true
     */
    public function remove()
    {
        if ($this->request->isPost()) {
            // 开启事务
            $this->app->db->startTrans();
            try {
                $id = $this->request->param('id');
                if (empty($id)) {
                    return json(['code' => 0, 'info' => '参数错误，请刷新重试！']);
                }

                // 检查权限
                if (!$this->checkPackageAuth($id)) {
                    return json(['code' => 0, 'info' => '您没有操作此包名的权限！']);
                }
                
                // 删除包名记录
                $result = $this->app->db->name('offer_package')
                    ->where(['id' => $id])
                    ->delete();
                if ($result === false) {
                    $this->app->db->rollback();
                    return json(['code' => 0, 'info' => '删除失败，请重试！']);
                }

                // 同步删除权限表中的相关记录
                $this->app->db->name('offer_package_auth')
                    ->where(['package_id' => $id])
                    ->delete();

                $this->app->db->commit();
                sysoplog('积分墙列表', '删除成功');

                return json(['code' => 1, 'info' => '删除成功！']);
            } catch (\Exception $e) {
                $this->app->db->rollback();
                trace("删除包名异常：" . $e->getMessage());
                return json(['code' => 0, 'info' => '系统异常，请稍后重试！']);
            }
        }
    }

    /**
     * 切换状态
     * @auth true
     * @menu true
     */
    public function state()
    {
        if ($this->request->isPost()) {
            try {
                $data = $this->_vali([
                    'id.require' => '记录ID不能为空！',
                    'status.in:0,1' => '状态值不正确！'
                ]);
                
                // 检查权限
                if (!$this->checkPackageAuth($data['id'])) {
                    return json(['code' => 0, 'info' => '您没有操作此包名的权限！']);
                }
                
                // 检查记录是否存在
                $exists = $this->app->db->name('offer_package')
                    ->where(['id' => $data['id']])
                    ->find();
                
                if (empty($exists)) {
                    return json(['code' => 0, 'info' => '记录不存在！']);
                }
                
                // 更新状态
                $updateData = [
                    'status' => $data['status'],
                    'update_time' => time(),
                    'username' => session('user.username') ?? ''
                ];
                
                $result = $this->app->db->name('offer_package')
                    ->where(['id' => $data['id']])
                    ->update($updateData);
                    
                if ($result === false) {
                    return json(['code' => 0, 'info' => '状态更新失败，请重试！']);
                }
                sysoplog('积分墙列表', '状态更新成功');

                return json(['code' => 1, 'info' => '状态更新成功！']);
                
            } catch (\Exception $e) {
                trace("状态切换异常：" . $e->getMessage() . "\n" . $e->getTraceAsString());
                return json(['code' => 0, 'info' => '系统异常，请稍后重试！']);
            }
        }
    }

    /**
     * 生成测试数据
     * @auth true
     */
    public function generateTestData()
    {
        try {
            // 设置执行时间为无限制
            set_time_limit(0);
            ini_set('memory_limit', '1024M');

            // 开启事务
            $this->app->db->startTrans();
            try {
                $insertData = [];
                $existPackages = [];
                $total = 8000;  // 总记录数
                $batchSize = 500;  // 每批插入数量
                $startTime = time();
                
                // 获取已存在的包名，避免重复
                $exists = $this->app->db->name($this->table)
                    ->column('package_name');
                $existPackages = array_flip($exists);

                // 预生成一些常用词，提高应用名称的真实性
                $prefixes = ['Super', 'My', 'Fast', 'Smart', 'Easy', 'Pro', 'Best', 'Quick'];
                $suffixes = ['Browser', 'Player', 'Cleaner', 'Manager', 'Tool', 'Helper', 'App', 'Game'];
                $domains = ['com', 'net', 'org', 'app', 'tech', 'io'];

                // 生成记录
                for ($i = 0; $i < $total; $i++) {
                    // 生成唯一包名
                    do {
                        // 生成更真实的包名 xxx.xxx.xxx.xxx
                        $domain = $domains[array_rand($domains)];
                        $company = $this->generateRandomString(rand(3, 8));
                        $product = $this->generateRandomString(rand(3, 8));
                        $module = $this->generateRandomString(rand(3, 8));
                        $packageName = "{$domain}.{$company}.{$product}.{$module}";
                    } while (isset($existPackages[$packageName]));

                    $existPackages[$packageName] = 1;

                    // 生成更真实的应用名称
                    $prefix = $prefixes[array_rand($prefixes)];
                    $suffix = $suffixes[array_rand($suffixes)];
                    $appName = $prefix . ' ' . $suffix . ' ' . ($i + 1);

                    // 生成数据
                    $insertData[] = [
                        'package_name' => $packageName,
                        'name' => $appName,
                        'status' => rand(0, 1),  // 随机状态
                        'add_time' => time() - rand(0, 86400 * 30),  // 随机时间，最近30天内
                        'update_time' => time(),
                        'username' => session('user.username') ?? 'system'
                    ];

                    // 批量插入
                    if (count($insertData) >= $batchSize) {
                        $this->app->db->name($this->table)->insertAll($insertData);
                        $insertData = [];
                        
                        // 输出进度
                        $progress = round(($i + 1) / $total * 100, 2);
                        trace("数据生成进度：{$progress}%");
                    }
                }

                // 插入剩余数据
                if (!empty($insertData)) {
                    $this->app->db->name($this->table)->insertAll($insertData);
                }

                $endTime = time();
                $timeUsed = $endTime - $startTime;

                $this->app->db->commit();
                return json([
                    'code' => 1, 
                    'info' => "测试数据生成成功！共生成 {$total} 条记录，耗时 {$timeUsed} 秒"
                ]);
            } catch (\Exception $e) {
                $this->app->db->rollback();
                throw $e;
            }
        } catch (\Exception $e) {
            trace("生成测试数据异常：" . $e->getMessage() . "\n" . $e->getTraceAsString());
            return json(['code' => 0, 'info' => '系统异常：' . $e->getMessage()]);
        }
    }

    /**
     * 生成随机字符串
     * @param int $length 长度
     * @return string
     */
    private function generateRandomString($length = 5)
    {
        // 添加数字，使包名更真实
        $characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
        $result = '';
        
        // 第一个字符必须是字母
        $result .= $characters[rand(0, 25)];
        
        // 生成剩余字符
        for ($i = 1; $i < $length; $i++) {
            $result .= $characters[rand(0, strlen($characters) - 1)];
        }
        return $result;
    }
} 