import { Component, createSignal, onMount, onCleanup, For, Show } from 'solid-js'
import { Rocket, CheckCircle, XCircle, Loader, Sparkles, LogIn, LogOut, Shield, ExternalLink, Copy } from 'lucide-solid'
import { getUserScopedKey } from '../../lib/user-storage'
import { instances } from '../../stores/instances'
import { fetchProviders } from '../../stores/session-api'

interface AntigravityModel {
    id: string
    name: string
    family?: string
    reasoning?: boolean
    tool_call?: boolean
    limit?: {
        context: number
        output: number
    }
}

interface AntigravityToken {
    access_token: string
    refresh_token?: string
    expires_in: number
    created_at: number
}

const ANTIGRAVITY_TOKEN_KEY = "antigravity_oauth_token"
const ANTIGRAVITY_PROJECT_KEY = "antigravity_project_id"

const AntigravitySettings: Component = () => {
    const [models, setModels] = createSignal<AntigravityModel[]>([])
    const [isLoading, setIsLoading] = createSignal(true)
    const [connectionStatus, setConnectionStatus] = createSignal<'idle' | 'testing' | 'connected' | 'failed'>('idle')
    const [connectionIssue, setConnectionIssue] = createSignal<{ title: string; message: string; link?: string } | null>(null)
    const [authStatus, setAuthStatus] = createSignal<'unknown' | 'authenticated' | 'unauthenticated'>('unknown')
    const [error, setError] = createSignal<string | null>(null)
    const [projectId, setProjectId] = createSignal("")

    // Device auth state
    const [isAuthenticating, setIsAuthenticating] = createSignal(false)
    const [deviceAuthSession, setDeviceAuthSession] = createSignal<{
        sessionId: string
        userCode?: string
        verificationUrl: string
    } | null>(null)
    const [copied, setCopied] = createSignal(false)

    let pollInterval: number | undefined

    // Check stored token on mount
    onMount(async () => {
        const storedProjectId = window.localStorage.getItem(getUserScopedKey(ANTIGRAVITY_PROJECT_KEY))
        if (storedProjectId) {
            setProjectId(storedProjectId)
        }
        checkAuthStatus()
        await loadModels()
        await testConnection()
    })

    onCleanup(() => {
        if (pollInterval) {
            clearInterval(pollInterval)
        }
    })

    const getStoredToken = (): AntigravityToken | null => {
        if (typeof window === "undefined") return null
        try {
            const raw = window.localStorage.getItem(getUserScopedKey(ANTIGRAVITY_TOKEN_KEY))
            if (!raw) return null
            return JSON.parse(raw)
        } catch {
            return null
        }
    }

    const isTokenValid = (token: AntigravityToken | null): boolean => {
        if (!token) return false
        const createdAt = token.created_at > 1e12 ? Math.floor(token.created_at / 1000) : token.created_at
        const expiresAt = (createdAt + token.expires_in) * 1000 - 300000 // 5 min buffer
        return Date.now() < expiresAt
    }

    const parseSubscriptionIssue = (raw: string | null | undefined) => {
        if (!raw) return null
        try {
            const parsed = JSON.parse(raw)
            const errorPayload = parsed?.error
            const message = typeof errorPayload?.message === "string" ? errorPayload.message : raw
            const details = Array.isArray(errorPayload?.details) ? errorPayload.details : []
            const reason = details.find((entry: any) => entry?.reason)?.reason
            const helpLink = details
                .flatMap((entry: any) => Array.isArray(entry?.links) ? entry.links : [])
                .find((link: any) => typeof link?.url === "string")?.url

            if (reason === "SUBSCRIPTION_REQUIRED" || /Gemini Code Assist license/i.test(message)) {
                return {
                    title: "Subscription required",
                    message,
                    link: helpLink
                }
            }
        } catch {
            if (/SUBSCRIPTION_REQUIRED/i.test(raw) || /Gemini Code Assist license/i.test(raw)) {
                return {
                    title: "Subscription required",
                    message: raw
                }
            }
        }
        return null
    }

    const getAuthHeaders = () => {
        const token = getStoredToken()
        const headers: Record<string, string> = {}
        if (token?.access_token && isTokenValid(token)) {
            headers.Authorization = `Bearer ${token.access_token}`
        }
        if (projectId()) {
            headers["X-Antigravity-Project"] = projectId()
        }
        return Object.keys(headers).length > 0 ? headers : undefined
    }

    const checkAuthStatus = () => {
        const token = getStoredToken()
        if (isTokenValid(token)) {
            setAuthStatus('authenticated')
        } else {
            setAuthStatus('unauthenticated')
        }
    }

    const loadModels = async () => {
        setIsLoading(true)
        try {
            const response = await fetch('/api/antigravity/models', {
                headers: getAuthHeaders()
            })
            if (response.ok) {
                const data = await response.json()
                setModels(data.models || [])
                setError(null)
            } else {
                throw new Error('Failed to load models')
            }
        } catch (err) {
            console.error('Failed to load Antigravity models:', err)
            setError('Failed to load models')
        } finally {
            setIsLoading(false)
        }
    }

    const testConnection = async () => {
        setConnectionStatus('testing')
        setConnectionIssue(null)
        try {
            const response = await fetch('/api/antigravity/test', {
                headers: getAuthHeaders()
            })
            if (response.ok) {
                const data = await response.json()
                setConnectionStatus(data.connected ? 'connected' : 'failed')
                const issue = parseSubscriptionIssue(data.error)
                if (issue) {
                    setConnectionIssue(issue)
                }
            } else {
                const errorText = await response.text().catch(() => "")
                const issue = parseSubscriptionIssue(errorText)
                if (issue) {
                    setConnectionIssue(issue)
                }
                setConnectionStatus('failed')
            }
        } catch (err) {
            setConnectionStatus('failed')
        }
    }

    const offlineLabel = () => connectionIssue()?.title ?? "Offline"

    // Start device authorization flow
    const startDeviceAuth = async () => {
        setIsAuthenticating(true)
        setError(null)

        try {
            const response = await fetch('/api/antigravity/device-auth/start', {
                method: 'POST'
            })

            if (!response.ok) {
                const errorData = await response.json().catch(() => ({}))
                const base = errorData.error || 'Failed to start authentication'
                const details = errorData.details ? ` - ${errorData.details}` : ''
                throw new Error(`${base}${details}`)
            }

            const data = await response.json() as {
                sessionId: string
                userCode?: string
                verificationUrl: string
                expiresIn: number
                interval: number
            }

            setDeviceAuthSession({
                sessionId: data.sessionId,
                userCode: data.userCode || "",
                verificationUrl: data.verificationUrl
            })

            // Start polling for token
            const pollIntervalMs = (data.interval || 5) * 1000
            pollInterval = window.setInterval(() => {
                pollForToken(data.sessionId)
            }, pollIntervalMs)

            // Open verification URL in new tab
            window.open(data.verificationUrl, '_blank')

        } catch (err: any) {
            console.error('Device auth error:', err)
            // Try to get detailed error message
            let errorMessage = err.message || 'Authentication failed'
            if (err.details) {
                errorMessage += ` - ${err.details}`
            }
            setError(errorMessage)
            setIsAuthenticating(false)
        }
    }

    // Poll for token completion
    const pollForToken = async (sessionId: string) => {
        try {
            const response = await fetch('/api/antigravity/device-auth/poll', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ sessionId })
            })

            if (!response.ok) {
                const errorData = await response.json().catch(() => ({}))
                if (response.status === 410 || response.status === 404) {
                    // Session expired
                    stopPolling()
                    setError('Session expired. Please try again.')
                    return
                }
                throw new Error(errorData.error || 'Poll failed')
            }

            const data = await response.json() as any

            if (data.status === 'pending') {
                // Still waiting, continue polling
                return
            }

            if (data.status === 'success') {
                // Got tokens! Save them
                const token: AntigravityToken = {
                    access_token: data.accessToken,
                    refresh_token: data.refreshToken,
                    expires_in: data.expiresIn,
                    created_at: Date.now()
                }

                window.localStorage.setItem(
                    getUserScopedKey(ANTIGRAVITY_TOKEN_KEY),
                    JSON.stringify(token)
                )

                stopPolling()
                setAuthStatus('authenticated')
                setError(null)
                loadModels()
                await testConnection()
                for (const instance of instances().values()) {
                    try {
                        await fetchProviders(instance.id)
                    } catch (refreshError) {
                        console.error(`Failed to refresh providers for instance ${instance.id}:`, refreshError)
                    }
                }
                return
            }

            if (data.status === 'denied') {
                stopPolling()
                setError('Access was denied. Please try again.')
                return
            }

            if (data.status === 'expired') {
                stopPolling()
                setError('Session expired. Please try again.')
                return
            }

            if (data.status === 'error') {
                stopPolling()
                setError(data.error || 'Authentication failed')
                return
            }

        } catch (err: any) {
            console.error('Poll error:', err)
            // Don't stop polling on network errors, just log them
        }
    }

    const stopPolling = () => {
        if (pollInterval) {
            clearInterval(pollInterval)
            pollInterval = undefined
        }
        setIsAuthenticating(false)
        setDeviceAuthSession(null)
    }

    const cancelAuth = () => {
        stopPolling()
        setError(null)
    }

    const signOut = () => {
        window.localStorage.removeItem(getUserScopedKey(ANTIGRAVITY_TOKEN_KEY))
        setAuthStatus('unauthenticated')
        setConnectionIssue(null)
        setConnectionStatus('idle')
        for (const instance of instances().values()) {
            fetchProviders(instance.id).catch((refreshError) => {
                console.error(`Failed to refresh providers for instance ${instance.id}:`, refreshError)
            })
        }
    }

    const copyCode = async () => {
        const session = deviceAuthSession()
        if (session?.userCode) {
            await navigator.clipboard.writeText(session.userCode)
            setCopied(true)
            setTimeout(() => setCopied(false), 2000)
        }
    }

    const formatNumber = (num: number): string => {
        if (num >= 1000000) return `${(num / 1000000).toFixed(1)}M`
        if (num >= 1000) return `${(num / 1000).toFixed(0)}K`
        return num.toString()
    }

    const getModelFamily = (model: AntigravityModel): { label: string; color: string } => {
        if (model.id.startsWith('gemini')) return { label: 'Gemini', color: 'bg-blue-500/20 text-blue-400' }
        if (model.id.startsWith('claude')) return { label: 'Claude', color: 'bg-orange-500/20 text-orange-400' }
        if (model.id.startsWith('gpt')) return { label: 'GPT', color: 'bg-green-500/20 text-green-400' }
        return { label: model.family || 'Other', color: 'bg-zinc-700 text-zinc-400' }
    }

    return (
        <div class="space-y-6 p-6">
            {/* Header */}
            <div class="flex items-center justify-between">
                <div class="flex items-center gap-3">
                    <div class="p-2 bg-gradient-to-br from-purple-500/20 to-blue-500/20 rounded-lg">
                        <Rocket class="w-6 h-6 text-purple-400" />
                    </div>
                    <div>
                        <h2 class="text-xl font-semibold text-white">Antigravity</h2>
                        <p class="text-sm text-zinc-400">Premium models via Google authentication</p>
                    </div>
                </div>

                <div class="flex items-center gap-2">
                    {connectionStatus() === 'testing' && (
                        <span class="flex items-center gap-2 text-sm text-zinc-400">
                            <Loader class="w-4 h-4 animate-spin" />
                            Testing...
                        </span>
                    )}
                    {connectionStatus() === 'connected' && (
                        <span class="flex items-center gap-2 text-sm text-emerald-400">
                            <CheckCircle class="w-4 h-4" />
                            Connected
                        </span>
                    )}
                    {connectionStatus() === 'failed' && (
                        <span class="flex items-center gap-2 text-sm text-red-400">
                            <XCircle class="w-4 h-4" />
                            {offlineLabel()}
                        </span>
                    )}
                </div>
            </div>

            {/* Info Banner */}
            <div class="bg-gradient-to-r from-purple-500/10 via-blue-500/10 to-purple-500/10 border border-purple-500/20 rounded-xl p-4">
                <div class="flex items-start gap-3">
                    <Sparkles class="w-5 h-5 text-purple-400 mt-0.5" />
                    <div>
                        <h3 class="font-semibold text-purple-300 mb-1">Premium AI Models</h3>
                        <p class="text-sm text-zinc-300">
                            Antigravity provides access to Gemini 3 Pro/Flash, Claude Sonnet 4.5, Claude Opus 4.5,
                            and GPT-OSS 120B through Google's infrastructure. Sign in with your Google account to get started.
                        </p>
                    </div>
                </div>
            </div>

            {/* Authentication Section */}
            <div class="bg-zinc-900/50 border border-zinc-800 rounded-xl p-4 space-y-4">
                <div class="flex items-center justify-between">
                    <div class="flex items-center gap-3">
                        <Shield class="w-5 h-5 text-zinc-400" />
                        <div>
                            <h4 class="font-medium text-white">Google Authentication</h4>
                            <p class="text-xs text-zinc-500">
                                {authStatus() === 'authenticated'
                                    ? 'You are signed in and can use Antigravity models'
                                    : 'Sign in with Google to access premium models'}
                            </p>
                        </div>
                    </div>

                    <Show when={authStatus() === 'authenticated'}>
                        <div class="flex items-center gap-3">
                            <span class="flex items-center gap-2 px-3 py-1.5 bg-emerald-500/20 text-emerald-400 rounded-lg text-sm">
                                <CheckCircle class="w-4 h-4" />
                                Authenticated
                            </span>
                            <button
                                onClick={signOut}
                                class="flex items-center gap-2 px-3 py-1.5 text-sm text-zinc-400 hover:text-white bg-zinc-800 hover:bg-zinc-700 rounded-lg transition-colors"
                            >
                                <LogOut class="w-4 h-4" />
                                Sign out
                            </button>
                        </div>
                    </Show>
                </div>

                {/* Not authenticated - show login button or device auth flow */}
                <Show when={authStatus() === 'unauthenticated'}>
                    <Show when={!deviceAuthSession()}>
                        <button
                            onClick={startDeviceAuth}
                            disabled={isAuthenticating()}
                            class="w-full flex items-center justify-center gap-2 px-4 py-3 bg-purple-600 hover:bg-purple-500 disabled:bg-purple-600/50 text-white rounded-lg transition-colors"
                        >
                            {isAuthenticating() ? (
                                <>
                                    <Loader class="w-5 h-5 animate-spin" />
                                    Starting authentication...
                                </>
                            ) : (
                                <>
                                    <LogIn class="w-5 h-5" />
                                    Sign in with Google
                                </>
                            )}
                        </button>
                    </Show>

                    {/* Device auth in progress - show code */}
                    <Show when={deviceAuthSession()}>
                        <div class="bg-purple-500/10 border border-purple-500/30 rounded-lg p-4 space-y-4">
                            <div class="text-center">
                                <Show
                                    when={Boolean(deviceAuthSession()?.userCode)}
                                    fallback={
                                        <p class="text-sm text-zinc-300">
                                            Complete the sign-in in the browser window.
                                        </p>
                                    }
                                >
                                    <p class="text-sm text-zinc-300 mb-3">
                                        Enter this code on the Google sign-in page:
                                    </p>
                                    <div class="flex items-center justify-center gap-3">
                                        <code class="px-6 py-3 bg-zinc-900 rounded-lg text-2xl font-mono font-bold text-white tracking-widest">
                                            {deviceAuthSession()?.userCode}
                                        </code>
                                        <button
                                            onClick={copyCode}
                                            class="p-2 text-zinc-400 hover:text-white bg-zinc-800 hover:bg-zinc-700 rounded-lg transition-colors"
                                            title="Copy code"
                                        >
                                            {copied() ? <CheckCircle class="w-5 h-5 text-emerald-400" /> : <Copy class="w-5 h-5" />}
                                        </button>
                                    </div>
                                </Show>
                            </div>

                            <div class="flex items-center justify-center gap-2 text-sm text-purple-300">
                                <Loader class="w-4 h-4 animate-spin" />
                                Waiting for you to complete sign-in...
                            </div>

                            <div class="flex items-center justify-center gap-4">
                                <a
                                    href={deviceAuthSession()?.verificationUrl}
                                    target="_blank"
                                    rel="noopener noreferrer"
                                    class="flex items-center gap-2 px-4 py-2 bg-purple-600 hover:bg-purple-500 text-white rounded-lg text-sm transition-colors"
                                >
                                    <ExternalLink class="w-4 h-4" />
                                    Open Google Sign-in
                                </a>
                                <button
                                    onClick={cancelAuth}
                                    class="px-4 py-2 text-zinc-400 hover:text-white bg-zinc-800 hover:bg-zinc-700 rounded-lg text-sm transition-colors"
                                >
                                    Cancel
                                </button>
                            </div>
                        </div>
                    </Show>
                </Show>

                <div class="mt-4 flex flex-col gap-2 text-sm text-zinc-400">
                    <label class="text-xs uppercase tracking-wide text-zinc-500">Project ID (optional)</label>
                    <input
                        type="text"
                        value={projectId()}
                        onInput={(event) => {
                            const value = event.currentTarget.value.trim()
                            setProjectId(value)
                            if (typeof window !== "undefined") {
                                const key = getUserScopedKey(ANTIGRAVITY_PROJECT_KEY)
                                if (value) {
                                    window.localStorage.setItem(key, value)
                                } else {
                                    window.localStorage.removeItem(key)
                                }
                            }
                        }}
                        class="w-full bg-zinc-900/70 border border-zinc-800 rounded-lg px-3 py-2 text-sm text-white placeholder:text-zinc-600 focus:outline-none focus:ring-2 focus:ring-purple-500/50"
                        placeholder="e.g. my-gcp-project-id"
                    />
                    <p class="text-xs text-zinc-500">
                        Set this only if your account is tied to a specific Code Assist project.
                    </p>
                    <button
                        type="button"
                        onClick={() => testConnection()}
                        class="w-fit px-3 py-1.5 text-xs bg-zinc-800 hover:bg-zinc-700 rounded-lg text-zinc-200"
                    >
                        Re-check connection
                    </button>
                </div>
            </div>

            {/* Error Display */}
            <Show when={error()}>
                <div class="p-4 bg-red-500/10 border border-red-500/30 rounded-lg text-red-400 text-sm">
                    {error()}
                </div>
            </Show>

            <Show when={connectionIssue()}>
                <div class="p-4 bg-amber-500/10 border border-amber-500/30 rounded-lg text-amber-200 text-sm space-y-2">
                    <div class="font-semibold">{connectionIssue()?.title}</div>
                    <div>{connectionIssue()?.message}</div>
                    <Show when={connectionIssue()?.link}>
                        <a
                            href={connectionIssue()?.link}
                            target="_blank"
                            rel="noopener noreferrer"
                            class="inline-flex items-center gap-2 text-amber-300 hover:text-amber-200 underline"
                        >
                            Learn more
                        </a>
                    </Show>
                </div>
            </Show>

            {/* Models Grid */}
            <div class="space-y-4">
                <div class="flex items-center justify-between">
                    <h3 class="text-lg font-medium text-white">Available Models</h3>
                    <button
                        onClick={loadModels}
                        disabled={isLoading()}
                        class="flex items-center gap-2 px-3 py-1.5 text-sm bg-zinc-800 hover:bg-zinc-700 rounded-lg transition-colors"
                    >
                        {isLoading() ? <Loader class="w-4 h-4 animate-spin" /> : null}
                        Refresh
                    </button>
                </div>

                <Show when={isLoading()}>
                    <div class="flex items-center justify-center py-12">
                        <div class="flex items-center gap-3 text-zinc-400">
                            <Loader class="w-6 h-6 animate-spin" />
                            <span>Loading models...</span>
                        </div>
                    </div>
                </Show>

                <Show when={!isLoading() && models().length > 0}>
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                        <For each={models()}>
                            {(model) => {
                                const family = getModelFamily(model)
                                return (
                                    <div class="group bg-zinc-900/50 border border-zinc-800 hover:border-purple-500/50 rounded-xl p-4 transition-all">
                                        <div class="flex items-start justify-between mb-3">
                                            <div>
                                                <h4 class="font-semibold text-white group-hover:text-purple-300 transition-colors">
                                                    {model.name}
                                                </h4>
                                                <p class="text-xs text-zinc-500 font-mono">{model.id}</p>
                                            </div>
                                            <span class={`px-2 py-0.5 text-[10px] font-bold uppercase rounded ${family.color}`}>
                                                {family.label}
                                            </span>
                                        </div>

                                        <div class="flex flex-wrap gap-2 mb-3">
                                            {model.reasoning && (
                                                <span class="px-2 py-0.5 text-[10px] bg-purple-500/20 text-purple-400 rounded">
                                                    Thinking
                                                </span>
                                            )}
                                            {model.tool_call && (
                                                <span class="px-2 py-0.5 text-[10px] bg-blue-500/20 text-blue-400 rounded">
                                                    Tool Use
                                                </span>
                                            )}
                                        </div>

                                        {model.limit && (
                                            <div class="flex items-center gap-4 text-xs text-zinc-500">
                                                <span>Context: {formatNumber(model.limit.context)}</span>
                                                <span>Output: {formatNumber(model.limit.output)}</span>
                                            </div>
                                        )}
                                    </div>
                                )
                            }}
                        </For>
                    </div>
                </Show>

                <Show when={!isLoading() && models().length === 0}>
                    <div class="text-center py-12 text-zinc-500">
                        <p>Models will be available after signing in.</p>
                    </div>
                </Show>
            </div>

            {/* Usage Info */}
            <div class="bg-zinc-900/50 border border-zinc-800 rounded-xl p-4">
                <h4 class="font-medium text-white mb-2">How to Use</h4>
                <ul class="text-sm text-zinc-400 space-y-1">
                    <li>• Click "Sign in with Google" and enter the code on the Google page</li>
                    <li>• Once authenticated, select any Antigravity model from the chat model picker</li>
                    <li>• Models include Gemini 3, Claude Sonnet/Opus 4.5, and GPT-OSS</li>
                    <li>• Thinking-enabled models show step-by-step reasoning</li>
                    <li>• Full tool use and MCP support included</li>
                </ul>
            </div>
        </div>
    )
}

export default AntigravitySettings
