<?php

namespace App\Controllers\Api;

use App\Controllers\BaseController;
use App\Libraries\GiteaSyncService;
use CodeIgniter\API\ResponseTrait;

class GitApi extends BaseController
{
	use ResponseTrait;

	private function ensureLoggedIn()
	{
		if (!session()->get('userid')) {
			return $this->respond([
				'status' => 'error',
				'message' => 'Unauthorized',
			], 401);
		}

		return null;
	}

	private function ensureAdmin()
	{
		$level = (int) session()->get('level');
		if (!in_array($level, [0, 1, 2], true)) {
			return $this->respond([
				'status' => 'error',
				'message' => 'Forbidden. Admin only.',
			], 403);
		}

		return null;
	}

	public function summary()
	{
		if ($response = $this->ensureLoggedIn()) {
			return $response;
		}

		$db = \Config\Database::connect();

		$usersCount = $db->table('git_users')->countAllResults();
		$repositoriesCount = $db->table('git_repositories')->countAllResults();
		$commitsCount = $db->table('git_commits')->countAllResults();
		$pullRequestsCount = $db->table('git_pull_requests')->countAllResults();

		$latestCommit = $db->table('git_commits')->selectMax('committed_at', 'latest')->get()->getRowArray();
		$latestPullRequest = $db->table('git_pull_requests')->selectMax('updated_at_gitea', 'latest')->get()->getRowArray();
		$latestRepoSync = $db->table('git_repositories')->selectMax('last_synced_at', 'latest')->get()->getRowArray();

		return $this->respond([
			'status' => 'success',
			'message' => 'Summary fetched',
			'data' => [
				'users' => $usersCount,
				'repositories' => $repositoriesCount,
				'commits' => $commitsCount,
				'pull_requests' => $pullRequestsCount,
				'latest_commit_at' => $latestCommit['latest'] ?? null,
				'latest_pull_request_at' => $latestPullRequest['latest'] ?? null,
				'last_synced_at' => $latestRepoSync['latest'] ?? null,
			],
		], 200);
	}

	public function users()
	{
		if ($response = $this->ensureLoggedIn()) {
			return $response;
		}

		$db = \Config\Database::connect();
		$rows = $db->table('git_users')
			->select('id, gitea_user_id, username, full_name, email, is_active, is_admin, last_synced_at')
			->orderBy('username', 'ASC')
			->get()
			->getResultArray();

		return $this->respond([
			'status' => 'success',
			'message' => 'Users fetched',
			'data' => $rows,
		], 200);
	}

	public function repositories()
	{
		if ($response = $this->ensureLoggedIn()) {
			return $response;
		}

		$db = \Config\Database::connect();
		$rows = $db->table('git_repositories r')
			->select('r.id, r.gitea_repo_id, r.name, r.full_name, r.owner_username, r.default_branch, r.is_private, r.last_pushed_at, r.last_synced_at, u.username as owner_login')
			->join('git_users u', 'u.id = r.owner_user_id', 'left')
			->orderBy('r.full_name', 'ASC')
			->get()
			->getResultArray();

		return $this->respond([
			'status' => 'success',
			'message' => 'Repositories fetched',
			'data' => $rows,
		], 200);
	}

	private function getPaginationParams(): array
	{
		$page = (int) ($this->request->getGet('page') ?? 1);
		if ($page <= 0) {
			$page = 1;
		}

		$perPage = (int) ($this->request->getGet('per_page') ?? $this->request->getGet('limit') ?? 25);
		if ($perPage <= 0 || $perPage > 100) {
			$perPage = 25;
		}

		return [$page, $perPage];
	}

