<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Article;
use App\Models\Option;
use App\Services\TG\Http as TGHttp;
use App\Services\TomTool\Http as Http;
use App\Services\Github\Github as ServiceGithub;
use App\Services\Github\Blade as ServiceBlade;

class CronV2Controller
{
    
    private $sUserName;
    private $sProjectName;
    private $sMailName;
    private $sMailTail;
    
    private $sProjectPath;
    private $sProjectUrl;
    
    private $aArticle;
    
    private $isTest = 0;
    
    private $sSendTg = "y";
    
    private $sPull = "y";
    
    private function lifeToTg($h, $i, $s)
    {
        $oHttpTg = new TGHttp();
        
        if ($h == "08" && $i == "00") {
            $oArticle = Article::where("status", 1)->get();
            
            $aMsg = [];
            foreach ($oArticle as $oArticleRow) {
                $sMsgR = $this->_lifeToTg($oArticleRow);
                $aMsg[] = $sMsgR;
            }
            
            $oHttpTg->send($aMsg);
        }
    }
    
    private function _lifeToTg($oArticle)
    {
        $oHttp = new Http();
        $oHttp->sToUrl = "https://api.github.com/repos/".$oArticle->user_name."/".$oArticle->project_name;
        $oHttp->sMethod = "get";
        $r = $oHttp->send();
        
        $sMsg = "?";
        
        if (!$r) {
            $oHttpTg = new TGHttp();
            $oHttpTg->send("请求github的api失败？？");
        }
        
        $aGitHub = json_decode($r, true);
        
        if (isset($aGitHub["status"]) && $aGitHub["status"] == "404") {
            $aMsg["msg"] = "嘎了~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
            $aMsg["article"] = $oArticle;
            $sMsg = json_encode($aMsg, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
            return $sMsg;
        }
        
        $tmp = str_replace("T", " ", rtrim($aGitHub["updated_at"], "Z")); //updated_at, pushed_at
        $tmp = strtotime($tmp);
        $tmpDate = date("Y-m-d H:i:s", $tmp + (8 * 3600));
        $tmpTime = strtotime($tmpDate);
        $tmpNowTime = time();
        $tmpDiff = $tmpNowTime - $tmpTime;
        $iLastUpdate = ceil($tmpDiff / 60);
        
        $aGitHubNew = [];
        $aGitHubNew["⭐️星星"] = $aGitHub["stargazers_count"];
        $aGitHubNew["♻️最后更新"] = $iLastUpdate."分钟前"; // 替换T为空格并去掉Z
        $aGitHubNew["forks"] = $aGitHub["forks_count"];
        $aGitHubNew["watchers"] = $aGitHub["watchers_count"];
        $aGitHubNew["url"] = $this->urlFormat($aGitHub["html_url"]);
        
        $sMsg = json_encode($aGitHubNew, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        
        return $sMsg;
    }
    
    public function urlFormat($sUrl)
    {
        $sUrlNew = str_replace('/', '$', $sUrl);
        return $sUrlNew;
    }
    
    public function index()
    {
        try {
            
            $h = date("H");
            $i = date("i");
            $s = date("s");
            $iRand = rand(1, 1440);
            $aUpdate = [];
//            $bSendTg = true;
//            $isTest = 0;
            
            //// test
            $aGet = $_GET;
            if (isset($aGet['is_test']) && $aGet['is_test'] == 1) {
                $isTest = 1;
                $this->isTest = 1;
                $aUpdate["shell"] = "cmd";
                if ($aGet["time_type"] == 'i') {
                    $i = (string) $aGet['v'];
                } else if ($aGet["time_type"] == 'h') {
                    $h = (string) $aGet['v'];
                } else if ($aGet["time_type"] == "rand") {
                    $iRand = $aGet["v"];
                } else if ($aGet["time_type"] == "id") {
                    $iTestId = $aGet["v"];
                }
            }
            //// test
//            $h = "08";
//            $i = "00";
            
            $this->lifeToTg($h, $i, $s);
            
            if (isset($aGet["sSendTg"])) {
                $this->sSendTg = $aGet["sSendTg"];
            }
            
            if (isset($aGet["sPull"])) {
                $this->sPull = $aGet["sPull"];
            }
            
            // 暂停
//            $option = Option::where("type", "pause")->first();
            $option = Option::_hit("pause") ?? null;
            $isPause = isset($option->value) ? $option->value : null;
            if ($isPause == 1 && $isTest !== 1) {
                exit("暂停");
            }
            
            // id测试
            if (isset($iTestId)) {
                $aArticle = Article::where("id", $iTestId)->get()->toArray();
                if (!empty($aArticle)) {
                    $this->run($aArticle);
                } else {
                    exit("这个id没找到");
                }
                exit;
            }
            
            // i_in10规则
            $iIin10 = $i[1];
            $aArticle = Article::where("i_in10", $iIin10)->where("status", 1)->get()->toArray();
            if (!empty($aArticle)) {
                $this->run($aArticle);
            }
            
            // inday_count规则
//            $iRand = rand(1, 1440);
//            $iRand = 1;
            $oIndayArticle = Article::where("inday_count", ">=", $iRand)->where("status", 1)->get()->toArray(); // inday24 >= rand10
            if (!empty($oIndayArticle)) {
                $this->run($oIndayArticle);
            }
            
            // i%7==0
            $aConditions = Article::select('cron_condition')
                            ->where('status', 1)
                            ->distinct()
                            ->get()
                            ->toArray();

            foreach ($aConditions as $row) {
                
                $sCondition = $row['cron_condition'];
                
                if (!empty($sCondition) && eval("return $sCondition;")) {
                    
                    $aArticle = Article::where("cron_condition", $sCondition)->where("status", 1)->get()->toArray();
                    
                    $this->run($aArticle);
                    
                }
                
            }

        } catch (\Throwable $e) {
            
            $sMessage = "错误（文件: " . $e->getFile() . "，行: " . $e->getLine() . "）: " . $e->getMessage();
            
            $oTGHttp = new TGHttp();
            $oTGHttp->sendToTG($sMessage, $aUpdate);
            
        }
        
    }
    
    private function run($aArticle)
    {
        
        $shabi = "https://";
        
        if (env("www_master") == "dd.loc") {
            $shabi = "http://";
        }
//        echo 111;exit;
        foreach ($aArticle as $row) {
            $this->sUserName = $row["user_name"];
            $this->sMailName = $row["mail_name"];
            $this->sMailTail = $row["mail_tail"];
            $this->sProjectName = $row["project_name"];
            $this->sProjectPath = env("BASE_DIR")."github/".$this->sUserName."-".$this->sProjectName;
            $this->sProjectUrl = "git@".$this->sMailName.".com:".$this->sUserName."/".$this->sProjectName.".git";
            $this->aArticle = $row;
            $aArticleRow = $row;
            $sModType = $row["mod_type"] ?? "v1";
            $sMod = $row["mod"];
            
//            $oHttp->aData = $row;
//            $sReadMe = $oHttp->send($sMasterUrl);
            
            // 获取文章的方式
            if ($sModType == "v1") {
                
                $sReadMe = ServiceGithub::GetReadMe($row);
                
            // 新版
            } else {
                
                $oHttp = new Http();
                $oHttp->sMethod = "post";
                $sMasterUrl = $shabi.env("www_master")."/api/github/get";
//                $oHttp->bIsJson = true;
                $oHttp->aData = $row;
                $sReadMe = $oHttp->send($sMasterUrl);
                
            }
            
            // 没有文件夹，创建一个
            if (!is_dir($this->sProjectPath)) {
                
                mkdir($this->sProjectPath, 0755, true); // 0755 是权限，true 表示递归创建目录
                
                mkdir($this->sProjectPath."/feed", 0755, true);
                
            }
            
            // 没有文件夹，创建一个
            if (!is_dir($this->sProjectPath."/feed")) {
                
                mkdir($this->sProjectPath."/feed", 0755, true);
                
            }
            
            // 没有仓库，创建一个
            if (!is_dir($this->sProjectPath . "/.git")) {
                
                $this->gitInit();
                
                $this->sshConfigAdd();
                
            }
            
            // 请求cfn，更新订阅文件
            // 不管是是否真更新，cfn那边没更新就返回昨天的文件，一样用。
            $sFnCode = date("Ymd");
            //// test
            // 20250721 - 23 有数据
//            $sFnCode = 20250721;
            //// test end
            $oHttp = new Http();
            $oHttp->sMethod = "get";
//            $sMasterUrl = env("api_url_freenode_base")."/api/github/getfntoday/".$sFnCode;
//            /api/v1/freenode/url_feed_today/{siteCode}/{client?}
            $sMasterUrl = $shabi.env("www_master")."/api/v1/freenode/url_feed_today/".$row["fn_code_short"];
            $sReturn = $oHttp->send($sMasterUrl);
            $aReturn = json_decode($sReturn, true);

            if (!isset($aReturn["code"])) {
                exit("异常没有code -> {$sMasterUrl}:{$sReturn}");
            }
            
            if ($aReturn["code"] == "400") { // test
                exit("异常400");
            }
            
            if ($aReturn["code"] == "200") {
                file_put_contents($this->sProjectPath."/feed/clash-".$sFnCode.".yaml", file_get_contents("https://".$aReturn["data"]["clash"]));
                file_put_contents($this->sProjectPath."/feed/v2ray-".$sFnCode.".txt", file_get_contents("https://".$aReturn["data"]["v2ray"]));
                file_put_contents($this->sProjectPath."/feed/singbox-".$sFnCode.".txt", file_get_contents("https://".$aReturn["data"]["singbox"]));
            }
            
            // 写入内容
            if ($sReadMe) {
                file_put_contents($this->sProjectPath."/README.md", $this->formatstr($sReadMe));
            }
            
            file_put_contents($this->sProjectPath."/version.text", md5(time()));

            if ($this->sPull == "n") {
                exit("\n 不提交");
            }
            
            // 提交
            if ($this->sSendTg == "n") {
                $content = file_get_contents($this->sProjectPath."/README.md");
                echo $content;
                exit;
            } else {
                $this->gitPush();
            }
            
        }
    }
    
    private function sshConfigAdd()
    {
        
        // 定义要添加的配置
        $host = $this->sMailName;
        $hostname = "github.com";
        $user = "git";
        $identityFile = env("path_ssh")."/id_rsa_".$host;

        // 构建配置字符串
        $config = "\nHost ".$host.".com\n";
        $config .= "\tHostName $hostname\n";
        $config .= "\tUser $user\n";
        $config .= "\tIdentityFile $identityFile\n";

        // 指定 SSH 配置文件路径
        $sshConfigFile = env("path_ssh")."/config";

        // 检查文件是否存在，如果不存在则创建
        if (!file_exists($sshConfigFile)) {
            touch($sshConfigFile);
        }

        // 追加配置到文件
        file_put_contents($sshConfigFile, $config, FILE_APPEND | LOCK_EX);

        // 设置文件权限
        chmod($sshConfigFile, 0600);

        echo "SSH config updated successfully.\n";

    }
    
    private function formatstr($str)
    {
//        $str = substr($str, 1, -1);
        return $str;
    }
    
    private function runCommand($command, $show_error = 1) {
        $output = [];
        $returnVar = 0;
        exec($command, $output, $returnVar);
        
        if ($returnVar !== 0 && $this->aArticle['show_error'] == 1 && $show_error == 1) {
            
            $aMsg = [
                "命令" => $command,
                "结果" => json_encode($output),
                "文章" => $this->aArticle,
            ];
            
            throw new \Exception(json_encode($aMsg, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
        }
    }

    
    private function gitInit()
    {
        // 进入指定目录
        if (!chdir($this->sProjectPath)) {
            throw new \Exception("无法进入目录 {$this->sProjectPath}\n");
        }

        // 初始化 Git 仓库
        $this->runCommand('git init');

        // 添加安全目录
        $this->runCommand("git config --local --add safe.directory \"{$this->sProjectPath}\"");

        // 设置用户
        $this->runCommand("git config --local user.name \"{$this->sUserName}\"");
        $this->runCommand("git config --local user.email \"{$this->sMailName}@{$this->sMailTail}\""); //这里得改，直接tuta不行

        // 创建并切换到 main 分支
        $this->runCommand('git branch -M main');

        // 添加远程仓库
        $this->runCommand("git remote add origin \"{$this->sProjectUrl}\"");
        
        // 立即拉取覆盖一次
        $this->runCommand("git fetch origin", 0);
        $this->runCommand("git reset --hard origin/main", 0);
        
        echo "操作完成：以初始化仓库[".$this->aArticle['id']."]。\n";
        
    }
    
//    private function gitPullR()
//    {
//        // 进入指定目录
//        if (!chdir($this->sProjectPath)) {
//            echo "无法进入目录 {$this->sProjectPath}\n";
//            exit(1);
//        }
//
//        // 获取远程更新
//        $this->runCommand('git fetch origin');
//
//        // 硬重置到远程主分支
//        $this->runCommand('git reset --hard origin/main');
//
//        echo "操作完成：已重置到远程主分支。\n";
//    }
    
    private function gitPush()
    {
        // 进入指定目录
        if (!chdir($this->sProjectPath)) {
            throw new \Exception("无法进入目录 {$this->sProjectPath}\n");
        }

        // 添加更改到暂存区
        $this->runCommand('git add .');

        // 提交更改，使用当前日期作为提交信息
        $commitMessage = date('Y-m-d H:i:s'); // 使用当前日期和时间作为提交信息
        $this->runCommand("git commit -m \"$commitMessage\"");

        // 推送到远程主分支
        $this->runCommand('git push -u origin main --force'); // 确保将 'main' 替换为你的默认分支名称，  覆盖

        echo "操作完成：已提交并推送更改[".$this->aArticle['id']."]。\n";
    }
    
}
