const AUTH_SESSION_STORAGE_KEY = 'orgboard.auth.session.v1';

function normalizeAuthSession(session) {
    if (!session) return null;
    const normalized = { ...session };
    if (!normalized.expires_at && normalized.expires_in) {
        normalized.expires_at = Math.floor(Date.now() / 1000) + Number(normalized.expires_in);
    }
    return normalized;
}

function getStoredAuthSession() {
    try {
        return normalizeAuthSession(JSON.parse(localStorage.getItem(AUTH_SESSION_STORAGE_KEY) || 'null'));
    } catch {
        return null;
    }
}

function storeAuthSession(session) {
    const normalized = normalizeAuthSession(session);
    state.authSession = normalized;
    if (normalized) {
        localStorage.setItem(AUTH_SESSION_STORAGE_KEY, JSON.stringify(normalized));
    } else {
        localStorage.removeItem(AUTH_SESSION_STORAGE_KEY);
    }
}

function getCloudApiBase() {
    return state.cloudConfig?.cloudApiUrl || '';
}

function getPublicAppBase() {
    return (state.cloudConfig?.publicAppUrl || 'https://orgboard.iacovici.it').replace(/\/$/, '');
}

function getSupabaseConfig() {
    return {
        url: state.cloudConfig?.supabaseUrl || '',
        key: state.cloudConfig?.supabasePublishableKey || ''
    };
}

function getDesktopOAuthRedirectUrl() {
    return `${getPublicAppBase()}/desktop-auth.html`;
}

async function callSupabaseAuth(path, body, extra = {}) {
    const { url, key } = getSupabaseConfig();
    if (!url || !key) throw new Error('Cloud auth is not configured yet.');
    const response = await fetch(`${url}/auth/v1/${path}`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            apikey: key,
            ...extra.headers
        },
        body: JSON.stringify(body)
    });
    const data = await response.json().catch(() => ({}));
    if (!response.ok) {
        throw new Error(data.msg || data.error_description || data.error || 'Authentication failed');
    }
    return data;
}

async function cloudRequest(path, { method = 'GET', token, body } = {}) {
    const response = await fetch(`${getCloudApiBase()}${path}`, {
        method,
        headers: {
            'Content-Type': 'application/json',
            ...(token ? { Authorization: `Bearer ${token}` } : {})
        },
        ...(body ? { body: JSON.stringify(body) } : {})
    });
    const data = await response.json().catch(() => ({}));
    if (!response.ok) {
        throw new Error(data.error || 'Cloud request failed');
    }
    return data;
}

