<?php

namespace app\admin\service\setting;

use app\admin\service\AdminBaseService;
use app\model\StockBrlListModel;
use app\model\StockEurListModel;
use app\model\StockFurListModel;
use app\model\StockGBXListModel;
use app\model\StockHkdListModel;
use app\model\StockIdnListModel;
use app\model\StockInListModel;
use app\model\StockJpListModel;
use app\model\StockListModel;
use app\model\StockMarketModel;
use app\model\StockMysListModel;
use app\model\StockThaListModel;

// 股票市场
class StockMarketService extends AdminBaseService
{

    public function index()
    {
        try {
            $list = StockMarketModel::order('stock_market_type', 'asc')->select();
            $rows = [];
            if(!$list->isEmpty()){
                $rows = $list->toArray();
            }

            return $this->toData('0','SUCCESS', ['total' => count($rows), 'list' => $rows, 'extent' => [
                'stock_market_type_list' => StockMarketModel::STOCK_MARKET_TYPE,
                'trade_day_type' => StockMarketModel::TRADE_DAY_TYPE,
            ]]);
        }catch (\Exception $exception){
            return $this->toData('1', '系统繁忙', [$exception->getMessage()]);
        }
    }


    // 新增
    public function add($param)
    {
        try {
            $stockMarketTypeArr = StockMarketModel::STOCK_MARKET_TYPE;
            $tradeDayTypeArr = StockMarketModel::TRADE_DAY_TYPE;
            $stockMarketTypeKeys = array_keys($stockMarketTypeArr);
            $tradeDayTypeKeys = array_keys($tradeDayTypeArr);
            if(empty($param['stock_market_type']) || !in_array($param['stock_market_type'], $stockMarketTypeKeys)){
                return $this->toData('1', '股票市场类型无效', []);
            }

            // 判断是否已经存在
            $stockM = StockMarketModel::where('stock_market_type', $param['stock_market_type'])->find();
            if($stockM){
                return $this->toData('1', '股票市场类型已经存在', []);
            }

            $amOpenTime = '00:00';
            $amCloseTime = '00:00';
            $pmOpenTime = '00:00';
            $pmCloseTime = '00:00';
            $num = 0;
            if(isset($param['am_open_time']) && is_string($param['am_open_time'])){
                $amOpenTimestamp = strtotime($param['am_open_time']);
                if($amOpenTimestamp !== false && date('H:i', $amOpenTimestamp) === $param['am_open_time']){
                    $amOpenTime = $param['am_open_time'];
                    $num++;
                }
            }

            if(isset($param['am_close_time']) && is_string($param['am_close_time'])){
                $amCloseTimestamp = strtotime($param['am_close_time']);
                if($amCloseTimestamp !== false && date('H:i', $amCloseTimestamp) === $param['am_close_time']){
                    $amCloseTime = $param['am_close_time'];
                    $num++;
                }
            }

            if(isset($param['pm_open_time']) && is_string($param['pm_open_time'])){
                $pmOpenTimestamp = strtotime($param['pm_open_time']);
                if($pmOpenTimestamp !== false && date('H:i', $pmOpenTimestamp) === $param['pm_open_time']){
                    $pmOpenTime = $param['pm_open_time'];
                    $num++;
                }
            }

            if(isset($param['pm_close_time']) && is_string($param['pm_close_time'])){
                $pmCloseTimestamp = strtotime($param['pm_close_time']);
                if($pmCloseTimestamp !== false && date('H:i', $pmCloseTimestamp) === $param['pm_close_time']){
                    $pmCloseTime = $param['pm_close_time'];
                    $num++;
                }
            }


            if(empty($param['status']) || !in_array($param['status'], [StockMarketModel::STATUS_NO, StockMarketModel::STATUS_OFF])){
                return $this->toData('1', '状态类型无效', []);
            }

            // 如果是开启状态 必须设置开盘时间
            if($param['status'] == StockMarketModel::STATUS_NO && $num < 4){
                return $this->toData('1', '需要设置开盘时间', []);
            }

            // 货币单位
            if(empty($param['unit']) || !is_string($param['unit']) || strlen($param['unit']) > 10){
                return $this->toData('1', '货币单位无效', []);
            }

            // 货币符号
            if(empty($param['symbol']) || !is_string($param['symbol']) || strlen($param['symbol']) > 10){
                return $this->toData('1', '货币符号无效', []);
            }

            // 兑换汇率
            if(empty($param['rate']) || !is_numeric($param['rate']) || strlen($param['rate']) > 200){
                return $this->toData('1', '兑换汇率无效', []);
            }

            // 如果是开启状态必须设置 交易日限制 如果是关闭状态
            if($param['status'] == StockMarketModel::STATUS_NO){
                if(empty($param['trade_day_type']) || !in_array($param['trade_day_type'], $tradeDayTypeKeys)){
                    return $this->toData('1', '交易日限制无效', []);
                }
                $tradeDayType = $param['trade_day_type'];
            }else{
                if(empty($param['trade_day_type']) || !in_array($param['trade_day_type'], $tradeDayTypeKeys)){
                    $tradeDayType = 0;
                } else{
                    $tradeDayType = $param['trade_day_type'];
                }
            }

            // 设置股票杠杆
            $leverStatus = StockMarketModel::LEVER_STATUS_OFF;
            $stockMin = 0;
            $leverMin = 1;
            $leverMax = 1;
            if(!empty($param['lever_status']) && is_numeric($param['lever_status']) &&  $param['lever_status'] == StockMarketModel::LEVER_STATUS_ON){
                $leverStatus = $param['lever_status'];
                if(empty($param['stock_min']) || !is_numeric($param['stock_min']) || $param['stock_min'] <=0){
                    return $this->toData('1', '杠杆最小使用股数无效', []);
                }

                if(empty($param['lever_min']) || !is_numeric($param['lever_min']) || $param['lever_min'] <=0){
                    return $this->toData('1', '最小杠杆无效', []);
                }

                if(empty($param['lever_max']) || !is_numeric($param['lever_max']) || $param['lever_max'] <=0 || $param['lever_max'] < $param['lever_min']){
                    return $this->toData('1', '最大杠杆无效', []);
                }

                $stockMin = ceil($param['stock_min']);
                $leverMin = ceil($param['lever_min']);
                $leverMax = ceil($param['lever_max']);
            }


            $stockMarket = new StockMarketModel;
            $stockMarket->stock_market_type = $param['stock_market_type'];
            $stockMarket->status = $param['status'];
            $stockMarket->symbol = $param['symbol'];
            $stockMarket->unit = $param['unit'];
            $stockMarket->rate = $param['rate'];
            // 开盘时间
            $stockMarket->am_open_time = $amOpenTime;
            $stockMarket->am_close_time = $amCloseTime;
            $stockMarket->pm_open_time = $pmOpenTime;
            $stockMarket->pm_close_time = $pmCloseTime;
            $stockMarket->trade_day_type = $tradeDayType;
            $stockMarket->create_time = date('Y-m-d H:i:s');
            $stockMarket->update_time = date('Y-m-d H:i:s');

            $stockMarket->stock_min = $stockMin;
            $stockMarket->lever_min = $leverMin;
            $stockMarket->lever_max = $leverMax;
            $stockMarket->lever_status = $leverStatus;

            $stockMarket->save();

            // 缓存
            $list_key="STOCK_MARKET:LIST:" .$stockMarket->stock_market_type;
            $redis = $this->getRedis();
            $redis->del($list_key);
            $redis->hMset($list_key, [
                'id'=>$stockMarket->id,
                'stock_market_type'=>$stockMarket->stock_market_type,
                'trade_day_type'=>$stockMarket->trade_day_type,
                'unit'=>$stockMarket->unit,
                'rate'=>$stockMarket->rate,
                'symbol'=>$stockMarket->symbol,
                'status'=>$stockMarket->status,
                'am_open_time'=>$stockMarket->am_open_time,
                'am_close_time'=>$stockMarket->am_close_time,
                'pm_open_time'=>$stockMarket->pm_open_time,
                'pm_close_time'=>$stockMarket->pm_close_time,

                'lever_status' => $leverStatus,
                'stock_min' => $stockMin,
                'lever_min' => $leverMin,
                'lever_max' => $leverMax,

            ]);

            return $this->toData('0','SUCCESS');
        }catch (\Exception $exception){
            return $this->toData('1', '系统繁忙', [$exception->getMessage(),$exception->getLine()]);
        }
    }

