public function __construct()
    {
        $this->config = config('jira');
        $this->initializeJiraClient();
    }

/**
     * @throws JiraException
     */
    private function initializeJiraClient(): void
    {
        $clientConfig = new ArrayConfiguration([
            'jiraHost' => $this->config['host'],
            'jiraUser' => $this->config['username'],
            'jiraPassword' => $this->config['auth_type'] === 'token'
                ? $this->config['api_token']
                : $this->config['password'],
            'timeout' => $this->config['timeout'],
        ]);

        $this->issueService = new IssueService($clientConfig);
        $this->projectService = new ProjectService($clientConfig);
    }

/**
     * 按项目组织任务数据
     */
    private function organizeIssuesByProject(array $issues): Collection
    {
        $organized = collect();

        foreach ($issues as $issue) {
            $projectKey = $issue->fields->project->key;
            $isSubtask = $issue->fields->issuetype->subtask ?? false;

            if (!$organized->has($projectKey)) {
                $organized->put($projectKey, [
                    'name' => $issue->fields->project->name,
                    'tasks' => collect(),
                ]);
            }

            if ($isSubtask && isset($issue->fields->parent)) {
                // 子任务
                $parentKey = $issue->fields->parent->key;
                $this->addSubtask($organized[$projectKey]['tasks'], $parentKey, $issue);
            } else {
                // 主任务
                $this->addMainTask($organized[$projectKey]['tasks'], $issue);
            }
        }

        return $organized;
    }

/**
     * 获取单个任务的详细信息
     */
    private function getIssueDetails(string $issueKey): ?object
    {
        try {
            return $this->issueService->get($issueKey, [
                'summary',
                'status',
                'project',
                'issuetype'
            ]);
        } catch (JiraException) {
            return null;
        }
    }

private function addMainTask(Collection $tasks, $issue): void
    {
        $tasks->put($issue->key, [
            'key' => $issue->key,
            'summary' => $issue->fields->summary,
            'url' => $this->config['host'] . '/browse/' . $issue->key,
            'subtasks' => collect(),
        ]);
    }

$parentSummary = $parentDetails ? $parentDetails->fields->summary : '父任务';

private function addSubtask(Collection $tasks, string $parentKey, $issue): void
    {
        if (!$tasks->has($parentKey)) {
            // 获取父任务的真实信息
            $parentDetails = $this->getIssueDetails($parentKey);
            $parentSummary = $parentDetails ? $parentDetails->fields->summary : '父任务';

            $tasks->put($parentKey, [
                'key' => $parentKey,
                'summary' => $parentSummary,
                'url' => $this->config['host'] . '/browse/' . $parentKey,
                'subtasks' => collect(),
            ]);
        }

        $tasks[$parentKey]['subtasks']->put($issue->key, [
            'created' => $issue->fields->created ?? null,
        ]);
    }

/**
     * 获取未来一周的任务
     */
    public function getNextWeekTasks(?string $username = null): Collection
    {
        $username = $username ?: $this->config['default_user'];

        if (!$username) {
            throw new \InvalidArgumentException('用户名不能为空');
        }

        // 定义已完成的状态列表（需要排除的状态）
        $completedStatuses = [
            'Done',
            '已上线',
            '已完成',
        ];
        $statusExclusion = implode('", "', $completedStatuses);

        // 查询分配给用户且未完成的需求（Story/需求类型，不包括子任务）
        $jql = sprintf(
            'assignee = "%s" AND status NOT IN ("%s") AND issuetype in ("Story", "需求") ORDER BY created ASC',
            $username,
            $statusExclusion
        );

        try {
            $issues = $this->issueService->search($jql, 0, 50, [
                'status',
                'issuetype',
                'created'
            ]);

            if (!empty($issues->issues)) {
                return $this->organizeIssuesByProject($issues->issues);
            }
        } catch (JiraException $e) {
            throw new \RuntimeException('获取未来任务失败: ' . $e->getMessage());
        }

        return collect();
    }

$workLogs = $this->getWorkLogs($username, $startOfWeek, $endOfWeek);

$organizedTasks = $this->organizeTasksForReport($workLogs, $username);

$left, $right) => strnatcasecmp((string) $left, (string) $right)

static fn ($left, $right) => strnatcasecmp((string) $left, (string) $right)

$checkbox = $this->isTaskCompleted($task['status']) ? '[x]' : '[ ]';

$subtaskCheckbox = $this->isTaskCompleted($subtask['status']) ? '[x]' : '[ ]';

function ($bug) {
                        return $bug['parent_key'] ?? 'standalone';
                    });

$checkbox = $this->isTaskCompleted($bug['status']) ? '[x]' : '[ ]';