	public function commits()
	{
		if ($response = $this->ensureLoggedIn()) {
			return $response;
		}

		$repoId = $this->request->getGet('repo_id');
		$userId = $this->request->getGet('user_id');
		$startDate = $this->request->getGet('start_date');
		$endDate = $this->request->getGet('end_date');
		[$page, $perPage] = $this->getPaginationParams();
		$offset = ($page - 1) * $perPage;

		$db = \Config\Database::connect();
		$baseBuilder = $db->table('git_commits c')
			->join('git_repositories r', 'r.id = c.repository_id', 'inner')
			->join('git_users u', 'u.id = c.author_user_id', 'left');

		if (!empty($repoId)) {
			$baseBuilder->where('c.repository_id', (int) $repoId);
		}

		if (!empty($userId)) {
			$baseBuilder->where('c.author_user_id', (int) $userId);
		}

		if (!empty($startDate)) {
			$baseBuilder->where('c.committed_at >=', $startDate . ' 00:00:00');
		}

		if (!empty($endDate)) {
			$baseBuilder->where('c.committed_at <=', $endDate . ' 23:59:59');
		}

		$total = (int) (clone $baseBuilder)
			->countAllResults();

		$rows = $baseBuilder
			->select('c.id, c.sha, c.short_sha, c.message, c.author_name, c.author_email, c.committed_at, c.html_url, r.id as repository_id, r.full_name as repository_full_name, u.id as user_id, u.username as user_username')
			->orderBy('c.committed_at', 'DESC')
			->limit($perPage, $offset)
			->get()
			->getResultArray();

		return $this->respond([
			'status' => 'success',
			'message' => 'Commits fetched',
			'data' => $rows,
			'meta' => [
				'total' => $total,
				'page' => $page,
				'per_page' => $perPage,
				'total_pages' => $perPage > 0 ? (int) ceil($total / $perPage) : 0,
			],
		], 200);
	}

	public function pullRequests()
	{
		if ($response = $this->ensureLoggedIn()) {
			return $response;
		}

		$repoId = $this->request->getGet('repo_id');
		$userId = $this->request->getGet('user_id');
		$state = $this->request->getGet('state');
		$startDate = $this->request->getGet('start_date');
		$endDate = $this->request->getGet('end_date');
		[$page, $perPage] = $this->getPaginationParams();
		$offset = ($page - 1) * $perPage;

		$db = \Config\Database::connect();
		$baseBuilder = $db->table('git_pull_requests p')
			->join('git_repositories r', 'r.id = p.repository_id', 'inner')
			->join('git_users u', 'u.id = p.author_user_id', 'left');

		if (!empty($repoId)) {
			$baseBuilder->where('p.repository_id', (int) $repoId);
		}

		if (!empty($userId)) {
			$baseBuilder->where('p.author_user_id', (int) $userId);
		}

		if (!empty($state)) {
			$baseBuilder->where('p.state', $state);
		}

		if (!empty($startDate)) {
			$baseBuilder->where('p.updated_at_gitea >=', $startDate . ' 00:00:00');
		}

		if (!empty($endDate)) {
			$baseBuilder->where('p.updated_at_gitea <=', $endDate . ' 23:59:59');
		}

		$total = (int) (clone $baseBuilder)
			->countAllResults();

		$rows = $baseBuilder
			->select('p.id, p.number, p.title, p.state, p.is_draft, p.is_merged, p.created_at_gitea, p.updated_at_gitea, p.merged_at, p.closed_at, p.html_url, r.id as repository_id, r.full_name as repository_full_name, u.id as user_id, u.username as user_username')
			->orderBy('p.updated_at_gitea', 'DESC')
			->limit($perPage, $offset)
			->get()
			->getResultArray();

		return $this->respond([
			'status' => 'success',
			'message' => 'Pull requests fetched',
			'data' => $rows,
			'meta' => [
				'total' => $total,
				'page' => $page,
				'per_page' => $perPage,
				'total_pages' => $perPage > 0 ? (int) ceil($total / $perPage) : 0,
			],
		], 200);
	}

	public function sync()
	{
		if ($response = $this->ensureLoggedIn()) {
			return $response;
		}

		if ($response = $this->ensureAdmin()) {
			return $response;
		}

		$service = new GiteaSyncService();
		$result = $service->syncAll();

		$statusCode = $result['success'] ? 200 : 500;
		return $this->respond([
			'status' => $result['success'] ? 'success' : 'error',
			'message' => $result['message'],
			'data' => $result['stats'] ?? [],
		], $statusCode);
	}
}