    public function edit($param)
    {
        try {
            if(empty($param['id']) || !is_numeric($param['id'])){
                return $this->toData('1', '主键无效', []);
            }

            $stockMarket = StockMarketModel::where('id', $param['id'])->find();
            if(empty($stockMarket)){
                return $this->toData('1', '主键无效', []);
            }

            $tradeDayTypeArr = StockMarketModel::TRADE_DAY_TYPE;
            $tradeDayTypeKeys = array_keys($tradeDayTypeArr);


            // 状态
            if(empty($param['status']) || !in_array($param['status'], [StockMarketModel::STATUS_NO, StockMarketModel::STATUS_OFF])){
                return $this->toData('1', '状态类型无效', []);
            }

            $amOpenTime = '00:00';
            $amCloseTime = '00:00';
            $pmOpenTime = '00:00';
            $pmCloseTime = '00:00';
            $num = 0;
            if(isset($param['am_open_time']) && is_string($param['am_open_time'])){
                $amOpenTimestamp = strtotime($param['am_open_time']);
                if($amOpenTimestamp !== false && date('H:i', $amOpenTimestamp) === $param['am_open_time']){
                    $amOpenTime = $param['am_open_time'];
                    $num++;
                }
            }

            if(isset($param['am_close_time']) && is_string($param['am_close_time'])){
                $amCloseTimestamp = strtotime($param['am_close_time']);
                if($amCloseTimestamp !== false && date('H:i', $amCloseTimestamp) === $param['am_close_time']){
                    $amCloseTime = $param['am_close_time'];
                    $num++;
                }
            }

            if(isset($param['pm_open_time']) && is_string($param['pm_open_time'])){
                $pmOpenTimestamp = strtotime($param['pm_open_time']);
                if($pmOpenTimestamp !== false && date('H:i', $pmOpenTimestamp) === $param['pm_open_time']){
                    $pmOpenTime = $param['pm_open_time'];
                    $num++;
                }
            }

            if(isset($param['pm_close_time']) && is_string($param['pm_close_time'])){
                $pmCloseTimestamp = strtotime($param['pm_close_time']);
                if($pmCloseTimestamp !== false && date('H:i', $pmCloseTimestamp) === $param['pm_close_time']){
                    $pmCloseTime = $param['pm_close_time'];
                    $num++;
                }
            }

            // 如果是开启状态 必须设置开盘时间
            if($param['status'] == StockMarketModel::STATUS_NO && $num < 4){
                return $this->toData('1', '需要设置开盘时间', []);
            }


            // 货币单位
            if(empty($param['unit']) || !is_string($param['unit']) || strlen($param['unit']) > 10){
                return $this->toData('1', '货币单位无效', []);
            }

            // 货币符号
            if(empty($param['symbol']) || !is_string($param['symbol']) || strlen($param['symbol']) > 10){
                return $this->toData('1', '货币符号无效', []);
            }

            // 兑换汇率
            if(empty($param['rate']) || !is_numeric($param['rate']) || strlen($param['rate']) > 200){
                return $this->toData('1', '兑换汇率无效', []);
            }

            $tradeDayType = $stockMarket->trade_day_type;

            // 只有在没有设置过的情况下可以设置 设置之后不能修改
            if($tradeDayType == 0){
                if($param['status'] == StockMarketModel::STATUS_NO){
                    // 如果是开启状态 必须设置
                    if(empty($param['trade_day_type']) || !in_array($param['trade_day_type'], $tradeDayTypeKeys)){
                        return $this->toData('1', '交易日限制无效', []);
                    }
                    $tradeDayType = $param['trade_day_type'];
                }else{
                    // 关闭状态 可以不设置
                    if(!empty($param['trade_day_type']) && in_array($param['trade_day_type'], $tradeDayTypeKeys)){
                        $tradeDayType = $param['trade_day_type'];
                    } else{
                        $tradeDayType = 0;
                    }
                }
            }

            // 设置股票杠杆
            $leverStatus = StockMarketModel::LEVER_STATUS_OFF;
            $stockMin = 0;
            $leverMin = 1;
            $leverMax = 1;
            if(!empty($param['lever_status']) && is_numeric($param['lever_status']) &&  $param['lever_status'] == StockMarketModel::LEVER_STATUS_ON){
                $leverStatus = $param['lever_status'];
                if(empty($param['stock_min']) || !is_numeric($param['stock_min']) || $param['stock_min'] <=0){
                    return $this->toData('1', '杠杆最小使用股数无效', []);
                }

                if(empty($param['lever_min']) || !is_numeric($param['lever_min']) || $param['lever_min'] <=0){
                    return $this->toData('1', '最小杠杆无效', []);
                }

                if(empty($param['lever_max']) || !is_numeric($param['lever_max']) || $param['lever_max'] <=0 || $param['lever_max'] < $param['lever_min']){
                    return $this->toData('1', '最大杠杆无效', []);
                }



            }
            $stockMin = ceil($param['stock_min']);
            $leverMin = ceil($param['lever_min']);
            $leverMax = ceil($param['lever_max']);


            $stockMarket->status = $param['status'];
            $stockMarket->trade_day_type = $tradeDayType;
            $stockMarket->symbol = $param['symbol'];
            $stockMarket->unit = $param['unit'];
            $stockMarket->rate = $param['rate'];
            $stockMarket->am_open_time = $amOpenTime;
            $stockMarket->am_close_time = $amCloseTime;
            $stockMarket->pm_open_time = $pmOpenTime;
            $stockMarket->pm_close_time = $pmCloseTime;
            $stockMarket->trade_day_type = $tradeDayType;
            $stockMarket->update_time = date('Y-m-d H:i:s');

            $stockMarket->stock_min = $stockMin;
            $stockMarket->lever_min = $leverMin;
            $stockMarket->lever_max = $leverMax;
            $stockMarket->lever_status = $leverStatus;

            $stockMarket->save();

            // 缓存
            $list_key="STOCK_MARKET:LIST:" .$stockMarket->stock_market_type;
            $redis = $this->getRedis();
            $redis->del($list_key);
            $redis->hMset($list_key, [
                'id'=>$stockMarket->id,
                'stock_market_type'=>$stockMarket->stock_market_type,
                'trade_day_type'=>$stockMarket->trade_day_type,
                'status'=>$stockMarket->status,
                'symbol'=>$stockMarket->symbol,
                'unit'=>$stockMarket->unit,
                'rate'=>$stockMarket->rate,
                'am_open_time'=>$stockMarket->am_open_time,
                'am_close_time'=>$stockMarket->am_close_time,
                'pm_open_time'=>$stockMarket->pm_open_time,
                'pm_close_time'=>$stockMarket->pm_close_time,

                'lever_status' => $leverStatus,
                'stock_min' => $stockMin,
                'lever_min' => $leverMin,
                'lever_max' => $leverMax,
            ]);
            $arr=$redis->hGetAll($list_key);

            return $this->toData('0','SUCCESS',$arr);
        }catch (\Exception $exception){
            return $this->toData('1', '系统繁忙', [$exception->getMessage()]);
        }
    }