/**
     * 生成 Markdown 格式的周报
     */
    public function generateWeeklyReport(?string $username = null): string
    {

        // 获取上周的工时记录
        $now = Carbon::now();
        $startOfWeek = $now->copy()->subWeek()->startOfWeek();
        $endOfWeek = $now->copy()->subWeek()->endOfWeek();

        $workLogs = $this->getWorkLogs($username, $startOfWeek, $endOfWeek);
        $organizedTasks = $this->organizeTasksForReport($workLogs, $username);

        $nextWeekTasks = $this->getNextWeekTasks($username);

        $markdown = "# 过去一周的任务\n\n";

        if ($organizedTasks->isEmpty()) {
            $markdown .= "本周暂无工时记录的任务。\n\n";
        } else {
            // 按Sprint分类的需求
            if ($organizedTasks->has('sprints') && $organizedTasks['sprints']->isNotEmpty()) {
                $sortedSprints = $organizedTasks['sprints']->sortKeysUsing(
                    static fn ($left, $right) => strnatcasecmp((string) $left, (string) $right)
                );
                foreach ($sortedSprints as $sprintName => $tasks) {
                    $markdown .= "### {$sprintName}\n";
                    foreach ($tasks as $task) {
                        $checkbox = $this->isTaskCompleted($task['status']) ? '[x]' : '[ ]';
                        $markdown .= "- {$checkbox} [{$task['key']}]({$task['url']}) {$task['summary']}\n";

                        if ($task['subtasks']->isNotEmpty()) {
                            // 按创建时间排序子任务
                            $sortedSubtasks = $task['subtasks']->sortBy('created');
                            foreach ($sortedSubtasks as $subtask) {
                                $subtaskCheckbox = $this->isTaskCompleted($subtask['status']) ? '[x]' : '[ ]';
                                $markdown .= "    - {$subtaskCheckbox} [{$subtask['key']}]({$subtask['url']}) {$subtask['summary']}\n";
                            }
                        }
                    }
                    $markdown .= "\n";
                }
            }

            // 没有Sprint的需求
            if ($organizedTasks->has('stories') && $organizedTasks['stories']->isNotEmpty()) {
                $markdown .= "### 需求\n";
                foreach ($organizedTasks['stories'] as $task) {
                    $checkbox = $this->isTaskCompleted($task['status']) ? '[x]' : '[ ]';
                    $markdown .= "- {$checkbox} [{$task['key']}]({$task['url']}) {$task['summary']}\n";

                    if ($task['subtasks']->isNotEmpty()) {
                        // 按创建时间排序子任务
                        $sortedSubtasks = $task['subtasks']->sortBy('created');
                        foreach ($sortedSubtasks as $subtask) {
                            $subtaskCheckbox = $this->isTaskCompleted($subtask['status']) ? '[x]' : '[ ]';
                            $markdown .= "    - {$subtaskCheckbox} [{$subtask['key']}]({$subtask['url']}) {$subtask['summary']}\n";
                        }
                    }
                }
                $markdown .= "\n";
            }

            // 单独列出的任务
            if ($organizedTasks->has('tasks') && $organizedTasks['tasks']->isNotEmpty()) {
                $markdown .= "### 任务\n";
                foreach ($organizedTasks['tasks'] as $task) {

                        }
                    }
                }
            }

            // 按发现阶段分类的Bug
            if ($organizedTasks->has('bugs') && $organizedTasks['bugs']->isNotEmpty()) {
                foreach ($organizedTasks['bugs'] as $stage => $bugs) {
                    $markdown .= "### {$stage}\n";

                    // 按父任务分组Bug
                    $groupedBugs = collect($bugs)->groupBy(function ($bug) {
                    });

                    foreach ($groupedBugs as $parentKey => $bugGroup) {
                        if ($parentKey === 'standalone') {
                            // 独立的Bug
                            foreach ($bugGroup as $bug) {
                                $checkbox = $this->isTaskCompleted($bug['status']) ? '[x]' : '[ ]';
                                $summary = $this->cleanSummary($bug['summary']);
                                // 只标记非代码错误的Bug类型，并附加修复描述
                                $bugTypeLabel = '';
                                if ($bug['bug_type'] && $bug['bug_type'] !== '代码错误') {
                                    $bugTypeLabel = "\n    - {$bug['bug_type']}";
                                    if ($bug['bug_description']) {
                                        $bugTypeLabel .= "；{$bug['bug_description']}";
                                    }
                                }
                                $markdown .= "- {$checkbox} [{$bug['key']}]({$bug['url']}) {$summary}{$bugTypeLabel}\n";
                            }
                        } else {
                            // 有父任务的Bug
                            $firstBug = $bugGroup->first();
                            $markdown .= "- [x] {$firstBug['parent_summary']}\n";
                                    $bugTypeLabel = "\n        - {$bug['bug_type']}";
                                    }
                                }
                                $markdown .= "  - {$checkbox} [{$bug['key']}]({$bug['url']}) {$summary}{$bugTypeLabel}\n";
                            }
                        }
                    }
                }
            }
        }

        $markdown .= "\n# 未来一周的任务\n\n";

        foreach ($nextWeekTasks as $project) {
            foreach ($project['tasks'] as $task) {
                $markdown .= "- [ ] [{$task['key']}]({$task['url']}) {$task['summary']}\n";
            }
        }

        return $markdown;
    }

