import { useState, useEffect, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import {
    Terminal,
    CheckCircle2,
    AlertCircle,
    RefreshCw,
    Cpu,
    Globe,
    CodeXml,
    Loader2,
    Eye,
    RotateCcw,
    Copy,
    X,
    Bot,
    Trash2
} from 'lucide-react';
import { copyToClipboard } from '../../utils/clipboard';
import { request as invoke } from '../../utils/request';
import { showToast } from '../common/ToastContainer';
import ModalDialog from '../common/ModalDialog';
import { cn } from '../../utils/cn';
import { DroidSyncModal } from './DroidSyncModal';
import { OpenCodeSyncModal } from './OpenCodeSyncModal';
import { useProxyModels } from '../../hooks/useProxyModels';
import GroupedSelect from '../common/GroupedSelect';

interface CliSyncCardProps {
    proxyUrl: string;
    apiKey: string;
    className?: string;
}

type CliAppType = 'Claude' | 'Codex' | 'Gemini' | 'OpenCode' | 'Droid';

interface CliStatus {
    installed: boolean;
    version: string | null;
    is_synced: boolean;
    has_backup: boolean;
    current_base_url: string | null;
    files: string[];
    synced_count?: number;
}

export const CliSyncCard = ({ proxyUrl, apiKey, className }: CliSyncCardProps) => {
    const { t } = useTranslation();
    const [statuses, setStatuses] = useState<Record<CliAppType, CliStatus | null>>({
        Claude: null,
        Codex: null,
        Gemini: null,
        OpenCode: null,
        Droid: null
    });
    const [loading, setLoading] = useState<Record<CliAppType, boolean>>({
        Claude: false,
        Codex: false,
        Gemini: false,
        OpenCode: false,
        Droid: false
    });
    const [syncing, setSyncing] = useState<Record<CliAppType, boolean>>({
        Claude: false,
        Codex: false,
        Gemini: false,
        OpenCode: false,
        Droid: false
    });
    const [syncAccounts, setSyncAccounts] = useState(false);
    const [droidSyncModal, setDroidSyncModal] = useState(false);
    const [selectedModels, setSelectedModels] = useState<Record<CliAppType, string>>({
        Claude: 'claude-3-5-sonnet-latest',
        Codex: 'gpt-4o',
        Gemini: 'gemini-1.5-pro',
        OpenCode: '',
        Droid: ''
    });
    const [viewingConfig, setViewingConfig] = useState<{
        app: CliAppType,
        content: string,
        fileName: string,
        allFiles: string[]
    } | null>(null);
    const [restoreConfirmApp, setRestoreConfirmApp] = useState<CliAppType | null>(null);
    const [syncConfirmApp, setSyncConfirmApp] = useState<CliAppType | null>(null);
    const [openCodeSyncModal, setOpenCodeSyncModal] = useState(false);
    const [clearConfirmApp, setClearConfirmApp] = useState<CliAppType | null>(null);

    const { models: proxyModels } = useProxyModels();

    const modelOptions = proxyModels.map(m => ({
        value: m.id,
        label: m.name,
        group: m.group || 'General'
    }));

    // 根据不同的 CLI 应用格式化 Proxy URL
    const getFormattedProxyUrl = useCallback((app: CliAppType) => {
        if (!proxyUrl) return '';
        const base = proxyUrl.trimEnd().replace(/\/+$/, '');
        // Codex & OpenCode (OpenAI 协议) 通常需要带 /v1
        if (app === 'Codex' || app === 'OpenCode') {
            return base.endsWith('/v1') ? base : `${base}/v1`;
        }
        // Claude 和 Gemini 的 SDK 通常会自动处理版本路径或不需要 /v1
        return base.replace(/\/v1$/, '');
    }, [proxyUrl]);

    const checkStatus = useCallback(async (app: CliAppType) => {
        setLoading(prev => ({ ...prev, [app]: true }));
        try {
            const formattedUrl = getFormattedProxyUrl(app);
            let command: string;
            let params: Record<string, unknown>;
            if (app === 'Droid') {
                command = 'get_droid_sync_status';
                params = { proxyUrl: formattedUrl };
            } else if (app === 'OpenCode') {
                command = 'get_opencode_sync_status';
                params = { proxyUrl: formattedUrl };
            } else {
                command = 'get_cli_sync_status';
                params = { appType: app, proxyUrl: formattedUrl };
            }

            const status = await invoke<CliStatus>(command, params);
            setStatuses(prev => ({ ...prev, [app]: status }));
        } catch (error) {
            console.error(`Failed to check ${app} status:`, error);
        } finally {
            setLoading(prev => ({ ...prev, [app]: false }));
        }
    }, [getFormattedProxyUrl]);

    const handleSync = async (app: CliAppType) => {
        if (app === 'Droid') {
            setDroidSyncModal(true);
            return;
        }
        if (app === 'OpenCode') {
            setOpenCodeSyncModal(true);
            return;
        }
        setSyncConfirmApp(app);
    };

    const executeSync = async () => {
        const app = syncConfirmApp;
        if (!app) return;
        setSyncConfirmApp(null);

        if (!proxyUrl || !apiKey) {
            showToast(t('proxy.cli_sync.toast.config_missing', { defaultValue: '请先生成 API Key 并启动服务' }), 'error');
            return;
        }

        try {
            const formattedUrl = getFormattedProxyUrl(app);
            const command = app === 'OpenCode' ? 'execute_opencode_sync' : 'execute_cli_sync';
            const params = app === 'OpenCode'
                ? { proxyUrl: formattedUrl, apiKey: apiKey, syncAccounts: syncAccounts }
                : { appType: app, proxyUrl: formattedUrl, apiKey: apiKey, model: selectedModels[app] };

            await invoke(command, params);
            showToast(t(app === 'OpenCode' ? 'proxy.opencode_sync.toast.sync_success' : 'proxy.cli_sync.toast.sync_success', { name: app, defaultValue: `${app} synced successfully` }), 'success');
            await checkStatus(app);
        } catch (error: any) {
            showToast(t(app === 'OpenCode' ? 'proxy.opencode_sync.toast.sync_error' : 'proxy.cli_sync.toast.sync_error', { name: app, error: error.toString(), defaultValue: `Sync failed: ${error.toString()}` }), 'error');
        } finally {
            setSyncing(prev => ({ ...prev, [app]: false }));
        }
    };

    const handleRestore = (app: CliAppType) => {
        setRestoreConfirmApp(app);
    };

    const executeRestore = async () => {
        if (!restoreConfirmApp) return;
        const app = restoreConfirmApp;
        setRestoreConfirmApp(null);

        setSyncing(prev => ({ ...prev, [app]: true }));
        try {
            const command = app === 'Droid' ? 'execute_droid_restore' : app === 'OpenCode' ? 'execute_opencode_restore' : 'execute_cli_restore';
            const params = (app === 'Droid' || app === 'OpenCode') ? {} : { appType: app };
            await invoke(command, params);
            showToast(t('common.success'), 'success');
            await checkStatus(app);
        } catch (error: any) {
            showToast(error.toString(), 'error');
        } finally {
            setSyncing(prev => ({ ...prev, [app]: false }));
        }
    };

    const handleClear = (app: CliAppType) => {
        setClearConfirmApp(app);
    };

    const executeClear = async () => {
        if (!clearConfirmApp) return;
        const app = clearConfirmApp;
        setClearConfirmApp(null);

        setSyncing(prev => ({ ...prev, [app]: true }));
        try {
            const formattedUrl = getFormattedProxyUrl(app);
            await invoke('execute_opencode_clear', { proxyUrl: formattedUrl, clearLegacy: true });
            showToast(t('proxy.opencode_sync.toast.clear_success', { defaultValue: 'OpenCode cleared successfully' }), 'success');
            await checkStatus(app);
        } catch (error: any) {
            showToast(t('proxy.opencode_sync.toast.clear_error', { defaultValue: `Clear failed: ${error.toString()}` }), 'error');
        } finally {
            setSyncing(prev => ({ ...prev, [app]: false }));
        }
    };

    const handleViewConfig = async (app: CliAppType, fileName?: string) => {
        try {
            const status = statuses[app];
            if (!status) return;

            const targetFile = fileName || status.files[0];
            let command: string;
            let params: Record<string, unknown>;
            if (app === 'Droid') {
                command = 'get_droid_config_content';
                params = {};
            } else if (app === 'OpenCode') {
                command = 'get_opencode_config_content';
                params = { request: { fileName: targetFile } };
            } else {
                command = 'get_cli_config_content';
                params = { appType: app, fileName: targetFile };
            }

            const content = await invoke<string>(command, params);
            setViewingConfig({
                app,
                content,
                fileName: targetFile,
                allFiles: status.files
            });
        } catch (error: any) {
            showToast(error.toString(), 'error');
        }
    };

    useEffect(() => {
        checkStatus('Claude');
        checkStatus('Codex');
        checkStatus('Gemini');
        checkStatus('OpenCode');
        checkStatus('Droid');
    }, [checkStatus]);

    const renderCliItem = (app: CliAppType, icon: React.ReactNode, name: string) => {
        const status = statuses[app];
        const isAppLoading = loading[app];
        const isAppSyncing = syncing[app];

        return (
            <div className="flex flex-col bg-white/50 dark:bg-gray-800/40 rounded-xl border border-gray-100 dark:border-white/5 p-4 shadow-sm hover:shadow-lg hover:border-blue-200/50 dark:hover:border-blue-500/30 transition-all duration-300 group">
                <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-y-3 gap-x-2 mb-4">
                    <div className="flex items-center gap-3 min-w-0">
                        <div className="p-2.5 bg-gray-50 dark:bg-base-300 rounded-lg shrink-0 group-hover:scale-110 transition-transform duration-300">
                            {icon}
                        </div>
                        <div className="min-w-0">
                            <h4 className="text-sm font-bold text-gray-900 dark:text-gray-100 leading-tight truncate">
                                {t('proxy.cli_sync.card_title', { name })}
                            </h4>
                            <div className="mt-1 flex items-center gap-1.5 overflow-hidden">
                                {isAppLoading ? (
                                    <div className="flex items-center gap-1 text-[10px] text-gray-400">
                                        <Loader2 size={10} className="animate-spin" />
                                        {t('proxy.cli_sync.status.detecting')}
                                    </div>
                                ) : status?.installed ? (
                                    <span className="text-[10px] px-1.5 py-0.5 rounded-full bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 font-bold whitespace-nowrap">
                                        {t('proxy.cli_sync.status.installed', { version: status.version })}
                                    </span>
                                ) : (
                                    <span className="text-[10px] px-1.5 py-0.5 rounded-full bg-gray-100 dark:bg-gray-800 text-gray-400 font-medium whitespace-nowrap">
                                        {t('proxy.cli_sync.status.not_installed')}
                                    </span>
                                )}
                            </div>
                        </div>
                    </div>

                    {/* Show Sync Status if installed OR if it's OpenCode (which we now allow configuring even if not installed) */}
                    {!isAppLoading && (status?.installed || app === 'OpenCode' && status?.current_base_url) && (
                        <div className={cn(
                            "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-[10px] font-bold tracking-wide transition-all h-6 shrink-0 whitespace-nowrap shadow-sm",
                            status.is_synced
                                ? "bg-gradient-to-r from-green-500 to-emerald-600 text-white"
                                : "bg-amber-100 dark:bg-amber-900/30 text-amber-600 dark:text-amber-500 border border-amber-200/50 dark:border-amber-800/30"
                        )}>
                            {status.is_synced ? (
                                <><CheckCircle2 size={12} className="shrink-0" /> {t('proxy.cli_sync.status.synced', { defaultValue: '已同步' })}</>
                            ) : (
                                <><AlertCircle size={12} className="shrink-0" /> {t('proxy.cli_sync.status.not_synced', { defaultValue: '未同步' })}</>
                            )}
                        </div>
                    )}
                </div>

                <div className="mt-auto space-y-3">
                    <div className="p-2.5 bg-gray-50/80 dark:bg-gray-900/40 rounded-lg border border-dashed border-gray-200 dark:border-white/10">
                        <div className="flex justify-between items-start mb-1">
                            <div className="text-[9px] text-gray-400 dark:text-gray-500 uppercase font-bold tracking-wider">{t('proxy.cli_sync.status.current_base_url')}</div>
                        </div>
                        <div className="text-[10px] font-mono truncate text-gray-500 dark:text-gray-400 italic">
                            {status?.current_base_url || '---'}
                        </div>
                    </div>

                    {/* Claude, Codex, Gemini 的模型选择 */}
                    {(status?.installed || app === 'OpenCode') && (app === 'Claude' || app === 'Codex' || app === 'Gemini') && (
                        <div className="space-y-1">
                            <div className="text-[9px] text-gray-400 dark:text-gray-500 uppercase font-bold tracking-wider px-1">
                                {t('proxy.cli_sync.model_select', { defaultValue: 'Select Model' })}
                            </div>
                            <GroupedSelect
                                value={selectedModels[app]}
                                onChange={(val) => setSelectedModels(prev => ({ ...prev, [app]: val }))}
                                options={modelOptions}
                                className="w-full !h-8 !text-[11px] !rounded-lg"
                                allowCustomInput={true}
                            />
                        </div>
                    )}

                    {/* OpenCode 独有的账号同步选项 - Allow even if not installed */}
                    {app === 'OpenCode' && (
                        <div className="flex items-center gap-2 p-2 bg-gray-50/50 dark:bg-gray-900/20 rounded-lg">
                            <input
                                type="checkbox"
                                id="opencode-sync-accounts"
                                checked={syncAccounts}
                                onChange={(e) => setSyncAccounts(e.target.checked)}
                                className="checkbox checkbox-xs checkbox-primary"
                            />
                            <label htmlFor="opencode-sync-accounts" className="text-[10px] text-gray-600 dark:text-gray-400 cursor-pointer select-none">
                                {t('proxy.opencode_sync.sync_accounts', { defaultValue: 'Sync accounts to antigravity-accounts.json' })}
                            </label>
                        </div>
                    )}

                    <div className="flex items-center gap-2">
                        {(status?.installed || app === 'OpenCode') && (
                            <>
                                {/* 对于 OpenCode，如果未同步，则不显示查看按钮（因为文件尚未生成，后端会报错） */}
                                {(app !== 'OpenCode' || status?.is_synced) && (
                                    <button
                                        onClick={() => handleViewConfig(app)}
                                        className="p-1 text-gray-400 hover:text-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded transition-colors"
                                        title={t(app === 'OpenCode' ? 'proxy.opencode_sync.btn_view' : 'proxy.cli_sync.btn_view', { defaultValue: 'View Config' })}
                                    >
                                        <Eye size={14} />
                                    </button>
                                )}
                                <button
                                    onClick={() => handleRestore(app)}
                                    className="p-1 text-gray-400 hover:text-orange-500 hover:bg-orange-50 dark:hover:bg-orange-900/20 rounded transition-colors"
                                    title={t(app === 'OpenCode' ? 'proxy.opencode_sync.btn_restore' : 'proxy.cli_sync.btn_restore', { defaultValue: 'Restore' })}
                                >
                                    <RotateCcw size={14} />
                                </button>
                                {/* OpenCode 独有的 Clear 按钮 */}
                                {app === 'OpenCode' && (
                                    <button
                                        onClick={() => handleClear(app)}
                                        className="p-1 text-gray-400 hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors"
                                        title={t('proxy.opencode_sync.btn_clear', { defaultValue: 'Clear' })}
                                    >
                                        <Trash2 size={14} />
                                    </button>
                                )}
                            </>
                        )}
                        <button
                            onClick={() => handleSync(app)}
                            disabled={(app !== 'OpenCode' && !status?.installed) || isAppSyncing || isAppLoading}
                            className={cn(
                                "btn btn-sm flex-1 gap-2 rounded-xl transition-all font-bold shadow-sm",
                                status?.is_synced
                                    ? "btn-ghost border-gray-200 dark:border-base-400 text-gray-500 hover:bg-gray-100"
                                    : "btn-primary hover:shadow-lg shadow-blue-500/20"
                            )}
                        >
                            {isAppSyncing ? (
                                <Loader2 size={14} className="animate-spin" />
                            ) : (
                                <RefreshCw size={14} className={cn(isAppLoading && "animate-spin-once")} />
                            )}
                            {t('proxy.cli_sync.btn_sync')}
                        </button>
                    </div>
                </div>
            </div>
        );
    };

    return (
        <div className={cn("space-y-4", className)}>
            <div className="px-1 flex items-center justify-between">
                <div className="flex items-center gap-2 text-gray-400">
                    <Terminal size={14} />
                    <span className="text-[10px] font-bold uppercase tracking-widest">
                        {t('proxy.cli_sync.title')}
                    </span>
                </div>
                <p className="text-[10px] text-gray-400 dark:text-gray-500 italic">
                    {t('proxy.cli_sync.subtitle')}
                </p>
            </div>

            <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
                {renderCliItem('Claude', <CodeXml size={20} className="text-purple-500" />, 'Claude Code')}
                {renderCliItem('Codex', <Cpu size={20} className="text-blue-500" />, 'Codex AI')}
                {renderCliItem('Gemini', <Globe size={20} className="text-green-500" />, 'Gemini CLI')}
                {renderCliItem('OpenCode', <CodeXml size={20} className="text-blue-500" />, 'OpenCode')}
                {renderCliItem('Droid', <Bot size={20} className="text-orange-500" />, 'Droid')}
            </div>

            {/* Config Viewer Modal */}
            {viewingConfig && (
                <div className="fixed inset-0 z-[300] flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-in fade-in duration-200">
                    <div className="bg-white dark:bg-base-100 rounded-2xl shadow-2xl border border-gray-200 dark:border-base-300 w-full max-w-2xl overflow-hidden animate-in zoom-in-95 duration-200">
                        <div className="px-6 py-4 border-b border-gray-100 dark:border-base-200 flex items-center justify-between bg-gray-50/50 dark:bg-base-200/50">
                            <div>
                                <h3 className="font-bold text-gray-900 dark:text-base-content flex items-center gap-2">
                                    <CodeXml size={18} className="text-blue-500" />
                                    {t('proxy.cli_sync.modal.view_title', { name: viewingConfig.app })}
                                </h3>
                                <div className="mt-2 flex gap-2">
                                    {viewingConfig.allFiles.map(file => (
                                        <button
                                            key={file}
                                            onClick={() => handleViewConfig(viewingConfig.app, file)}
                                            className={cn(
                                                "px-3 py-1 text-[10px] font-bold rounded-lg transition-all border",
                                                viewingConfig.fileName === file
                                                    ? "bg-blue-500 text-white border-blue-500"
                                                    : "bg-white dark:bg-base-300 text-gray-400 border-gray-100 dark:border-base-400 hover:border-blue-200"
                                            )}
                                        >
                                            {file}
                                        </button>
                                    ))}
                                </div>
                            </div>
                            <div className="flex items-center gap-2">
                                <button
                                    onClick={async () => {
                                        const success = await copyToClipboard(viewingConfig.content);
                                        if (success) {
                                            showToast(t('proxy.cli_sync.modal.copy_success'), 'success');
                                        }
                                    }}
                                    className="btn btn-ghost btn-sm hover:bg-blue-50 hover:text-blue-600 dark:hover:bg-blue-900/20"
                                >
                                    <Copy size={16} />
                                </button>
                                <button
                                    onClick={() => setViewingConfig(null)}
                                    className="btn btn-ghost btn-sm hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20"
                                >
                                    <X size={18} />
                                </button>
                            </div>
                        </div>
                        <div className="p-6">
                            <div className="bg-gray-900 rounded-xl p-4 overflow-auto max-h-[50vh] border border-gray-800 shadow-inner">
                                <pre className="text-xs font-mono text-gray-300 leading-relaxed">
                                    {viewingConfig.content}
                                </pre>
                            </div>
                        </div>
                    </div>
                </div>
            )}
            {/* 恢复默认/备份确认弹窗 */}
            <ModalDialog
                isOpen={!!restoreConfirmApp}
                title={statuses[restoreConfirmApp!]?.has_backup
                    ? t('proxy.cli_sync.btn_restore_backup')
                    : t('proxy.cli_sync.btn_restore') || t('proxy.cli_sync.title')}
                message={restoreConfirmApp
                    ? (statuses[restoreConfirmApp!]?.has_backup
                        ? t('proxy.cli_sync.restore_backup_confirm')
                        : t('proxy.cli_sync.restore_confirm', { name: restoreConfirmApp }))
                    : ''}
                onConfirm={executeRestore}
                onCancel={() => setRestoreConfirmApp(null)}
                isDestructive={true}
            />

            {/* 同步配置确认弹窗 (Issue #756) */}
            <ModalDialog
                isOpen={!!syncConfirmApp}
                title={t('proxy.cli_sync.sync_confirm_title')}
                message={syncConfirmApp ? t('proxy.cli_sync.sync_confirm_message', { name: syncConfirmApp }) : ''}
                onConfirm={executeSync}
                onCancel={() => setSyncConfirmApp(null)}
                isDestructive={true}
            />

            {/* Clear 确认弹窗 - 仅 OpenCode */}
            <ModalDialog
                isOpen={!!clearConfirmApp}
                title={t('proxy.opencode_sync.clear_confirm_title', { defaultValue: 'Clear OpenCode Configuration' })}
                message={t('proxy.opencode_sync.clear_confirm_message', { defaultValue: 'This will clear all OpenCode configurations including legacy settings. Are you sure?' })}
                onConfirm={executeClear}
                onCancel={() => setClearConfirmApp(null)}
                isDestructive={true}
            />

            {/* Droid 模型添加弹窗 */}
            {droidSyncModal && (
                <DroidSyncModal
                    proxyUrl={proxyUrl}
                    apiKey={apiKey}
                    getFormattedProxyUrl={getFormattedProxyUrl}
                    onClose={() => setDroidSyncModal(false)}
                    onSyncDone={() => checkStatus('Droid')}
                />
            )}

            {/* OpenCode 模型选择弹窗 */}
            {openCodeSyncModal && (
                <OpenCodeSyncModal
                    proxyUrl={proxyUrl}
                    apiKey={apiKey}
                    getFormattedProxyUrl={getFormattedProxyUrl}
                    onClose={() => setOpenCodeSyncModal(false)}
                    onSyncDone={() => checkStatus('OpenCode')}
                />
            )}
        </div>
    );
};


export default CliSyncCard;