function parseOAuthCallbackUrl(callbackUrl) {
    if (!callbackUrl) return {};
    try {
        const normalized = callbackUrl.startsWith('orgboardai://')
            ? callbackUrl.replace('orgboardai://', 'https://orgboardai.local/')
            : callbackUrl;
        const parsed = new URL(normalized);
        const hashParams = new URLSearchParams(parsed.hash.replace(/^#/, ''));
        const queryParams = parsed.searchParams;
        return {
            access_token: hashParams.get('access_token') || queryParams.get('access_token') || '',
            refresh_token: hashParams.get('refresh_token') || queryParams.get('refresh_token') || '',
            expires_in: hashParams.get('expires_in') || queryParams.get('expires_in') || '',
            expires_at: hashParams.get('expires_at') || queryParams.get('expires_at') || '',
            token_type: hashParams.get('token_type') || queryParams.get('token_type') || '',
            error: hashParams.get('error_description') || hashParams.get('error') || queryParams.get('error_description') || queryParams.get('error') || '',
            error_code: hashParams.get('error_code') || queryParams.get('error_code') || ''
        };
    } catch {
        return {};
    }
}

async function finishOAuthSessionFromUrl(callbackUrl) {
    const payload = parseOAuthCallbackUrl(callbackUrl);
    if (payload.error) {
        throw new Error(payload.error);
    }
    if (!payload.access_token || !payload.refresh_token) {
        throw new Error('Google sign-in did not return a valid session.');
    }
    storeAuthSession({
        access_token: payload.access_token,
        refresh_token: payload.refresh_token,
        expires_in: payload.expires_in ? Number(payload.expires_in) : undefined,
        expires_at: payload.expires_at ? Number(payload.expires_at) : undefined,
        token_type: payload.token_type || 'bearer'
    });
    await bootstrapCloudIdentity();
    closeAuthGate();
    showToast('Signed in with Google.', 'success');
    await continueAuthenticatedStartup();
}

function waitForAuth(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}

async function refreshAuthSessionIfNeeded() {
    const session = getStoredAuthSession();
    if (!session?.refresh_token) return null;
    const now = Math.floor(Date.now() / 1000);
    if ((session.expires_at || 0) - now > 120) {
        state.authSession = session;
        return session;
    }
    const refreshed = await callSupabaseAuth('token?grant_type=refresh_token', {
        refresh_token: session.refresh_token
    });
    storeAuthSession(refreshed);
    return state.authSession;
}

async function bootstrapCloudIdentity() {
    const session = await refreshAuthSessionIfNeeded();
    if (!session?.access_token) throw new Error('Missing auth session');
    let lastError = null;
    for (const delay of [0, 350, 900, 1800]) {
        if (delay) await waitForAuth(delay);
        try {
            const authData = await cloudRequest('/auth/me', { token: session.access_token });
            const entitlementData = await cloudRequest('/entitlements/me', { token: session.access_token });
            state.authProfile = authData.user || null;
            state.cloudEntitlement = entitlementData.entitlement || authData.entitlement || null;
            state.cloudUsage = entitlementData.usage || null;
            renderAccountSummary();
            registerCurrentDevice().catch(() => {});
            return true;
        } catch (error) {
            lastError = error;
        }
    }
    throw lastError || new Error('Authentication bootstrap failed');
}

async function registerCurrentDevice() {
    if (!state.authSession?.access_token) return;
    const fingerprint = [
        navigator.platform || 'unknown-platform',
        navigator.userAgent || 'unknown-agent',
        window.orgBoardDesktop?.isDesktop ? 'desktop' : 'browser'
    ].join('|');
    await cloudRequest('/devices/register', {
        method: 'POST',
        token: state.authSession.access_token,
        body: {
            device_name: window.orgBoardDesktop?.isDesktop ? 'Org Board AI Desktop' : 'Org Board AI Browser',
            device_fingerprint: fingerprint
        }
    });
}

async function syncPortalProjectSnapshot(item, division, todos = []) {
    if (!state.authSession?.access_token) throw new Error('Sign in to enable public client portals.');
    const completed = todos.filter((todo) => Number(todo.done) === 1 || todo.done === true).length;
    const total = todos.length;
    const snapshot = {
        client_name: item.title,
        local_item_id: String(item.id),
        division_id: division?.id || item.division_id || null,
        current_stage: division?.name || '',
        stage_desc: division?.subtitle || '',
        stage_color: division?.color_var || '',
        tasks_done: completed,
        tasks_total: total,
        progress_percent: total ? Math.round((completed / total) * 100) : 0,
        updated_at: new Date().toISOString()
    };
    const response = await cloudRequest('/portal/projects/sync', {
        method: 'POST',
        token: state.authSession.access_token,
        body: {
            local_item_id: String(item.id),
            client_name: item.title,
            division_id: division?.id || item.division_id || null,
            snapshot,
            is_active: true
        }
    });
    return response.public_url || `${getPublicAppBase()}/portal.html?token=${response.project?.public_token || ''}`;
}

function setAuthMode(mode = 'signin') {
    const authModeInput = document.getElementById('authModeInput');
    const registerFields = document.getElementById('authRegisterFields');
    const confirmWrap = document.getElementById('authConfirmWrap');
    const submitBtn = document.getElementById('authSubmitBtn');
    const switchBtn = document.getElementById('authSwitchModeBtn');
    const title = document.getElementById('authGateTitle');
    const body = document.getElementById('authGateBody');
    if (authModeInput) authModeInput.value = mode;
    if (registerFields) registerFields.classList.toggle('hidden', mode !== 'signup');
    if (confirmWrap) confirmWrap.classList.toggle('hidden', mode !== 'signup');
    if (submitBtn) submitBtn.textContent = mode === 'signup' ? 'Create Account' : 'Sign In';
    if (switchBtn) switchBtn.textContent = mode === 'signup' ? 'Already have an account? Sign in' : 'New here? Create an account';
    if (title) title.textContent = mode === 'signup' ? 'Create your Org Board AI account' : 'Sign in to Org Board AI';
    if (body) body.textContent = mode === 'signup'
        ? 'Create a real account so the desktop app can unlock your cloud plan, sync portals, and keep your entitlements active.'
        : 'Use your Org Board AI account to unlock cloud features, paid plans, and synced client portals.';
}

function openAuthGate(message = '') {
    const modal = document.getElementById('authGateModal');
    const status = document.getElementById('authStatusMessage');
    const configPanel = document.getElementById('authConfigPanel');
    const cloudApiInput = document.getElementById('authCloudApiUrlInput');
    const supabaseUrlInput = document.getElementById('authSupabaseUrlInput');
    const configInput = document.getElementById('authPublishableKeyInput');
    if (!modal) return;
    status.textContent = message || '';
    status.className = `text-sm ${message ? 'text-amber-300' : 'text-gray-500'} min-h-[1.25rem]`;
    if (configPanel) configPanel.classList.toggle('hidden', Boolean(state.cloudConfig?.authReady));
    if (cloudApiInput && !cloudApiInput.value) cloudApiInput.value = state.cloudConfig?.cloudApiUrl || '';
    if (supabaseUrlInput && !supabaseUrlInput.value) supabaseUrlInput.value = state.cloudConfig?.supabaseUrl || '';
    if (configInput && !configInput.value) configInput.value = state.cloudConfig?.supabasePublishableKey || '';
    modal.classList.remove('hidden');
}

function closeAuthGate() {
    document.getElementById('authGateModal')?.classList.add('hidden');
}

function setAuthBusy(isBusy, label = 'Working...') {
    const submitBtn = document.getElementById('authSubmitBtn');
    if (!submitBtn) return;
    submitBtn.disabled = isBusy;
    submitBtn.innerHTML = isBusy
        ? `<i class="fas fa-spinner fa-spin"></i> ${escapeHtml(label)}`
        : escapeHtml((document.getElementById('authModeInput')?.value === 'signup') ? 'Create Account' : 'Sign In');
}

function setGoogleBusy(isBusy, label = 'Continue with Google') {
    const button = document.getElementById('authGoogleBtn');
    if (!button) return;
    button.disabled = isBusy;
    button.classList.toggle('opacity-60', isBusy);
    button.classList.toggle('cursor-not-allowed', isBusy);
    button.innerHTML = isBusy
        ? `<i class="fas fa-spinner fa-spin"></i> ${escapeHtml(label)}`
        : `<i class="fab fa-google text-red-300"></i> Continue with Google`;
}

function renderAccountSummary() {
    const emailEl = document.getElementById('settingsAccountEmail');
    const planEl = document.getElementById('settingsAccountPlan');
    const usageEl = document.getElementById('settingsAccountUsage');
    const statusEl = document.getElementById('settingsAccountStatus');
    if (emailEl) emailEl.textContent = state.authProfile?.email || 'Not signed in';
    if (planEl) planEl.textContent = state.cloudEntitlement?.plan_code ? state.cloudEntitlement.plan_code.toUpperCase() : '—';
    if (usageEl) usageEl.textContent = state.cloudUsage ? `${Number(state.cloudUsage.tokens_in || 0) + Number(state.cloudUsage.tokens_out || 0)} tokens this month` : 'No cloud usage yet';
    if (statusEl) statusEl.textContent = state.cloudEntitlement?.status || 'inactive';
}

async function handleAuthSubmit(event) {
    event.preventDefault();
    const mode = document.getElementById('authModeInput')?.value || 'signin';
    const name = document.getElementById('authNameInput')?.value.trim();
    const email = document.getElementById('authEmailInput')?.value.trim();
    const password = document.getElementById('authPasswordInput')?.value || '';
    const confirm = document.getElementById('authConfirmPasswordInput')?.value || '';
    const status = document.getElementById('authStatusMessage');

    if (!state.cloudConfig?.authReady) {
        openAuthGate('Cloud auth is not configured yet. Add your Supabase publishable key first.');
        return;
    }
    if (!email || !password) {
        status.textContent = 'Email and password are required.';
        status.className = 'text-sm text-red-300 min-h-[1.25rem]';
        return;
    }
    if (mode === 'signup' && password !== confirm) {
        status.textContent = 'Passwords do not match.';
        status.className = 'text-sm text-red-300 min-h-[1.25rem]';
        return;
    }

    setAuthBusy(true, mode === 'signup' ? 'Creating account...' : 'Signing in...');
    status.textContent = '';

    try {
        let payload;
        if (mode === 'signup') {
            payload = await callSupabaseAuth('signup', {
                email,
                password,
                data: name ? { full_name: name } : {}
            });
            if (!payload.session) {
                setAuthBusy(false);
                status.textContent = 'Account created. Check your email if confirmation is enabled, then sign in.';
                status.className = 'text-sm text-emerald-300 min-h-[1.25rem]';
                setAuthMode('signin');
                return;
            }
            payload = await callSupabaseAuth('token?grant_type=password', { email, password });
        } else {
            payload = await callSupabaseAuth('token?grant_type=password', { email, password });
        }

        storeAuthSession(payload.session || payload);
        await bootstrapCloudIdentity();
        closeAuthGate();
        showToast(mode === 'signup' ? 'Account created.' : 'Signed in.', 'success');
        await continueAuthenticatedStartup();
    } catch (error) {
        status.textContent = error.message || 'Authentication failed';
        status.className = 'text-sm text-red-300 min-h-[1.25rem]';
    } finally {
        setAuthBusy(false);
    }
}

async function handleGoogleAuth() {
    const status = document.getElementById('authStatusMessage');
    if (!state.cloudConfig?.authReady) {
        openAuthGate('Cloud auth is not configured yet.');
        return;
    }
    const { url } = getSupabaseConfig();
    if (!url) {
        openAuthGate('Supabase URL is missing.');
        return;
    }

    const redirectTo = getDesktopOAuthRedirectUrl();
    const authUrl = new URL(`${url}/auth/v1/authorize`);
    authUrl.searchParams.set('provider', 'google');
    authUrl.searchParams.set('redirect_to', redirectTo);
    authUrl.searchParams.set('scopes', 'openid email profile');
    authUrl.searchParams.set('response_type', 'token');
    authUrl.searchParams.set('prompt', 'select_account');

    setGoogleBusy(true, 'Waiting for Google...');
    status.textContent = 'Continue in your browser, then return to the app.';
    status.className = 'text-sm text-indigo-200 min-h-[1.25rem]';

    let cleanup = null;
    try {
        const settlePromise = new Promise((resolve, reject) => {
            const timeout = setTimeout(() => {
                cleanup?.();
                reject(new Error('Google sign-in timed out. Complete it in the browser, then try again.'));
            }, 180000);

            const finalize = async (callbackUrl) => {
                if (!callbackUrl) return;
                clearTimeout(timeout);
                cleanup?.();
                try {
                    await finishOAuthSessionFromUrl(callbackUrl);
                    resolve(true);
                } catch (error) {
                    reject(error);
                }
            };

            const unsub = window.orgBoardDesktop?.onAuthCallback?.((callbackUrl) => {
                finalize(callbackUrl);
            });
            cleanup = () => {
                clearTimeout(timeout);
                if (typeof unsub === 'function') unsub();
            };
        });

        await window.orgBoardDesktop?.openExternal?.(authUrl.toString());
        const pending = await window.orgBoardDesktop?.getPendingAuthCallback?.();
        if (pending) {
            await finishOAuthSessionFromUrl(pending);
        } else {
            await settlePromise;
        }
    } catch (error) {
        status.textContent = error.message || 'Google sign-in failed';
        status.className = 'text-sm text-red-300 min-h-[1.25rem]';
    } finally {
        cleanup?.();
        setGoogleBusy(false);
    }
}

async function logoutUser() {
    try {
        const session = state.authSession;
        const { url, key } = getSupabaseConfig();
        if (session?.access_token && url && key) {
            await fetch(`${url}/auth/v1/logout`, {
                method: 'POST',
                headers: {
                    apikey: key,
                    Authorization: `Bearer ${session.access_token}`
                }
            }).catch(() => {});
        }
    } finally {
        storeAuthSession(null);
        state.authProfile = null;
        state.cloudEntitlement = null;
        state.cloudUsage = null;
        window.location.reload();
    }
}

async function initAuthGate() {
    state.cloudConfig = await api.getPublicConfig();
    renderAccountSummary();

    const session = getStoredAuthSession();
    if (!session) {
        openAuthGate(state.cloudConfig?.authReady ? '' : 'Cloud auth is not configured yet. Add the Supabase publishable key and reopen the app.');
        state.authInitialized = true;
        return false;
    }

    try {
        state.authSession = session;
        await bootstrapCloudIdentity();
        state.authInitialized = true;
        return true;
    } catch (_error) {
        state.authSession = session;
        openAuthGate('We could not finish cloud sign-in yet. Try signing in again in a few seconds.');
        state.authInitialized = true;
        return false;
    }
}

async function saveAuthCloudConfig() {
    const cloudApiUrl = document.getElementById('authCloudApiUrlInput')?.value.trim();
    const supabaseUrl = document.getElementById('authSupabaseUrlInput')?.value.trim();
    const key = document.getElementById('authPublishableKeyInput')?.value.trim();
    if (!cloudApiUrl || !supabaseUrl || !key) {
        openAuthGate('Paste the cloud API URL, Supabase URL, and publishable key first.');
        return;
    }
    state.cloudConfig = await api.savePublicConfig({
        cloudApiUrl,
        supabaseUrl,
        supabasePublishableKey: key
    });
    openAuthGate('Cloud auth config saved. You can sign in now.');
}

function initAuthUi() {
    document.getElementById('authForm')?.addEventListener('submit', handleAuthSubmit);
    document.getElementById('authSwitchModeBtn')?.addEventListener('click', () => {
        const nextMode = (document.getElementById('authModeInput')?.value || 'signin') === 'signup' ? 'signin' : 'signup';
        setAuthMode(nextMode);
    });
    document.getElementById('saveAuthConfigBtn')?.addEventListener('click', saveAuthCloudConfig);
    document.getElementById('settingsLogoutBtn')?.addEventListener('click', logoutUser);
    document.getElementById('onboardingLogoutBtn')?.addEventListener('click', logoutUser);
    document.getElementById('authGoogleBtn')?.addEventListener('click', handleGoogleAuth);
    setAuthMode('signin');
}