string $username, Carbon $startDate, Carbon $endDate): Collection

$workLogs = $this->extractWorkLogs($issues->issues, $username, $startDate, $endDate);

/**
     * 获取指定日期范围内的工时记录
     */
    public function getWorkLogs(string $username, Carbon $startDate, Carbon $endDate): Collection
    {
        // 标准工时查询 - 注意：某些JIRA版本可能不支持worklogAuthor和worklogDate
            'worklogAuthor = "%s" AND worklogDate >= "%s" AND worklogDate <= "%s" ORDER BY updated DESC',
            $startDate->format('Y-m-d'),
            $endDate->format('Y-m-d')
        );

        try {
            $issues = $this->issueService->search($jql, 0, 100, [
                'worklog',
                'parent',
                'status',
                'created',
                'fixVersions',
                'labels',
                'assignee',             // 经办人
                'customfield_10004',    // Sprint字段
                'customfield_10900',    // Bug发现阶段
                'customfield_11000',    // 开发人
                'customfield_11301',    // 实际修复人
                'customfield_12700',    // Bug错误类型
                'customfield_10115',    // Bug修复描述
                'customfield_14305',    // 需求类型
            ]);

                $workLogs = $this->extractWorkLogs($issues->issues, $username, $startDate, $endDate);

                if ($workLogs->isNotEmpty()) {
                    return $workLogs;
                }
            }
            throw new \RuntimeException('获取工时记录失败: ' . $e->getMessage());
        }
        // 如果所有查询都没有结果，返回空集合
    }

array $issues, string $username, Carbon $startDate, Carbon $endDate): Collection

$authorName = is_array($worklog->author) ? ($worklog->author['name'] ?? '') : ($worklog->author->name ?? '');

/**
     * 提取工时记录
     */
    private function extractWorkLogs(array $issues, string $username, Carbon $startDate, Carbon $endDate): Collection
    {
        $workLogs = collect();

            try {
                $worklogData = $this->issueService->getWorklog($issue->key);

                foreach ($worklogData->worklogs as $worklog) {
                    try {
                        $worklogDate = Carbon::parse($worklog->started);

                        // 处理 author 可能是数组或对象的情况
                        $authorName = is_array($worklog->author) ? ($worklog->author['name'] ?? '') : ($worklog->author->name ?? '');

                        if (!empty($authorName) && $authorName === $username &&
                            $worklogDate->between($startDate, $endDate)) {

                            // 获取父任务信息
                            $parentTask = null;
                            if (isset($issue->fields->parent)) {
                                $parentTask = [
                                    'key' => $issue->fields->parent->key ?? '',
                                    'summary' => $issue->fields->parent->fields->summary ?? '',
                                ];
                            }

                            // 提取Sprint信息
                            $sprint = $this->extractSprintInfo($issue);

                            // 提取Bug相关信息
                            $bugStage = $this->extractBugStage($issue);
                            $bugType = $this->extractBugType($issue);
                            $bugDescription = $this->extractBugDescription($issue);

                            // 提取需求类型
                            $requirementType = $this->extractRequirementType($issue);

                            // 提取经办人、开发人、实际修复人
                            $assignee = $this->extractAssignee($issue);
                            $developer = $this->extractDeveloper($issue);
                            $actualFixer = $this->extractActualFixer($issue);

                            $workLogs->push([
                                'id' => $worklog->id ?? '',
                                'project' => $issue->fields->project->name ?? '',
                                'project_key' => $issue->fields->project->key ?? '',
                                'issue_key' => $issue->key,
                                'issue_summary' => $issue->fields->summary ?? '',
                                'issue_url' => $this->config['host'] . '/browse/' . $issue->key,
                                'issue_status' => $issue->fields->status->name ?? 'Unknown',
                                'issue_type' => $issue->fields->issuetype->name ?? 'Unknown',
                                'issue_created' => $issue->fields->created ?? null,
                                'parent_task' => $parentTask,
                                'sprint' => $sprint,
                                'bug_stage' => $bugStage,
                                'bug_type' => $bugType,
                                'bug_description' => $bugDescription,
                                'requirement_type' => $requirementType,
                                'assignee' => $assignee,
                                'developer' => $developer,
                                'actual_fixer' => $actualFixer,
                                'date' => $worklogDate->format('Y-m-d'),
                                'time' => $worklogDate->format('H:i'),
                                'hours' => round(($worklog->timeSpentSeconds ?? 0) / 3600, 2),
                                'time_spent_seconds' => $worklog->timeSpentSeconds ?? 0,
                                'time_spent' => $worklog->timeSpent ?? '',
                                'comment' => $worklog->comment ?? '',
                                'author' => [
                                    'name' => $authorName,
                                    'display_name' => is_array($worklog->author) ? ($worklog->author['displayName'] ?? '') : ($worklog->author->displayName ?? ''),
                                    'email' => is_array($worklog->author) ? ($worklog->author['emailAddress'] ?? '') : ($worklog->author->emailAddress ?? ''),
                                ],
                                'created' => isset($worklog->created) ? Carbon::parse($worklog->created)->format('Y-m-d H:i:s') : '',
                                'updated' => isset($worklog->updated) ? Carbon::parse($worklog->updated)->format('Y-m-d H:i:s') : '',
                                'started' => $worklogDate->format('Y-m-d H:i:s'),
                            ]);
                        }
                    } catch (\Exception) {
                        // 跳过有问题的工时记录
                        continue;
                    }
                }
            } catch (JiraException) {
                // 跳过无法获取工时记录的任务
                continue;
            }
        }

        return $workLogs->sortByDesc('date');
    }

