import { Check, Facebook, Instagram, LoaderCircle, MessageCircle, Plug, Plus, RefreshCw, Settings2, Unplug } from 'lucide-react';
import { useEffect, useState } from 'react';
import { useApp } from '../context/AppContext';
import { ApiError } from '../services/api';
import { channelsApi } from '../services/domain';
import type { Channel } from '../types';

interface FacebookCallback {
    success: boolean;
    message: string;
    data?: { session_id?: string; pages?: Array<{ id: string; name: string }> };
}

export function ChannelsPage() {
    const { current, can } = useApp();
    const [channels, setChannels] = useState<Channel[]>([]);
    const [loading, setLoading] = useState(true);
    const [busy, setBusy] = useState(false);
    const [error, setError] = useState('');
    const [notice, setNotice] = useState('');
    const [sessionId, setSessionId] = useState('');
    const [pages, setPages] = useState<Array<{ id: string; name: string }>>([]);
    const [selectedPage, setSelectedPage] = useState('');
    const [showPages, setShowPages] = useState(false);
    const [actionChannel, setActionChannel] = useState<number | null>(null);
    const [detailsChannel, setDetailsChannel] = useState<number | null>(null);
    const [channelStatuses, setChannelStatuses] = useState<Record<number, Awaited<ReturnType<typeof channelsApi.status>>>>({});

    async function refresh() {
        if (!current) return;
        setLoading(true);
        try { setChannels(await channelsApi.list(current.workspace.id)); setError(''); }
        catch (cause) { setError(cause instanceof Error ? cause.message : 'Could not load channels.'); }
        finally { setLoading(false); }
    }
    useEffect(() => { void refresh(); }, [current?.workspace.id]);

    async function connectFacebook() {
        if (!current || busy) return;
        setBusy(true); setError(''); setNotice('');
        try {
            const { authorization_url: url } = await channelsApi.connectFacebook(current.workspace.id);
            await completeAuthorization(url);
        } catch (cause) {
            setError(cause instanceof ApiError && cause.status === 503
                ? 'Facebook connection is unavailable. Configure META_APP_ID, META_APP_SECRET, and META_REDIRECT_URI, then try again.'
                : cause instanceof Error ? cause.message : 'Could not connect Facebook.');
        } finally { setBusy(false); }
    }
    async function completeAuthorization(url: string) {
        if (!current) return;
        const popup = window.open(url, 'relay-facebook-connect', 'popup,width=640,height=760');
        if (!popup) throw new Error('The Facebook login window was blocked. Allow pop-ups and try again.');
        try {
            const callback = await waitForOAuthCallback(popup);
            if (!callback.success || !callback.data?.session_id) throw new Error(callback.message || 'Facebook authorization did not complete.');
            setSessionId(callback.data.session_id);
            let availablePages = callback.data.pages ?? [];
            if (availablePages.length === 0) availablePages = (await channelsApi.facebookPages(current.workspace.id, callback.data.session_id)).pages;
            setPages(availablePages);
            if (availablePages.length === 1) await choosePage(callback.data.session_id, availablePages[0].id);
            else if (availablePages.length > 1) setShowPages(true);
            else throw new Error('No Facebook Pages were found for this account.');
        } catch (cause) {
            popup.close();
            throw cause;
        }
    }
    async function waitForOAuthCallback(popup: Window): Promise<FacebookCallback> {
        return new Promise((resolve, reject) => {
            const started = Date.now();
            const timer = window.setInterval(() => {
                if (popup.closed) {
                    window.clearInterval(timer);
                    reject(new Error('Facebook authorization window was closed.'));
                    return;
                }
                if (Date.now() - started > 9 * 60_000) {
                    window.clearInterval(timer);
                    popup.close();
                    reject(new Error('Facebook authorization timed out. Please try again.'));
                    return;
                }
                let callbackOrigin: string;
                try { callbackOrigin = new URL(popup.location.href).origin; }
                catch { return; }
                if (callbackOrigin !== window.location.origin) return;
                try {
                    const response = popup.document.body.innerText.trim();
                    if (!response) return;
                    const result = JSON.parse(response) as FacebookCallback;
                    window.clearInterval(timer);
                    popup.close();
                    resolve(result);
                } catch (cause) {
                    window.clearInterval(timer);
                    popup.close();
                    reject(cause instanceof Error ? new Error(`Facebook callback response could not be read: ${cause.message}`) : new Error('Facebook callback response could not be read.'));
                }
            }, 500);
        });
    }
    async function choosePage(id: string, pageId: string) {
        if (!current || !pageId) return;
        setBusy(true); setError('');
        try {
            const channel = await channelsApi.selectFacebookPage(current.workspace.id, id, pageId);
            setShowPages(false);
            setSessionId('');
            setNotice(`${channel.name} connected successfully.`);
            await refresh();
        } catch (cause) { setError(cause instanceof Error ? cause.message : 'Could not connect this Facebook Page.'); }
        finally { setBusy(false); }
    }
    async function disconnect(channel: Channel) {
        if (!current || !window.confirm(`Disconnect ${channel.name}? New messages will no longer be received.`)) return;
        setActionChannel(channel.id); setError('');
        try { await channelsApi.disconnect(current.workspace.id, channel.id); setNotice(`${channel.name} disconnected.`); await refresh(); }
        catch (cause) { setError(cause instanceof Error ? cause.message : 'Could not disconnect this channel.'); }
        finally { setActionChannel(null); }
    }
    async function reconnect(channel: Channel) {
        if (!current) return;
        setActionChannel(channel.id); setError('');
        try {
            const result = await channelsApi.reconnect(current.workspace.id, channel.id);
            if ('authorization_url' in result) {
                setBusy(true);
                await completeAuthorization(result.authorization_url);
            }
            else await refresh();
        } catch (cause) {
            setError(cause instanceof ApiError && cause.status === 503
                ? 'Facebook connection is unavailable. Configure META_APP_ID, META_APP_SECRET, and META_REDIRECT_URI, then try again.'
                : cause instanceof Error ? cause.message : 'Could not reconnect this channel.');
        }
        finally { setBusy(false); setActionChannel(null); }
    }
    async function toggleDiagnostics(channel: Channel) {
        if (!current) return;
        if (detailsChannel === channel.id) {
            setDetailsChannel(null);
            return;
        }
        setDetailsChannel(channel.id);
        try {
            const status = await channelsApi.status(current.workspace.id, channel.id);
            setChannelStatuses((existing) => ({ ...existing, [channel.id]: status }));
        } catch (cause) {
            setError(cause instanceof Error ? cause.message : 'Could not load channel readiness details.');
        }
    }
    const connected = channels.filter((channel) => channel.status === 'connected').length;

    return <div className="channels-page">
        <div className="page-heading"><div><div className="eyebrow">WORKSPACE INTEGRATIONS</div><h1>Channels</h1><p>Connect your messaging accounts to bring conversations into the inbox.</p></div>{can('channels.manage') && <button className="button button-primary" disabled={busy} onClick={() => void connectFacebook()}>{busy ? <LoaderCircle className="spin" size={16} /> : <Plus size={16} />}Connect channel</button>}</div>
        {error && <div role="alert" className="alert-error">{error}<button onClick={() => setError('')}>×</button></div>}
        {notice && <div className="alert-success">{notice}<button onClick={() => setNotice('')}>×</button></div>}
        <div className="channel-summary"><div><span className="channel-summary-icon"><Plug size={17} /></span><span><b>{connected} connected</b><small>Channels connected to this workspace</small></span></div><div><span className="channel-summary-icon muted-channel"><MessageCircle size={17} /></span><span><b>{channels.length} total channels</b><small>Across all messaging platforms</small></span></div><button className="button button-outline" onClick={() => void refresh()}><RefreshCw size={14} />Refresh</button></div>
        <section className="channel-section"><div className="section-title"><div><h2>Connected channels</h2><p>Manage your active messaging integrations.</p></div></div>
            {loading ? <div className="panel channel-loading">Loading channels…</div> : channels.length === 0 ? <div className="panel channel-empty"><span className="empty-icon"><Plug size={23} /></span><b>No channels connected yet</b><p>Connect a Facebook Page to start receiving customer messages.</p>{can('channels.manage') && <button className="button button-primary" disabled={busy} onClick={() => void connectFacebook()}><Facebook size={15} />Connect Facebook</button>}</div> : <div className="channel-grid">{channels.map((channel) => <article className="panel channel-card" key={channel.id}><div className="channel-card-head"><span className={`platform-icon ${channel.provider}`}><PlatformIcon provider={channel.provider} /></span><span className={`channel-state ${channel.status}`}><i />{channel.status}</span><button className="icon-button small" aria-label={`Channel settings for ${channel.name}`} aria-expanded={detailsChannel === channel.id} onClick={() => void toggleDiagnostics(channel)}><Settings2 size={16} /></button></div><h3>{channel.name}</h3><p>{channel.provider === 'facebook' ? 'Facebook Page' : channel.provider[0].toUpperCase() + channel.provider.slice(1)} · {channel.external_id || 'Account ID unavailable'}</p><div className="channel-capabilities">{Object.entries(channel.capabilities ?? {}).filter(([, enabled]) => enabled).map(([capability]) => <span key={capability}><Check size={11} />{capability.replaceAll('_', ' ')}</span>)}</div>{detailsChannel === channel.id && <ChannelReadiness status={channelStatuses[channel.id]} provider={channel.provider} />}<div className="channel-card-footer"><small>{channel.status === 'connected' ? 'Messages syncing' : 'Reconnect required'}</small><div>{can('channels.manage') && <>{channel.status === 'connected' ? <button className="text-button danger-text" onClick={() => void disconnect(channel)} disabled={actionChannel === channel.id}><Unplug size={13} />Disconnect</button> : <button className="text-button" onClick={() => void reconnect(channel)} disabled={actionChannel === channel.id}><RefreshCw size={13} />Reconnect</button>}</>}</div></div></article>)}</div>}
        </section>
        <section className="channel-section available-section"><div className="section-title"><div><h2>Available channels</h2><p>More channels are on the way.</p></div></div><div className="channel-available-grid"><PlatformCard provider="facebook" title="Facebook Messenger" detail="Connect a Facebook Page and manage Messenger conversations." enabled /><PlatformCard provider="instagram" title="Instagram" detail="Instagram messaging integration is coming soon." /><PlatformCard provider="whatsapp" title="WhatsApp" detail="WhatsApp Business integration is coming soon." /><PlatformCard provider="webchat" title="Website chat" detail="Website chat widget is coming soon." /></div></section>
        {showPages && <div className="modal-backdrop"><div className="modal-card"><button className="modal-close" onClick={() => setShowPages(false)}>×</button><div className="modal-icon"><Facebook size={19} /></div><div className="eyebrow">FACEBOOK MESSENGER</div><h2>Choose a Page</h2><p>Select which Facebook Page you want to connect to this workspace.</p><label>Facebook Page<select value={selectedPage} onChange={(event) => setSelectedPage(event.target.value)}><option value="">Select a Page…</option>{pages.map((page) => <option key={page.id} value={page.id}>{page.name}</option>)}</select></label><div className="modal-actions"><button className="button button-quiet" onClick={() => setShowPages(false)}>Cancel</button><button className="button button-primary" disabled={!selectedPage || busy} onClick={() => void choosePage(sessionId, selectedPage)}>{busy ? 'Connecting…' : 'Connect Page'}<Check size={15} /></button></div></div></div>}
    </div>;
}