    // 股票筛选 根据股票号 股票市场 模糊搜索股票数据
    public function searchStock($param)
    {
        try {
            $marketTypeList = StockMarketModel::STOCK_MARKET_TYPE;
            if(empty($param['market_type']) || !in_array($param['market_type'], array_keys($marketTypeList))){
                return $this->toData('1', '股票市场无效', []);
            }

            $where = [];
            if(empty($param['page']) || !is_numeric($param['page']) || ceil($param['page']) != $param['page'] || $param['page'] <= 0){
                return $this->toData('1', '分页参数无效', []);
            }

            if(empty($param['limit']) || !is_numeric($param['limit']) || ceil($param['limit']) != $param['limit'] || $param['limit'] <= 0){
                return $this->toData('1', '分页参数无效', []);
            }

            if(!empty($param['stock_code']) && is_string($param['stock_code'])){
                $where[] = ['stock_code', 'like', '%'.$param['stock_code']];
            }

            switch ($param['market_type'])
            {
                // 美股
                case StockMarketModel::STOCK_MARKET_USA:
                    $stockList = StockListModel::where($where)->page($param['page'], $param['limit'])->select();
                    $total = StockListModel::where($where)->count();
                    break;
                case StockMarketModel::STOCK_MARKET_YNG:
                    $stockList = StockIdnListModel::where($where)->page($param['page'], $param['limit'])->select();
                    $total = StockIdnListModel::where($where)->count();
                    break;
                case StockMarketModel::STOCK_MARKET_MG:
                    $stockList = StockMysListModel::where($where)->page($param['page'], $param['limit'])->select();
                    $total = StockMysListModel::where($where)->count();
                    break;
                case StockMarketModel::STOCK_MARKET_TG:
                    $stockList = StockThaListModel::where($where)->page($param['page'], $param['limit'])->select();
                    $total = StockThaListModel::where($where)->count();
                    break;
                case StockMarketModel::STOCK_MARKET_IN:
                    $stockList = StockInListModel::where($where)->page($param['page'], $param['limit'])->select();
                    $total = StockInListModel::where($where)->count();
                    break;
                case StockMarketModel::STOCK_MARKET_HK:
                    $stockList = StockHkdListModel::where($where)->page($param['page'], $param['limit'])->select();
                    $total = StockHkdListModel::where($where)->count();
                    break;
                case StockMarketModel::STOCK_MARKET_UK:
                    $stockList = StockGBXListModel::where($where)->page($param['page'], $param['limit'])->select();
                    $total = StockGBXListModel::where($where)->count();
                    break;
                case StockMarketModel::STOCK_MARKET_FUR:
                    $stockList = StockFurListModel::where($where)->page($param['page'], $param['limit'])->select();
                    $total = StockFurListModel::where($where)->count();
                    break;
                case StockMarketModel::STOCK_MARKET_EUR:
                    $stockList = StockEurListModel::where($where)->page($param['page'], $param['limit'])->select();
                    $total = StockEurListModel::where($where)->count();
                    break;
                case StockMarketModel::STOCK_MARKET_BRL:
                    $stockList = StockBrlListModel::where($where)->page($param['page'], $param['limit'])->select();
                    $total = StockBrlListModel::where($where)->count();
                    break;
                case StockMarketModel::STOCK_MARKET_JP:
                    $stockList = StockJpListModel::where($where)->page($param['page'], $param['limit'])->select();
                    $total = StockJpListModel::where($where)->count();
                    break;
                default:
                    return $this->toData('1', '股票市场无效', []);
            }

            $rows = [];
            if(!$stockList->isEmpty()){
                $rows = $stockList->toArray();
            }

            return $this->toData('0','SUCCESS', ['total' => $total, 'list' => $rows, 'extent' => [
                'stock_market_type_list' => StockMarketModel::STOCK_MARKET_TYPE,
                'trade_day_type' => StockMarketModel::TRADE_DAY_TYPE,
            ]]);
        }catch (\Exception $exception){
            return $this->toData('1', '系统繁忙', [$exception->getMessage()]);
        }
    }