$sprintField = $issue->fields->customFields['customfield_10004'];

/**
     * 提取Sprint信息
     */
    private function extractSprintInfo($issue): ?string
    {
        // 尝试从customfield_10004获取Sprint信息
        if (isset($issue->fields->customFields['customfield_10004'])) {
            $sprintField = $issue->fields->customFields['customfield_10004'];

            // 处理数组情况
            if (is_array($sprintField) && !empty($sprintField)) {
                $lastSprint = end($sprintField);
                if (is_string($lastSprint)) {
                    // 解析Sprint字符串，格式通常为: com.atlassian.greenhopper.service.sprint.Sprint@xxx[name=十月中需求,...]
                    if (preg_match('/name=([^,\]]+)/', $lastSprint, $matches)) {
                        return $matches[1];
                    }
                } elseif (is_object($lastSprint) && isset($lastSprint->name)) {
                    return $lastSprint->name;
                }
            }

            // 处理对象情况
            if (is_object($sprintField) && isset($sprintField->name)) {
                return $sprintField->name;
            }

            // 处理字符串情况
            if (is_string($sprintField)) {
                if (preg_match('/name=([^,\]]+)/', $sprintField, $matches)) {
                    return $matches[1];
                }
                // 如果是纯文本，直接返回
                return $sprintField;
            }
        }

        // 尝试从fixVersions获取版本信息作为备选
        if (isset($issue->fields->fixVersions) && is_array($issue->fields->fixVersions) && !empty($issue->fields->fixVersions)) {
            return $issue->fields->fixVersions[0]->name ?? null;
        }

        // 尝试从summary中提取Sprint信息（如果summary包含【十月中需求】这样的标记）
        if (isset($issue->fields->summary)) {
            $summary = $issue->fields->summary;
            // 匹配【xxx需求】或【xxx】格式
            if (preg_match('/【([^】]*需求)】/', $summary, $matches)) {
                return $matches[1];
            }
        }

        return null;
    }

/**
     * 提取Bug发现阶段
     */
    private function extractBugStage($issue): ?string
    {
        // 从customfield_10900获取Bug阶段
        if (isset($issue->fields->customFields['customfield_10900'])) {
            $stage = $issue->fields->customFields['customfield_10900'];

            // 处理对象类型
            if (is_object($stage) && isset($stage->value)) {
                $stageValue = $stage->value;
            } elseif (is_string($stage)) {
                $stageValue = $stage;
            } else {
                $stageValue = null;
            }

            if ($stageValue && !empty($stageValue)) {
                // 标准化阶段名称
                if (str_contains($stageValue, 'SIT') || str_contains($stageValue, 'sit') || $stageValue === '测试阶段') {
                    return 'SIT环境BUG';
                }
                if (str_contains($stageValue, '生产') || str_contains($stageValue, 'PROD') || str_contains($stageValue, 'prod') || $stageValue === '生产环境') {
                    return '生产环境BUG';
                }
                if (str_contains($stageValue, 'UAT') || str_contains($stageValue, 'uat')) {
                    return 'UAT环境BUG';
                }
                // 如果不匹配标准格式，直接返回原值
                return $stageValue . 'BUG';
            }
        }

        // 从labels中提取Bug阶段
        if (isset($issue->fields->labels) && is_array($issue->fields->labels)) {
            foreach ($issue->fields->labels as $label) {
                if (str_contains($label, 'SIT') || str_contains($label, 'sit')) {
                }
                if (str_contains($label, '生产') || str_contains($label, 'PROD') || str_contains($label, 'prod')) {
                }
                if (str_contains($label, 'UAT') || str_contains($label, 'uat')) {
                }
            }
        }

    }

$bugTypes = ['需求未说明', '沟通问题', '接口文档未说明', '数据问题', '配置问题', '环境问题'];

