<?php

namespace Modules\Admin\app\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Mail\WorklogReport;
use App\Traits\HasFilterRequest;
use App\Traits\HasOrderByRequest;
use App\Traits\HasSearchRequest;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Services\JiraService;
use Carbon\Carbon;
use DateTime;
use DateTimeZone;
use GuzzleHttp\Promise\Utils;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Mail;

class JiraController extends Controller
{
    use HasOrderByRequest;
    use HasFilterRequest;
    use HasSearchRequest;

    protected $jiraService;

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

    public function fetchAllIssues($startAt = 0, $maxResults = 50)
    {
        try {
            $allIssues = [];
            $projects = $this->jiraService->getAllProjects();
            $promises = [];

            foreach ($projects as $project) {
                if ($project['key'] !== 'GCT') {
                    $promises[] = $this->jiraService->getIssuesAsync($project['key'], $startAt, $maxResults)
                        ->then(function ($response) use ($project) {
                            $issues = [];
                            $data = json_decode($response->getBody()->getContents(), true);
                            foreach ($data['issues'] as $issue) {
                                $issues[] = [
                                    'summary' => $issue['fields']['summary'] ?? null,
                                    'desc' => $issue['fields']['description']['content'][0] ?? null,
                                    'assignee' => $issue['fields']['assignee']['displayName'] ?? null,
                                    'status' => $issue['fields']['status']['name'] ?? null,
                                    'worklogs' => json_encode(array_map(function ($log) {
                                        return [
                                            'author' => $log['author']['displayName'] ?? null,
                                            'timeSpent' => $log['timeSpent'] ?? null,
                                            'started' => $log['started'] ?? null,
                                            'updated' => $log['updated'] ?? null,
                                        ];
                                    }, $issue['fields']['worklog']['worklogs'] ?? []), JSON_PRETTY_PRINT),
                                    'originalEstimate' => isset($issue['fields']['timeoriginalestimate']) ? $issue['fields']['timeoriginalestimate'] / 60 / 60 : null,
                                    'timeSpent' => isset($issue['fields']['timespent']) ? $issue['fields']['timespent'] / 60 / 60 : null
                                ];
                            }
                            return ['project' => $project['name'], 'issues' => $issues];
                        });
                }
            }

            $results = Utils::settle($promises)->wait();

            foreach ($results as $result) {
                if ($result['state'] === 'fulfilled') {
                    $allIssues[] = $result['value'];
                } else {
                    // Handle the errors if necessary
                    \Log::error("Error fetching issues: " . $result['reason']->getMessage());
                }
            }

            return response()->json($allIssues);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    public function getAllProject()
    {
        $projects = $this->jiraService->getAllProjects();

        return response()->json([
            'data' => $projects,
            'status' => true
        ], 200);
    }

    public function fetchIssuesByProject(Request $request)
    {
        $project = ['key' => $request->key, 'name' => $request->name];
        $allIssues = [];

        if ($project['key'] !== 'GCT') {
            $startAt = 0;
            $issues = [];
            $total = 0;
            $issueLength = 0;
            $checked = true;

            // while ($checked) {
            $response = $this->jiraService->getIssues($project['key'], $startAt);
            $total = $response['total'];
            $issueLength = count($response['issues']);

            foreach ($response['issues'] as $issue) {
                $issues[] = [
                    'summary' => $issue['fields']['summary'] ?? null,
                    'desc' => $issue['fields']['description']['content'][0] ?? null,
                    'assignee' => $issue['fields']['assignee']['displayName'] ?? null,
                    'status' => $issue['fields']['status']['name'] ?? null,
                    'worklogs' => json_encode(array_map(function ($log) {
                        return [
                            'author' => $log['author']['displayName'] ?? null,
                            'timeSpent' => $log['timeSpent'] ?? null,
                            'started' => $log['started'] ?? null,
                            'updated' => $log['updated'] ?? null,
                        ];
                    }, $issue['fields']['worklog']['worklogs'] ?? []), JSON_PRETTY_PRINT),
                    'originalEstimate' => isset($issue['fields']['timeoriginalestimate']) ? $issue['fields']['timeoriginalestimate'] / 60 / 60 : null,
                    'timeSpent' => isset($issue['fields']['timespent']) ? $issue['fields']['timespent'] / 60 / 60 : null
                ];
                // }

                // if (($startAt + $issueLength >= $total && $total !== 0) || $total === 0) {
                //     $checked = false;
                // }

                // $startAt += $issueLength;
            }

            $allIssues[] = [
                'project' => $project['name'],
                'issues' => $issues
            ];

            return response()->json([
                'data' => $allIssues,
                'status' => true
            ], 200);
        }
        return response()->json([
            'data' => $allIssues,
            'status' => false
        ], 500);
    }

    public function exportToExcel()
    {
        $allIssues = $this->fetchAllIssues()->original;
        $fileName = 'allIssues.xlsx';

        Excel::store(new \App\Exports\IssuesExport($allIssues), $fileName);

        return response()->download(storage_path("app/{$fileName}"));
    }

    public function getAllUserWorkLogs(Request $request)
    {
        try {
            $workLogs = $this->jiraService->getAllUserWorkLogs($request->startDate, $request->endDate);
            return response()->json([
                'data' => $workLogs,
                'status' => true
            ], 200);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    public function sendReport()
    {
        $dateFormatted = Carbon::yesterday()->setTimezone(env('TIME_ZONE'))->format('Y-m-d');
        // $dateFormatted = Carbon::create(2024, 06, 28)->format('Y-m-d');
        $workLogs = $this->jiraService->getAllUserWorkLogs($dateFormatted, $dateFormatted);

        $tasksByUser = $this->formatWorkLogsByUser($workLogs);
        Mail::to(['luanlt632000@gmail.com'])->send(new WorklogReport($tasksByUser));
        // Mail::to(['luanlt632000@gmail.com', 'admin@apactech.io'])->send(new WorklogReport($tasksByUser));

        // return "Email sent successfully!";
        return response()->json([
            'data' => $tasksByUser,
            'status' => true
        ], 200);
    }

    private function customSort($a, $b, $order)
    {
        $pos_a = array_search(strtolower($a), $order);
        $pos_b = array_search(strtolower($b), $order);

        if ($pos_a === false || $pos_b === false) {
            return 0;
        }

        return $pos_a - $pos_b;
    }

    private function formatWorkLogsByUser($workLogs)
    {
        // Assuming each workLog has a 'user' field
        $tasksByUser = [];
        $predefinedOrder = ['closed', 'done', 'customer_test', 'testing', 'in progress', 'to do', 'backlog'];
        foreach ($workLogs as $log) {
            $user = $log['username'];

            if (!isset($tasksByUser[$user])) {
                $tasksByUser[$user] = [];
            }
            $tasksByUser[$user]['user'] = $log['user'];
            foreach ($log['information']['issues'] as $issue) {

                $today = Carbon::yesterday()->setTimezone(env('TIME_ZONE'))->format('Y-m-d');
                // $today = Carbon::create('2024','6','28');
                $filteredWorklogs = [];
                $totalTimeSpent = 0;
                foreach ($issue['fields']['worklog']['worklogs'] as $worklog) {
                    $started = Carbon::parse($worklog['started']);
                    $totalTimeSpent = $totalTimeSpent + ($worklog['timeSpentSeconds'] / 60 / 60);
                    if ($started->isSameDay($today) && $worklog['updateAuthor']['displayName'] == $user) {
                        $filteredWorklogs[] = $worklog;
                    }
                }
                $tasksByUser[$user]["allStatus"][$issue['fields']['status']['name']][] = [
                    'summary' => $issue['fields']['summary'],
                    'project' => $issue['fields']['project'],
                    'estimate' => $issue['fields']['timeoriginalestimate'],
                    'time_spent' => $issue['fields']['timespent'],
                    'worklogs' => $filteredWorklogs,
                    'totalTimeSpent' => $totalTimeSpent,
                ];
                $tasksByUser[$user]['assignment'] = $log['tasksAssign'];
                uksort($tasksByUser[$user]["allStatus"], function ($a, $b) use ($predefinedOrder) {
                    return $this->customSort($a, $b, $predefinedOrder);
                });
            }
        }
        // dd($tasksByUser);
        return $tasksByUser;
    }


    public function getAllUserDoing(Request $request)
    {
        try {
            $doing = $this->jiraService->getAllUserDoing();
            return response()->json([
                'data' => $doing,
                'status' => true
            ], 200);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    public function getDetailIssueById(Request $request)
    {
        $data = $this->jiraService->getDetailIssueByKey($request->issueKey);

        return response()->json([
            'data' => $data,
            'status' => true
        ], 200);
    }
    
    public function getDetailsProjectsById(Request $request)
    {
        $id = $request->input('id');
        $projects = $this->jiraService->getDetailsProjectsById($id);
        return response()->json([
            'data' => $projects,
            'status' => true
        ], 200);
    }

    public function getAllBoardByIdProjects(Request $request)
    {
        $id = $request->input('id');
        $projects = $this->jiraService->getAllBoardByIdProjects($id);

        return response()->json([
            'data' => $projects,
            'status' => true
        ], 200);
    }

    public function getAllSprintByIdBoard(Request $request)
    {
        $id = $request->input('id');
        $projects = $this->jiraService->getAllSprintByIdBoard($id);

        return response()->json([
            'data' => $projects,
            'status' => true
        ], 200);
    }
    public function getAllIssueByIdSprint(Request $request)
    {
        $id = $request->input('id');
        $projects = $this->jiraService->getAllIssueByIdSprint($id);

        return response()->json([
            'data' => $projects,
            'status' => true
        ], 200);
    }
}