function PlatformIcon({ provider }: { provider: string }) {
    if (provider === 'facebook') return <Facebook size={19} />;
    if (provider === 'instagram') return <Instagram size={19} />;
    return <MessageCircle size={19} />;
}
function ChannelReadiness({ status, provider }: {
    status: Awaited<ReturnType<typeof channelsApi.status>> | undefined;
    provider: string;
}) {
    return <div className="channel-readiness" aria-live="polite">
        {!status ? <small>Loading readiness diagnostics…</small> : <>
            <b>Connection readiness</b>
            <span>Channel connected: {status.status === 'connected' ? 'Yes' : 'No'}</span>
            {provider === 'facebook' && <>
                <span>Page selected: {status.page_selected ? 'Yes' : 'No'}</span>
                <span>Page credentials present: {status.credentials_present ? 'Yes' : 'No'}</span>
                <span>Webhook configuration ready: {status.webhook_ready ? 'Yes' : 'No'}</span>
                {!status.webhook_ready && <small>Local app verification settings are missing. External Meta subscriptions are not checked here.</small>}
            </>}
        </>}
    </div>;
}
function PlatformCard({ provider, title, detail, enabled = false }: { provider: string; title: string; detail: string; enabled?: boolean }) {
    return <article className={`panel platform-card${enabled ? ' enabled' : ''}`}><span className={`platform-icon ${provider}`}><PlatformIcon provider={provider} /></span><div><b>{title}</b><p>{detail}</p></div>{enabled ? <span className="available-label">Available</span> : <span className="soon-label">Coming soon</span>}</article>;
}