/**
     * 提取Bug错误类型
     */
    private function extractBugType($issue): ?string
    {
        // 从customfield_12700获取Bug类型
        if (isset($issue->fields->customFields['customfield_12700'])) {
            $type = $issue->fields->customFields['customfield_12700'];

            // 处理对象类型
            if (is_object($type) && isset($type->value)) {
                return $type->value;
            } elseif (is_string($type) && !empty($type)) {
                return $type;
            }
        }

        // 从labels中提取Bug类型
            $bugTypes = ['需求未说明', '沟通问题', '接口文档未说明', '数据问题', '配置问题', '环境问题'];
                foreach ($bugTypes as $bugType) {
                    if (str_contains($label, $bugType)) {
                        return $bugType;
                    }
                }
            }
        }

    }

$description = $issue->fields->customFields['customfield_10115'];

/**
     * 提取Bug修复描述
     */
    private function extractBugDescription($issue): ?string
    {
        // 从customfield_10115获取Bug修复描述
        if (isset($issue->fields->customFields['customfield_10115'])) {
            $description = $issue->fields->customFields['customfield_10115'];

            if (is_string($description) && !empty($description)) {
                return $description;
            }
        }

    }

/**
     * 提取需求类型
     */
    private function extractRequirementType($issue): ?string
    {
        // 从customfield_14305获取需求类型
        if (isset($issue->fields->customFields['customfield_14305'])) {
            $type = $issue->fields->customFields['customfield_14305'];
            if (is_array($type) && !empty($type)) {
                $firstType = $type[0];
                if (is_object($firstType) && isset($firstType->value)) {
                    return $firstType->value;
                }
            } elseif (is_object($type) && isset($type->value)) {
            } elseif (is_string($type)) {
            }
        }

    }

/**
     * 提取经办人
     */
    private function extractAssignee($issue): ?string
    {
        // 从assignee字段获取经办人
        if (isset($issue->fields->assignee)) {
            $assignee = $issue->fields->assignee;

            // 处理对象类型
            if (is_object($assignee)) {
                return $assignee->name ?? $assignee->key ?? null;
            } elseif (is_string($assignee)) {
                return $assignee;
            }
        }

    }

/**
     * 提取开发人
     */
    private function extractDeveloper($issue): ?string
    {
        // 从customfield_11000获取开发人
        if (isset($issue->fields->customFields['customfield_11000'])) {
            $developer = $issue->fields->customFields['customfield_11000'];

            if (is_string($developer) && !empty($developer)) {
                return $developer;
            }
        }

    }

/**
     * 提取实际修复人
     */
    private function extractActualFixer($issue): ?string
    {
        // 从customfield_11301获取实际修复人
        if (isset($issue->fields->customFields['customfield_11301'])) {
            $fixer = $issue->fields->customFields['customfield_11301'];

            if (is_string($fixer) && !empty($fixer)) {
                return $fixer;
            }
        }

    }

$summary = preg_replace('/!([^!]+\.(png|jpg|jpeg|gif|bmp))!/i', '', $summary);

/**
     * 清理摘要中的图片链接
     */
    private function cleanSummary(string $summary): string
    {
        // 移除 Jira 图片标记 !image-xxx.png! 和 !https://xxx.png!
        $summary = preg_replace('/!([^!]+\.(png|jpg|jpeg|gif|bmp))!/i', '', $summary);
        // 移除多余的空格和换行
        $summary = preg_replace('/\s+/', ' ', $summary);
        return trim($summary);
    }

/**
     * 判断任务状态是否应该标记为完成
     */
    private function isTaskCompleted(string $status): bool
    {
        // 定义"未完成"的状态列表（包括未开始和进行中）
        // 如果状态不在这个列表中，则认为任务已完成
        $incompleteStatuses = [
            '未开始',
            '需求已确认',
            '开发中',
            '需求调研中',
            '需求已调研',
            '需求已评审',
            '需求已排期',
            '待提测',
            '需求设计中',
        ];

        // 如果状态不在"未完成"列表中，则标记为已完成
        return !in_array($status, $incompleteStatuses, true);
    }

$isBug = in_array($issueType, ['Bug', 'BUG', 'bug', '缺陷', 'Defect']);

$isSubtask = in_array($issueType, ['Sub-task', 'sub-task', '子任务']);

$bugData['parent_summary'] = $workLog['parent_task']['summary'];

$parentType = $parentDetails ? ($parentDetails->fields->issuetype->name ?? '') : '';

$isParentStory = in_array($parentType, ['Story', 'story', '需求']);

