<?= $this->extend('layouts/main.php') ?>

<?= $this->section('content') ?>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
<style>
    body {
        background-color: #f8f9fa;
    }
    .commit-card {
        transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
        border-left: 4px solid #0d6efd; /* Aksen warna biru di kiri */
    }
    .commit-card:hover {
        transform: translateY(-3px);
        box-shadow: 0 .5rem 1rem rgba(0,0,0,.1)!important;
    }
    .avatar {
        width: 48px;
        height: 48px;
        object-fit: cover;
    }
    .commit-message {
        font-size: 1.1rem;
        font-weight: 600;
        color: #212529;
        text-decoration: none;
    }
    .commit-message:hover {
        text-decoration: underline;
        color: #0d6efd;
    }
    .file-list {
        max-height: 200px;
        overflow-y: auto;
    }
</style>
<div class="page-wrapper">
	<div class="container-fluid">
		<div class="row page-titles">
			<div class="col-md-5 align-self-center">
				<h4 class="text-themecolor">Commit History</h4>
			</div>
		</div>
        
        <div class="row mb-4 bg-light p-3 rounded shadow-sm g-3">
            <div class="col-md-3">
                <label class="form-label fw-bold">1. Select User <span class="text-danger">*</span></label>
                <select id="selectUser" class="form-select">
                    <option value="">-- Select User --</option>
                    <option value="alamdh22">alamdh22</option>
                    <option value="faiztyanirh">faiztyanirh</option>
                    <option value="mahdahar">mahdahar</option>
                    <option value="mikael-zakaria">mikael-zakaria</option>
                </select>
            </div>
            
            <div class="col-md-3">
                <label class="form-label fw-bold">2. Select Repository (Optional)</label>
                <select id="selectRepo" class="form-select" disabled>
                    <option value="">-- All Repositories --</option>
                </select>
            </div>

            <div class="col-md-2">
                <label class="form-label fw-bold">3. Start Date <span class="text-danger">*</span></label>
                <input type="date" id="startDate" class="form-control">
            </div>

            <div class="col-md-2">
                <label class="form-label fw-bold">4. End Date <span class="text-danger">*</span></label>
                <input type="date" id="endDate" class="form-control">
            </div>

            <div class="col-md-2 d-flex align-items-end">
                <button id="btnLoadCommits" class="btn btn-success w-100" disabled>
                    Filter Commits
                </button>
            </div>
        </div>

        <div class="row justify-content-center">
            <div class="col-12" id="commits-container">
                <div class="alert alert-secondary text-center">
                    Please select User and Date Range first (Repository is optional)
                </div>
            </div>
        </div>

    </div>