    // 根据股票市场 股票主键 查询股票
    public function searchStockById($param)
    {
        $marketTypeList = StockMarketModel::STOCK_MARKET_TYPE;
        if(empty($param['market_type']) || !in_array($param['market_type'], array_keys($marketTypeList))){
            return [];
        }

        if(empty($param['stock_id']) || !is_numeric($param['stock_id'])){
            return [];
        }


        switch ($param['market_type'])
        {
            // 美股
            case StockMarketModel::STOCK_MARKET_USA:
                $stock = StockListModel::where('id', $param['stock_id'])->find();
                break;
            case StockMarketModel::STOCK_MARKET_YNG:
                $stock = StockIdnListModel::where('id', $param['stock_id'])->find();
                break;
            case StockMarketModel::STOCK_MARKET_MG:
                $stock = StockMysListModel::where('id', $param['stock_id'])->find();
                break;
            case StockMarketModel::STOCK_MARKET_TG:
                $stock = StockThaListModel::where('id', $param['stock_id'])->find();
                break;
            case StockMarketModel::STOCK_MARKET_IN:
                $stock = StockInListModel::where('id', $param['stock_id'])->find();
                break;
            case StockMarketModel::STOCK_MARKET_HK:
                $stock = StockHkdListModel::where('id', $param['stock_id'])->find();
                break;
            case StockMarketModel::STOCK_MARKET_UK:
                $stock = StockGBXListModel::where('id', $param['stock_id'])->find();
                break;
            case StockMarketModel::STOCK_MARKET_FUR:
                $stock = StockFurListModel::where('id', $param['stock_id'])->find();
                break;
            case StockMarketModel::STOCK_MARKET_EUR:
                $stock = StockEurListModel::where('id', $param['stock_id'])->find();
                break;
            case StockMarketModel::STOCK_MARKET_BRL:
                $stock = StockBrlListModel::where('id', $param['stock_id'])->find();
                break;
            case StockMarketModel::STOCK_MARKET_JP:
                $stock = StockJpListModel::where('id', $param['stock_id'])->find();
                break;
            default:
                return [];
        }

        if(empty($stock)){
            return [];
        }
        return $stock->toArray();
    }
}