/**
     * 组织任务数据用于周报生成
     */
    private function organizeTasksForReport(Collection $workLogs, string $username): Collection
    {
        $organized = collect([
            'sprints' => collect(),
            'stories' => collect(),  // 没有Sprint的需求
            'tasks' => collect(),
            'bugs' => collect(),
        ]);

        $processedIssues = collect();

        foreach ($workLogs as $workLog) {
            $issueKey = $workLog['issue_key'];
            $issueType = $workLog['issue_type'] ?? 'Unknown';
            $issueSummary = $workLog['issue_summary'] ?? '';
            $parentSummary = $workLog['parent_task']['summary'] ?? '';
            $excludeKeyword = '工作日志';

            // 排除工作日志相关的Jira
            if ((is_string($issueSummary) && mb_strpos($issueSummary, $excludeKeyword) !== false)
                || (is_string($parentSummary) && mb_strpos($parentSummary, $excludeKeyword) !== false)) {
                continue;
            }

            // 避免重复处理同一个任务
            if ($processedIssues->has($issueKey)) {
                continue;
            }
            $processedIssues->put($issueKey, true);

            // 判断是否为Bug（通过issuetype判断）
            $isBug = in_array($issueType, ['Bug', 'BUG', 'bug', '缺陷', 'Defect']);

            // 判断是否为需求（Story类型）
            $isStory = in_array($issueType, ['Story', 'story', '需求']);

            // 判断是否为子任务
            $isSubtask = in_array($issueType, ['Sub-task', 'sub-task', '子任务']);

            if ($isBug && $workLog['bug_stage']) {
                // Bug过滤逻辑：必须经办人、实际修复人或开发人是当前用户
                $assignee = $workLog['assignee'] ?? null;
                $developer = $workLog['developer'] ?? null;
                $actualFixer = $workLog['actual_fixer'] ?? null;

                // 检查是否有任一字段匹配当前用户
                $isUserRelated = ($assignee === $username)
                    || ($developer === $username)
                    || ($actualFixer === $username);

                // 如果不是当前用户相关的Bug，跳过
                if (!$isUserRelated) {
                    continue;
                }

                // Bug按发现阶段分类
                $stage = $workLog['bug_stage'];
                if (!$organized['bugs']->has($stage)) {
                    $organized['bugs']->put($stage, collect());
                }

                $bugData = [
                    'key' => $workLog['issue_key'],
                    'summary' => $workLog['issue_summary'],
                    'url' => $workLog['issue_url'],
                    'status' => $workLog['issue_status'],
                    'bug_type' => $workLog['bug_type'],
                    'bug_description' => $workLog['bug_description'],
                ];

                // 如果有父任务，添加父任务信息
                if ($workLog['parent_task']) {
                    $bugData['parent_key'] = $workLog['parent_task']['key'];
                    $bugData['parent_summary'] = $workLog['parent_task']['summary'];
                }

                $organized['bugs'][$stage]->push($bugData);
            } elseif (($isStory || $isSubtask) && $workLog['sprint']) {
                // Story类型或子任务，且有Sprint的，按Sprint分类（需求）
                $sprintName = $workLog['sprint'];
                if (!$organized['sprints']->has($sprintName)) {
                    $organized['sprints']->put($sprintName, collect());
                }

                $this->addTaskToSprintOrTaskList($organized['sprints'][$sprintName], $workLog);
            } elseif ($isStory && !$workLog['sprint']) {
                // Story类型但没有Sprint的，放入需求分类
                $this->addTaskToSprintOrTaskList($organized['stories'], $workLog);
            } elseif ($isSubtask && !$workLog['sprint'] && $workLog['parent_task']) {
                // 子任务没有Sprint，检查父任务类型来决定分类
                $parentKey = $workLog['parent_task']['key'];
                $parentDetails = $this->getIssueDetails($parentKey);
                $parentType = $parentDetails ? ($parentDetails->fields->issuetype->name ?? '') : '';
                $isParentStory = in_array($parentType, ['Story', 'story', '需求']);

                if ($isParentStory) {
                    // 父任务是Story，放入需求分类
                    $this->addTaskToSprintOrTaskList($organized['stories'], $workLog);
                } else {
                    // 父任务不是Story，放入任务分类
                    $this->addTaskToSprintOrTaskList($organized['tasks'], $workLog);
                }
            } else {
                // 其他任务单独列出（非Story/子任务类型）
                $this->addTaskToSprintOrTaskList($organized['tasks'], $workLog);
            }
        }

    }

$parentSummary = $parentDetails ? $parentDetails->fields->summary : $workLog['parent_task']['summary'];

$parentStatus = $parentDetails ? $parentDetails->fields->status->name : 'Unknown';

/**
     * 添加任务到Sprint或任务列表
     */
    private function addTaskToSprintOrTaskList(Collection $taskList, array $workLog): void
    {
        $status = $workLog['issue_status'] ?? 'Unknown';

        if ($workLog['parent_task']) {
            // 子任务
            $parentKey = $workLog['parent_task']['key'];

            if (!$taskList->has($parentKey)) {
                // 获取父任务的真实信息
                $parentSummary = $parentDetails ? $parentDetails->fields->summary : $workLog['parent_task']['summary'];
                $parentStatus = $parentDetails ? $parentDetails->fields->status->name : 'Unknown';

                $taskList->put($parentKey, [
                    'key' => $parentKey,
                    'summary' => $parentSummary,
                    'url' => $this->config['host'] . '/browse/' . $parentKey,
                    'status' => $parentStatus,
                    'subtasks' => collect(),
                ]);
            }

            $taskList[$parentKey]['subtasks']->put($workLog['issue_key'], [
                'key' => $workLog['issue_key'],
                'summary' => $workLog['issue_summary'],
                'url' => $workLog['issue_url'],
                'status' => $status,
                'created' => $workLog['issue_created'],
            ]);
        } else {
            // 主任务
            if (!$taskList->has($workLog['issue_key'])) {
                $taskList->put($workLog['issue_key'], [
                    'status' => $status,
                ]);
            }
        }
    }