</div>
<?= $this->endSection() ?>
<?= $this->section('script') ?>
<script>
document.addEventListener('DOMContentLoaded', () => {
    const selectUser = document.getElementById('selectUser');
    const selectRepo = document.getElementById('selectRepo');
    const startDate = document.getElementById('startDate');
    const endDate = document.getElementById('endDate');
    const btnLoadCommits = document.getElementById('btnLoadCommits');
    const commitsContainer = document.getElementById('commits-container');

    let availableRepos = [];

    setDefaultDateRange();
    updateButtonState();

    selectUser.addEventListener('change', async () => {
        const username = selectUser.value;

        if (!username) {
            availableRepos = [];
            resetRepoSelect('-- All Repositories --', true);
            updateButtonState();
            return;
        }

        resetRepoSelect('Loading repositories...', true);
        updateButtonState();

        try {
            const url = `<?= base_url('api/gitea/getrepos') ?>/${username}`;
            const res = await fetch(url);

            if (!res.ok) {
                throw new Error(`HTTP error! status: ${res.status}`);
            }

            const response = await res.json();
            availableRepos = (response.success && Array.isArray(response.data))
                ? response.data.map(repo => repo.name)
                : [];

            renderRepoOptions(availableRepos);
        } catch (error) {
            console.error('Error fetching repos:', error);
            availableRepos = [];
            resetRepoSelect('Error loading repository', true);
            alert('Failed to fetch repository data from the server.');
        } finally {
            updateButtonState();
        }
    });

    startDate.addEventListener('change', updateButtonState);
    endDate.addEventListener('change', updateButtonState);

    btnLoadCommits.addEventListener('click', async () => {
        const username = selectUser.value;
        const selectedRepo = selectRepo.value;

        if (!username || !startDate.value || !endDate.value) {
            commitsContainer.innerHTML = `<div class="alert alert-warning">User and date range are required.</div>`;
            return;
        }

        const start = new Date(`${startDate.value}T00:00:00`);
        const end = new Date(`${endDate.value}T23:59:59.999`);

        if (start > end) {
            commitsContainer.innerHTML = `<div class="alert alert-warning">Start date must be earlier than or equal to end date.</div>`;
            return;
        }

        const targetRepos = selectedRepo ? [selectedRepo] : availableRepos;

        if (!targetRepos.length) {
            commitsContainer.innerHTML = `<div class="alert alert-info">No repositories found for selected user.</div>`;
            return;
        }

        commitsContainer.innerHTML = `<div class="text-center"><div class="spinner-border text-primary" role="status"></div><p>Fetching commits from ${targetRepos.length} repos...</p></div>`;

        const limit = 100;
        const failedRepos = [];

        try {
            const results = await Promise.all(targetRepos.map(async (repoName) => {
                try {
                    const url = `<?= base_url('api/gitea/getcommits') ?>/${username}/${repoName}?limit=${limit}`;
                    const res = await fetch(url);

                    if (!res.ok) {
                        throw new Error(`HTTP ${res.status}`);
                    }

                    const response = await res.json();
                    if (!response.success || !Array.isArray(response.data)) {
                        throw new Error(response.message || 'Invalid response');
                    }

                    return response.data.map(item => ({ ...item, __repo: repoName }));
                } catch (error) {
                    failedRepos.push(repoName);
                    console.error(`Error fetching commits for repo ${repoName}:`, error);
                    return [];
                }
            }));

            const mergedCommits = results.flat();
            const filteredCommits = mergedCommits
                .filter(item => commitMatchesUser(item, username))
                .filter(item => isDateInRange(item, start, end))
                .sort((a, b) => {
                    const dateA = getCommitDate(a)?.getTime() ?? 0;
                    const dateB = getCommitDate(b)?.getTime() ?? 0;
                    return dateB - dateA;
                });

            renderCommits(filteredCommits, failedRepos);
        } catch (error) {
            console.error('Error filtering commits:', error);
            commitsContainer.innerHTML = `<div class="alert alert-danger">Failed to contact the server.</div>`;
        }
    });

    function setDefaultDateRange() {
        const today = new Date();
        const currentYear = today.getFullYear();
        const januaryFirst = new Date(currentYear, 0, 1);

        startDate.value = formatDateInput(januaryFirst);
        endDate.value = formatDateInput(today);
    }

    function formatDateInput(date) {
        const year = date.getFullYear();
        const month = String(date.getMonth() + 1).padStart(2, '0');
        const day = String(date.getDate()).padStart(2, '0');
        return `${year}-${month}-${day}`;
    }

    function resetRepoSelect(message, disabled = true) {
        selectRepo.innerHTML = `<option value="">${message}</option>`;
        selectRepo.disabled = disabled;
    }

    function renderRepoOptions(repos) {
        selectRepo.innerHTML = '<option value="">-- All Repositories --</option>';

        if (!repos.length) {
            selectRepo.innerHTML = '<option value="">Repository not found</option>';
            selectRepo.disabled = true;
            return;
        }

        repos.forEach(repoName => {
            selectRepo.innerHTML += `<option value="${repoName}">${repoName}</option>`;
        });

        selectRepo.disabled = false;
    }

    function updateButtonState() {
        const hasUser = Boolean(selectUser.value);
        const hasStartDate = Boolean(startDate.value);
        const hasEndDate = Boolean(endDate.value);
        btnLoadCommits.disabled = !(hasUser && hasStartDate && hasEndDate);
    }

    function getCommitDate(item) {
        const rawDate = item.commit?.author?.date || item.commit?.committer?.date;
        if (!rawDate) {
            return null;
        }

        const parsed = new Date(rawDate);
        return Number.isNaN(parsed.getTime()) ? null : parsed;
    }

    function isDateInRange(item, start, end) {
        const commitDate = getCommitDate(item);
        if (!commitDate) {
            return false;
        }

        return commitDate >= start && commitDate <= end;
    }

    function commitMatchesUser(item, selectedUsername) {
        const username = (selectedUsername || '').toLowerCase();
        const authorUsername = (item.author?.username || '').toLowerCase();
        const commitAuthorName = (item.commit?.author?.name || '').toLowerCase();
        const commitAuthorEmail = (item.commit?.author?.email || '').toLowerCase();
        const emailPrefix = commitAuthorEmail.includes('@') ? commitAuthorEmail.split('@')[0] : commitAuthorEmail;

        return [authorUsername, commitAuthorName, emailPrefix].some(value => value && value === username);
    }

    function renderCommits(commits, failedRepos = []) {
        if (!commits || commits.length === 0) {
            const warning = failedRepos.length
                ? `<div class="alert alert-warning text-center shadow-sm"><i class="bi bi-exclamation-triangle me-2"></i> Failed to load ${failedRepos.length} repository data.</div>`
                : '';

            commitsContainer.innerHTML = `${warning}
                <div class="alert alert-info text-center shadow-sm">
                    <i class="bi bi-info-circle me-2"></i> No commits found for selected filters.
                </div>`;
            return;
        }

        let html = '';

        if (failedRepos.length) {
            html += `<div class="alert alert-warning text-center shadow-sm"><i class="bi bi-exclamation-triangle me-2"></i> Failed to load ${failedRepos.length} repository data: ${escapeHtml(failedRepos.join(', '))}</div>`;
        }

        commits.forEach((item, index) => {
            const message = item.commit?.message || 'No commit message';
            const authorName = item.author?.username || item.commit?.author?.name || 'Unknown';
            const avatar = item.author?.avatar_url || `https://ui-avatars.com/api/?name=${encodeURIComponent(authorName)}&background=random`;

            const dateObj = getCommitDate(item);
            const dateStr = dateObj
                ? dateObj.toLocaleDateString('id-ID', { day: '2-digit', month: 'short', year: 'numeric' }) + ', ' +
                  dateObj.toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit' })
                : '-';

            const shaShort = item.sha ? item.sha.substring(0, 10) : '';
            const commitUrl = item.html_url || '#';
            const repoName = item.__repo || '-';

            const additions = item.stats?.additions || 0;
            const deletions = item.stats?.deletions || 0;
            const files = item.files || [];

            html += `
            <div class="card shadow-sm mb-3 border-0 commit-card">
                <div class="card-body">
                    <div class="d-flex justify-content-between align-items-start gap-3 flex-sm-row flex-column">

                        <div class="d-flex align-items-start flex-grow-1 overflow-hidden w-100">
                            <img src="${avatar}" class="rounded-circle avatar border me-3 flex-shrink-0" alt="Avatar ${authorName}" width="40" height="40">

                            <div class="overflow-hidden w-100">
                                <a href="${commitUrl}" target="_blank" class="commit-message text-truncate d-block fw-bold text-decoration-none text-dark" title="${escapeHtml(message)}">
                                    ${escapeHtml(message)}
                                </a>
                                <div class="text-muted small mt-1 text-truncate">
                                    <i class="bi bi-person-fill"></i> <strong>${escapeHtml(authorName)}</strong> melakukan commit pada ${dateStr}
                                </div>
                                <div class="mt-1">
                                    <span class="badge bg-primary-subtle text-primary border">Repo: ${escapeHtml(repoName)}</span>
                                </div>
                            </div>
                        </div>

                        <div class="text-sm-end flex-shrink-0 mt-3 mt-sm-0">
                            <a href="${commitUrl}" target="_blank" class="badge bg-light text-dark border font-monospace text-decoration-none fs-6 mb-2 d-inline-block">
                                <i class="bi bi-hash"></i>${shaShort}
                            </a>
                            <div class="stats small font-monospace fw-bold">
                                <span class="text-success me-2" title="Additions"><i class="bi bi-plus-square-fill"></i> ${additions}</span>
                                <span class="text-danger" title="Deletions"><i class="bi bi-dash-square-fill"></i> ${deletions}</span>
                            </div>
                        </div>
                    </div>`;

            if (files.length > 0) {
                html += `
                    <div class="mt-3 border-top pt-2 d-flex justify-content-between align-items-center">
                        <span class="text-muted small"><i class="bi bi-files"></i> Mengubah ${files.length} file</span>
                        <button class="btn btn-sm btn-outline-secondary rounded-pill" type="button" data-bs-toggle="collapse" data-bs-target="#files-${index}" aria-expanded="false">
                            Lihat Detail File <i class="bi bi-chevron-down"></i>
                        </button>
                    </div>
                    <div class="collapse mt-2" id="files-${index}">
                        <div class="card card-body bg-light border-0 p-3 file-list">
                            <ul class="list-unstyled mb-0 small font-monospace">`;

                files.forEach(file => {
                    let statusClass = 'text-secondary';
                    let icon = 'bi-file-earmark';
                    if (file.status === 'added') { statusClass = 'text-success'; icon = 'bi-file-earmark-plus-fill'; }
                    else if (file.status === 'modified') { statusClass = 'text-warning'; icon = 'bi-file-earmark-diff-fill'; }
                    else if (file.status === 'removed' || file.status === 'deleted') { statusClass = 'text-danger'; icon = 'bi-file-earmark-minus-fill'; }

                    html += `
                                <li class="mb-1 d-flex align-items-center">
                                    <i class="bi ${icon} ${statusClass} me-2 fs-6"></i>
                                    <span class="text-truncate" title="${escapeHtml(file.filename)}">
                                        ${escapeHtml(file.filename)}
                                    </span>
                                </li>`;
                });

                html += `   </ul>
                        </div>
                    </div>`;
            }

            html += `
                </div>
            </div>`;
        });

        commitsContainer.innerHTML = html;
    }

    function escapeHtml(unsafe) {
        if (!unsafe) return '';
        return unsafe
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;');
    }
});
</script>
<?= $this->endSection() ?>