// gmail.js - Gmail client
// === GMAIL CLIENT ===
let gmailLabel = 'INBOX';
let gmailNextPage = null;
let gmailCurrentId = null;
async function loadGmailInbox(pageToken) {
if (!await ensureToken()) { updateAuthUI(); return; }
const list = document.getElementById('mailList');
const loading = document.getElementById('mailListLoading');
if (loading) loading.style.display = 'block';
const search = document.getElementById('mailSearch')?.value || '';
const params = { action: 'list', accessToken: gAccessToken, label: gmailLabel, maxResults: 25 };
if (search) params.q = search;
if (pageToken) params.pageToken = pageToken;
try {
const res = await fetch('/api/gmail-proxy.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(params)
});
const data = await res.json();
if (data.error === 'TOKEN_EXPIRED') { gAccessToken = ''; updateAuthUI(); return; }
if (data.error) throw new Error(data.error);
gmailNextPage = data.nextPageToken;
const count = document.getElementById('mailCount');
if (count) count.textContent = (data.resultSizeEstimate || 0) + ' meddelanden';
if (list) {
list.innerHTML = data.messages.map(m => {
const fromName = m.from.replace(/<.*>/, '').trim() || m.from;
const isActive = m.id === gmailCurrentId;
return '<div onclick="readGmail(\'' + m.id + '\')" style="padding:12px 16px;border-bottom:1px solid #f1f5f9;cursor:pointer;background:' + (isActive ? '#eff6ff' : (m.unread ? '#fefce8' : '#fff')) + ';transition:background .15s' + '">'
+ '<div style="display:flex;justify-content:space-between;align-items:start">'
+ '<strong style="font-size:13px;font-weight:' + (m.unread ? '700' : '500') + ';color:#1a1a1a;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:220px">' + escHtml(fromName) + '</strong>'
+ '<span style="font-size:11px;color:#94a3b8;white-space:nowrap;margin-left:8px">' + formatMailDate(m.timestamp) + '</span>'
+ '</div>'
+ '<div style="font-size:13px;color:#334155;font-weight:' + (m.unread ? '600' : '400') + ';overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:2px">' + escHtml(m.subject) + '</div>'
+ '<div style="font-size:12px;color:#94a3b8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:2px">' + escHtml(m.snippet) + '</div>'
+ '</div>';
}).join('');
}
// Pagination
const pag = document.getElementById('mailPagination');
if (pag) {
pag.innerHTML = gmailNextPage
? '<button onclick="loadGmailInbox(\'' + gmailNextPage + '\')" style="padding:6px 16px;background:#f1f5f9;border:1px solid #e5e7eb;border-radius:6px;font-size:12px;cursor:pointer;font-family:inherit">Visa fler</button>'
: '';
}
} catch(e) {
if (list) list.innerHTML = '<div style="padding:20px;text-align:center;color:#ef4444;font-size:13px">' + e.message + '</div>';
}
if (loading) loading.style.display = 'none';
}
async function readGmail(id) {
if (!await ensureToken()) return;
gmailCurrentId = id;
// Highlight in list
loadGmailInbox();
const content = document.getElementById('mailReaderContent');
const empty = document.getElementById('mailReaderEmpty');
if (empty) empty.style.display = 'none';
if (content) { content.style.display = 'block'; content.innerHTML = '<div style="text-align:center;padding:40px;color:#94a3b8">Laddar...</div>'; }
try {
const res = await fetch('/api/gmail-proxy.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ action: 'read', accessToken: gAccessToken, id })
});
const data = await res.json();
if (data.error) throw new Error(data.error);
const fromName = data.from.replace(/<.*>/, '').trim();
const fromEmail = (data.from.match(/<(.+)>/) || ['', data.from])[1];
const dateStr = new Date(data.timestamp * 1000).toLocaleString('sv-SE');
content.innerHTML = '<div style="margin-bottom:20px">'
+ '<h2 style="font-size:18px;font-weight:700;color:#1a1a1a;margin-bottom:12px">' + escHtml(data.subject) + '</h2>'
+ '<div style="display:flex;justify-content:space-between;align-items:start;flex-wrap:wrap;gap:8px">'
+ '<div><strong style="font-size:14px">' + escHtml(fromName) + '</strong><br><span style="font-size:12px;color:#64748b">' + escHtml(fromEmail) + '</span>'
+ (data.cc ? '<br><span style="font-size:12px;color:#94a3b8">Cc: ' + escHtml(data.cc) + '</span>' : '') + '</div>'
+ '<span style="font-size:12px;color:#94a3b8">' + dateStr + '</span>'
+ '</div>'
+ '<div style="display:flex;gap:6px;margin-top:12px">'
+ '<button onclick="mailReply(\'' + id + '\')" style="padding:6px 14px;background:#024550;color:#fff;border:none;border-radius:6px;font-size:12px;font-weight:600;cursor:pointer;font-family:inherit">Svara</button>'
+ '<button onclick="mailForward(\'' + id + '\')" style="padding:6px 14px;background:#f1f5f9;color:#334155;border:1px solid #e5e7eb;border-radius:6px;font-size:12px;cursor:pointer;font-family:inherit">Vidarebefordra</button>'
+ '<button onclick="mailTrash(\'' + id + '\')" style="padding:6px 14px;background:#fef2f2;color:#991b1b;border:1px solid #fecaca;border-radius:6px;font-size:12px;cursor:pointer;font-family:inherit">Radera</button>'
+ '</div>'
+ '</div>'
+ (data.attachments.length ? '<div style="padding:8px 12px;background:#f8fafc;border-radius:8px;margin-bottom:12px;border:1px solid #e5e7eb"><span style="font-size:12px;font-weight:600;color:#334155">Bilagor: </span>' + data.attachments.map(a => '<span style="font-size:12px;color:#3b82f6">' + escHtml(a.filename) + ' (' + formatSize(a.size) + ')</span>').join(', ') + '</div>' : '')
+ '<div style="border-top:1px solid #e5e7eb;padding-top:16px">'
+ '<iframe id="mailBodyFrame" srcdoc="" style="width:100%;min-height:400px;border:none" sandbox="allow-same-origin"></iframe>'
+ '</div>';
// Set iframe content
const iframe = document.getElementById('mailBodyFrame');
if (iframe) {
const bodyContent = data.bodyHtml || ('<pre style="white-space:pre-wrap;font-family:sans-serif">' + escHtml(data.bodyText) + '</pre>');
iframe.srcdoc = '<html><head><style>body{font-family:sans-serif;font-size:14px;color:#1a1a1a;margin:0;padding:0;line-height:1.5}img{max-width:100%}a{color:#0284c7}</style></head><body>' + bodyContent + '</body></html>';
}
// Store for reply
window._lastMailData = data;
} catch(e) {
content.innerHTML = '<div style="padding:20px;color:#ef4444">' + e.message + '</div>';
}
}
function mailCompose() {
document.getElementById('composeTitle').textContent = 'Nytt meddelande';
document.getElementById('composeTo').value = '';
document.getElementById('composeCc').value = '';
document.getElementById('composeSubject').value = '';
document.getElementById('composeBody').value = '';
document.getElementById('composeReplyUid').value = '0';
document.getElementById('composeReplyFolder').value = '';
document.getElementById('composeReplyTo').value = '';
document.getElementById('composeSignature').value = gMailSignature || '--\nMed vänliga hälsningar\n' + gUserName + '\nSolargroup';
document.getElementById('mailComposeModal').style.display = 'flex';
}
function mailReply(id) {
const d = window._lastMailData;
if (!d) return;
document.getElementById('composeTitle').textContent = 'Svara';
document.getElementById('composeTo').value = d.replyTo || d.from;
document.getElementById('composeCc').value = '';
document.getElementById('composeSubject').value = (d.subject.startsWith('Re:') ? '' : 'Re: ') + d.subject;
document.getElementById('composeBody').value = '\n\n--- Ursprungligt meddelande ---\nFrån: ' + d.from + '\nDatum: ' + new Date(d.timestamp*1000).toLocaleString('sv-SE') + '\n\n' + (d.bodyText || '');
document.getElementById('composeReplyUid').value = id;
document.getElementById('composeReplyTo').value = d.messageId || '';
document.getElementById('composeSignature').value = gMailSignature || '--\nMed vänliga hälsningar\n' + gUserName;
document.getElementById('mailComposeModal').style.display = 'flex';
}
function mailForward(id) {
const d = window._lastMailData;
if (!d) return;
document.getElementById('composeTitle').textContent = 'Vidarebefordra';
document.getElementById('composeTo').value = '';
document.getElementById('composeCc').value = '';
document.getElementById('composeSubject').value = 'Fwd: ' + d.subject;
document.getElementById('composeBody').value = '\n\n--- Vidarebefordrat meddelande ---\nFrån: ' + d.from + '\nTill: ' + d.to + '\nDatum: ' + new Date(d.timestamp*1000).toLocaleString('sv-SE') + '\nÄmne: ' + d.subject + '\n\n' + (d.bodyText || '');
document.getElementById('composeReplyUid').value = '0';
document.getElementById('composeReplyTo').value = '';
document.getElementById('composeSignature').value = gMailSignature || '--\nMed vänliga hälsningar\n' + gUserName;
document.getElementById('mailComposeModal').style.display = 'flex';
}
async function mailSend() {
if (!await ensureToken()) return;
const btn = document.getElementById('composeSendBtn');
btn.textContent = 'Skickar...'; btn.disabled = true;
try {
const sig = document.getElementById('composeSignature').value.trim();
// Save signature for next time
if (sig !== gMailSignature) {
gMailSignature = sig;
localStorage.setItem('mailSignature', sig);
fetch('/api/gmail-proxy.php', {
method: 'POST', headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ action: 'signature', staffId: gStaffId, signature: sig })
});
}
const replyTo = document.getElementById('composeReplyTo').value;
const res = await fetch('/api/gmail-proxy.php', {
method: 'POST', headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
action: 'send', accessToken: gAccessToken,
to: document.getElementById('composeTo').value,
cc: document.getElementById('composeCc').value,
subject: document.getElementById('composeSubject').value,
body: document.getElementById('composeBody').value,
signature: sig,
inReplyTo: replyTo,
references: replyTo,
threadId: replyTo ? (window._lastMailData?.threadId || '') : '',
})
});
const data = await res.json();
if (data.error) throw new Error(data.error);
mailCloseCompose();
loadGmailInbox();
} catch(e) {
alert('Kunde inte skicka: ' + e.message);
}
btn.textContent = 'Skicka'; btn.disabled = false;
}
async function mailTrash(id) {
if (!await ensureToken()) return;
try {
await fetch('/api/gmail-proxy.php', {
method: 'POST', headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ action: 'trash', accessToken: gAccessToken, id })
});
gmailCurrentId = null;
document.getElementById('mailReaderContent').style.display = 'none';
document.getElementById('mailReaderEmpty').style.display = 'flex';
loadGmailInbox();
} catch(e) { alert(e.message); }
}
function mailCloseCompose() { document.getElementById('mailComposeModal').style.display = 'none'; }
function mailRefresh() { loadGmailInbox(); }
function mailSwitchFolder() {
gmailLabel = document.getElementById('mailFolderSelect').value;
gmailCurrentId = null;
document.getElementById('mailReaderContent').style.display = 'none';
document.getElementById('mailReaderEmpty').style.display = 'flex';
loadGmailInbox();
}
async function loadGmailLabels() {
if (!await ensureToken()) return;
try {
const res = await fetch('/api/gmail-proxy.php', {
method: 'POST', headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ action: 'labels', accessToken: gAccessToken })
});
const data = await res.json();
const select = document.getElementById('mailFolderSelect');
if (select && data.labels) {
const labelNames = { INBOX: 'Inkorg', SENT: 'Skickat', DRAFTS: 'Utkast', TRASH: 'Papperskorg', SPAM: 'Skräppost', STARRED: 'Stjärnmärkt', IMPORTANT: 'Viktigt' };
const show = data.labels.filter(l => ['INBOX','SENT','DRAFTS','TRASH','SPAM','STARRED','IMPORTANT'].includes(l.id) || l.type === 'user');
select.innerHTML = show.map(l => '<option value="' + l.id + '"' + (l.id === gmailLabel ? ' selected' : '') + '>' + (labelNames[l.id] || l.name) + '</option>').join('');
}
} catch(e) {}
}
function mailDisconnect() {
gAccessToken = '';
sessionStorage.removeItem('gAccessToken');
sessionStorage.removeItem('gTokenExpiry');
updateAuthUI();
}