function ($version) use ($currentVersion) {
                    if ($version->released ?? false) {
                        return false;
                    }
                    return version_compare($version->name, $currentVersion, '>');
                })

/**
     * 获取下一个 release 版本
     * 根据当前版本号，在 Jira 版本列表中找到下一个版本
     *
     * @param string $projectKey Jira 项目 key
     * @param string|null $currentVersion 当前版本号（来自 master 分支的 version.txt）
     */
    public function getUpcomingReleaseVersion(string $projectKey, ?string $currentVersion = null): ?array
    {
        try {
            $versions = $this->projectService->getVersions($projectKey);
            throw new \RuntimeException('获取 release 版本失败: ' . $e->getMessage(), previous: $e);
        }

        if (empty($versions)) {
        }

        // 按版本名称排序（假设版本号格式一致，如 1.0.0, 1.0.1, 1.1.0）
        $sortedVersions = collect($versions)
            ->filter(fn($version) => !empty($version->name))
            ->sortBy(fn($version) => $version->name, SORT_NATURAL)
            ->values();

        if ($sortedVersions->isEmpty()) {
        }

        // 如果没有提供当前版本，返回第一个未发布的版本
        if (empty($currentVersion)) {
            $candidate = $sortedVersions
                ->filter(fn($version) => !($version->released ?? false))
                ->first();

            if (!$candidate) {
                return null;
            }

            return [
                'version' => $candidate->name,
                'description' => $candidate->description ?? null,
                'release_date' => !empty($candidate->releaseDate)
                    ? Carbon::parse($candidate->releaseDate)->toDateString()
                    : null,
            ];
        }

        // 找到当前版本在列表中的位置，返回下一个版本
        $currentIndex = $sortedVersions->search(
            fn($version) => $version->name === $currentVersion
        );

        // 如果找不到当前版本，尝试找到第一个大于当前版本的未发布版本
        if ($currentIndex === false) {
                ->filter(function ($version) use ($currentVersion) {
                    }
                })

            }

            return [
                    : null,
            ];
        }

        // 从当前版本的下一个开始，找到第一个未发布的版本
        $candidate = $sortedVersions
            ->slice($currentIndex + 1)
            ->filter(fn($version) => !($version->released ?? false))
            ->first();

        if (!$candidate) {
        }

        return [
            'version' => $candidate->name,
            'description' => $candidate->description ?? null,
            'release_date' => !empty($candidate->releaseDate)
                ? Carbon::parse($candidate->releaseDate)->toDateString()
                : null,
        ];
    }

class JiraService
{
    private IssueService $issueService;
    private ProjectService $projectService;
    private array $config;

    public function __construct()
    {
    }

    /**
     */
    {
        ]);

    }

    /**
     */
    {

                ]);
            }

                // 子任务
            } else {
                // 主任务
            }
        }

    }

    /**
     */
    {
        try {
                'status',
            ]);
        }
    }

    private function addMainTask(Collection $tasks, $issue): void
    {
        ]);
    }

    private function addSubtask(Collection $tasks, string $parentKey, $issue): void
    {

            ]);
        }

        ]);
    }

    /**
     */
    {

        }

            'Done',
            '已上线',
            '已完成',
        ];

        );

        try {
                'status',
                'created'
            ]);

            }
        }

    }

    /**
     */
    {

        } else {
                );

                            }
                        }
                    }
                }
            }

                        }
                    }
                }
            }

            // 单独列出的任务

                        }
                    }
                }
            }

                    });

                            // 独立的Bug
                                    }
                                }
                            }
                        } else {
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

            }
        }

    }

    /**
     */
    {
        );

        try {
                'parent',
                'status',
                'labels',
            ]);

                }
            }
        }
    }

    /**
     * 提取工时记录
     */
    {

            try {

                    try {

                            // 获取父任务信息
                                ];
                            }

                            // 提取需求类型

                                ],
                            ]);
                        }
                        continue;
                    }
                }
                continue;
            }
        }

    }

    /**
     */
    {

            // 处理数组情况
                    }
                }
            }

            // 处理对象情况
            }

            // 处理字符串情况
                }
            }
        }

        }

            }
        }

    }

    /**
     */
    {

            // 处理对象类型
            } else {
            }

                // 标准化阶段名称
                }
                }
                }
            }
        }

                }
                }
                }
            }
        }

    }

    /**
     */
    {

            // 处理对象类型
            }
        }

                    }
                }
            }
        }

    }

    /**
     */
    {

            }
        }

    }

    /**
     * 提取需求类型
     */
    {
                }
            }
        }

    }

    /**
     * 提取经办人
     */
    {

            // 处理对象类型
            }
        }

    }

    /**
     * 提取开发人
     */
    {

            }
        }

    }

    /**
     * 提取实际修复人
     */
    {

            }
        }

    }

    /**
     */
    {
    }

    /**
     */
    {
            '未开始',
            '需求已确认',
            '开发中',
            '需求调研中',
            '需求已调研',
            '需求已评审',
            '需求已排期',
            '待提测',
            '需求设计中',
        ];

    }

    /**
     */
    {
        ]);

                continue;
            }

                continue;
            }

                    continue;
                }

                }

                ];

                }

                }

                } else {
                }
            } else {
            }
        }

    }

    /**
     */
    {

            // 子任务

                ]);
            }

            ]);
        } else {
            // 主任务
                ]);
            }
        }
    }

    /**
     *
     */
    {
        try {
        }

        }

        }

            }

            return [
                    : null,
            ];
        }

        );

                    }
                })

            }

            return [
                    : null,
            ];
        }

        }

        return [
                : null,
        ];
    }
}

public function __construct(JiraService $jiraService)
    {
        $this->jiraService = $jiraService;
    }

$username = $request->input('username') ?: config('jira.default_user');

/**
     * 生成上周周报
     */
    public function generateWeeklyReport(Request $request): JsonResponse
    {
        try {
            $username = $request->input('username') ?: config('jira.default_user');

            if (!$username) {
                return response()->json([
                    'success' => false,
                    'message' => '请提供用户名'
                ], 400);
            }

            $report = $this->jiraService->generateWeeklyReport($username);

            return response()->json([
                'success' => true,
                'data' => [
                    'report' => $report,
                    'username' => $username,
                    'generated_at' => Carbon::now()->format('Y-m-d H:i:s')
                ]
            ]);
        } catch (\Exception $e) {
                'success' => false,
                'message' => '生成周报失败: ' . $e->getMessage()
            ], 500);
        }
    }

$startDate = Carbon::parse($request->input('start_date'))->startOfDay();

$endDate = Carbon::parse($request->input('end_date'))->endOfDay();

$workLogs = $this->jiraService->getWorkLogs($username, $startDate, $endDate);

/**
     * 获取工时记录
     */
    public function getWorkLogs(Request $request): JsonResponse
    {
        $request->validate([
            'username' => 'required|string',
            'start_date' => 'required|date',
            'end_date' => 'required|date|after_or_equal:start_date',
        ]);

        try {
            $username = $request->input('username');
            $startDate = Carbon::parse($request->input('start_date'))->startOfDay();
            $endDate = Carbon::parse($request->input('end_date'))->endOfDay();

            $workLogs = $this->jiraService->getWorkLogs($username, $startDate, $endDate);

                'data' => [
                    'work_logs' => $workLogs->values()->toArray(),
                    'total_hours' => $workLogs->sum('hours'),
                    'total_records' => $workLogs->count(),
                    'date_range' => [
                        'start' => $startDate->format('Y-m-d'),
                        'end' => $endDate->format('Y-m-d')
                    ]
                ]
            ]);
                'message' => '获取工时记录失败: ' . $e->getMessage()
            ], 500);
        }
    }

/**
     * 获取JIRA配置信息
     */
    public function getConfig(): JsonResponse
    {
        return response()->json([
            'success' => true,
            'data' => [
                'default_user' => config('jira.default_user', ''),
                'host' => config('jira.host', '')
            ]
        ]);
    }

$filename = sprintf('weekly_report_%s_%s.md', $username, Carbon::now()->subWeek()->format('Y-m-d'));

/**
     * 下载周报文件
     */
    public function downloadWeeklyReport(Request $request)
    {
        try {

                ], 400);
            }

            $filename = sprintf('weekly_report_%s_%s.md', $username, Carbon::now()->subWeek()->format('Y-m-d'));

            return response($report)
                ->header('Content-Type', 'text/markdown')
                ->header('Content-Disposition', 'attachment; filename="' . $filename . '"');
                'message' => '下载周报失败: ' . $e->getMessage()
            ], 500);
        }
    }

class JiraController extends Controller
{
    private JiraService $jiraService;

    public function __construct(JiraService $jiraService)
    {
    }

    /**
     * 生成上周周报
     */
    {
        try {

                ], 400);
            }

                'data' => [
                ]
            ]);
            ], 500);
        }
    }

    /**
     * 获取工时记录
     */
    {
        ]);

        try {

                'data' => [
                    ]
                ]
            ]);
            ], 500);
        }
    }

    /**
     */
    {
            'data' => [
            ]
        ]);
    }

    /**
     * 下载周报文件
     */
    {
        try {

                ], 400);
            }

            ], 500);
        }
    }

}