<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, computed } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { MessagePlugin } from 'tdesign-vue-next';
import { repoApi, type Account } from '../services/repoApi';
import { useAccountStore } from '../stores/accountStorage';
import MonacoEditor from '../components/MonacoEditor.vue';
import RepoHeader from '../components/RepoHeader.vue';

const route = useRoute();
const router = useRouter();

const contentText = ref<string>('');
const loading = ref(false);
const showDiff = ref(false);
const originalText = ref('');
const fileSha = ref('');
const selectedAccount = ref<number | ''>('');
const currentPath = ref('');
const newFileName = ref('');
const store = useAccountStore();
const isNewFile = ref(false);

// Compute full path by combining directory path with new file name
const fullPath = computed(() => {
    if (!isNewFile.value) return currentPath.value;
    const basePath = route.query.path as string || '';
    return basePath ? `${basePath}/${newFileName.value}` : newFileName.value;
});

// 提交对话框状态
const showCommitDialog = ref(false);
const commitMessage = ref('');

const decodeContent = (base64Content: string, contentType: 'text' | 'binary' = 'text'): string | Uint8Array => {
    // 步骤1: 使用atob解码Base64字符串，获取原始二进制数据
    const binaryContent = atob(base64Content);

    if (contentType === 'binary') {
        // 对于二进制文件，返回Uint8Array
        const bytes = new Uint8Array(binaryContent.length);
        for (let i = 0; i < binaryContent.length; i++) {
            bytes[i] = binaryContent.charCodeAt(i);
        }
        return bytes;
    } else {
        // 对于文本内容，处理UTF-8编码
        try {
            // 方法1: 使用TextDecoder (推荐，更可靠)
            const bytes = new Uint8Array(binaryContent.length);
            for (let i = 0; i < binaryContent.length; i++) {
                bytes[i] = binaryContent.charCodeAt(i);
            }
            return new TextDecoder('utf-8').decode(bytes);
        } catch (e) {
            // 方法2: 兼容性方案
            return decodeURIComponent(escape(binaryContent));
        }
    }
};

const fetchContent = async () => {
    const account = store.accounts.find(acc => acc.id === selectedAccount.value);
    if (!account) {
        MessagePlugin.error(`未找到账户信息${selectedAccount.value}`);
        return;
    }
    try {
        loading.value = true;
        contentText.value = "";
        originalText.value = "";
        const result = await repoApi.getFileContent(account, currentPath.value);
        if (result.content) {
            // 不移除换行符，保持原始格式
            contentText.value = result.encoding && result.encoding == "base64" ? decodeContent(result.content) as string : result.content;
            originalText.value = contentText.value;
            fileSha.value = result.sha;
        }
    } catch (error) {
        MessagePlugin.error('获取文件内容失败');
    } finally {
        loading.value = false;
    }
};

const handleSave = () => {


    // For new files, we need a file name
    if (isNewFile.value && !newFileName.value) {
        MessagePlugin.error('请输入文件名');
        return;
    }

    if (contentText.value === '') {
        MessagePlugin.error('内容不能为空');
        return;
    }

    // For existing files, check if content was modified
    if (fileSha.value && originalText.value === contentText.value) {
        MessagePlugin.success('内容未修改');
        return;
    }

    showCommitDialog.value = true;
};

const handleConfirmSave = async () => {


    // Use the full path for new files, or the route path for existing files
    const path = isNewFile.value ? fullPath.value : (route.query.path as string);
    if (!path) {
        MessagePlugin.error('请输入文件名');
        return;
    }

    loading.value = true;
    try {
        const account = store.accounts.find(acc => acc.id === selectedAccount.value);

        if (!account) {
            MessagePlugin.error(`未找到账户信息${selectedAccount.value}`);
            return;
        }
 
        let response;
        if (isNewFile.value) {
            // Create new file
            response = await repoApi.createFile(
                account,
                path,
                contentText.value,
                commitMessage.value.trim() || '创建文件'
            );
        } else {
            // Update existing file
            response = await repoApi.updateFile(
                account,
                path,
                contentText.value,
                fileSha.value,
                commitMessage.value.trim() || '更新文件'
            );
        }

        // Update fileSha with the new value from response
        if (response && response.content && response.content.sha) {
            fileSha.value = response.content.sha;
        }

        MessagePlugin.success(isNewFile.value ? '创建成功' : '保存成功');
        originalText.value = contentText.value;
        showCommitDialog.value = false;
        commitMessage.value = '';

        // If this was a new file, update the URL to include the path
        if (isNewFile.value) {
            router.replace({
                path: '/content',
                query: {
                    ...route.query,
                    path,
                    newFile: undefined
                }
            });
        }
    } catch (error) {
        console.error(error);
        MessagePlugin.error('保存失败');
    } finally {
        loading.value = false;
    }
};

const handleCancelSave = () => {
    showCommitDialog.value = false;
    commitMessage.value = '';
};

// 删除对话框状态
const showDeleteDialog = ref(false);

const handleDelete = () => {


    showDeleteDialog.value = true;
};

const handleConfirmDelete = async () => {


    loading.value = true;
    try {
        const account = store.accounts.find(acc => acc.id === selectedAccount.value);

        if (!account) {
            MessagePlugin.error(`未找到账户信息${selectedAccount.value}`);
            return;
        }

        await repoApi.deleteFile(
            account,
            currentPath.value as string,
            fileSha.value,
            '删除文件'
        );
        MessagePlugin.success('删除成功');
        showDeleteDialog.value = false;
        router.back();
    } catch (error) {
        MessagePlugin.error('删除失败');
    } finally {
        loading.value = false;
    }
};

const handleCancelDelete = () => {
    showDeleteDialog.value = false;
};

// 定义按键事件处理函数
const handleKeyDown = (e: KeyboardEvent) => {
    if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 's') {
        e.preventDefault();
        handleSave();
    }
};

// 在显示差异按钮点击处理中添加
const toggleDiff = () => {
    showDiff.value = !showDiff.value;

    if (showDiff.value) {
        // 进入差异模式时，确保有原始文本作为比较
        if (originalText.value === '') {
            originalText.value = contentText.value;
        }
    }
};

// 在 AccountView.vue 中添加
watch(showDiff, (newVal) => {
    if (newVal && originalText.value === contentText.value) {
        // 如果开启差异模式但两个文本相同，可以考虑提示用户
        MessagePlugin.info('当前没有差异可以显示');
    }
}, { immediate: true });

const handlePathClick = (path: string) => {
    router.push({
        path: '/repo',
        query: {
            id: selectedAccount.value,
            path
        }
    });
};

const handleRootClick = () => {
    router.push({
        path: '/repo',
        query: {
            id: selectedAccount.value,
        }
    });
};

const handleAccountChange = (val: number) => {
    selectedAccount.value = val;
    currentPath.value = ''; // Reset path
    router.push({
        path: '/repo',
        query: {
            id: selectedAccount.value,
        }
    });
}

const getLanguageFromPath = computed(() => {
    const path = route.query.path as string;
    if (!path) return 'plaintext';

    const ext = path.split('.').pop()?.toLowerCase() || '';

    // Map file extensions to Monaco editor languages
    const languageMap: Record<string, string> = {
        'js': 'javascript',
        "mjs": 'javascript',
        'ts': 'typescript',
        'json': 'json',
        'md': 'markdown',
        'yml': 'yaml',
        'yaml': 'yaml',
        'py': 'python',
        'html': 'html',
        'css': 'css',
        'scss': 'scss',
        'less': 'less',
        'xml': 'xml',
        'sh': 'shell',
        'bash': 'shell',
        'vue': 'vue',
        'jsx': 'javascript',
        'tsx': 'typescript',
        'gitignore': 'plaintext',
        'env': 'plaintext',
        'txt': 'plaintext',
        "rs": 'rust',
        'go': 'go',
    };

    return languageMap[ext] || 'plaintext';
});

// 监听路由变化同步本地状态
watch(() => route.query, async (query) => {
    // Only respond to query changes when on the repo route
    if (route.path !== '/content') return;
    const { id, path, newFile } = query;
    isNewFile.value = !!newFile;
    if (id) {
        await store.fetchAccounts();
        const account = store.accounts.find(acc => acc.id === Number(id));
        if (account) {
            selectedAccount.value = account.id;
        }
        currentPath.value = path as string;

        if (isNewFile.value) {
            contentText.value = '';
            originalText.value = '';
            newFileName.value = ''; // Reset new file name when entering new file mode
            return;
        }
        if (path) {
            await fetchContent();
        }
    }
}, { immediate: true });

onMounted(() => {
    window.addEventListener('keydown', handleKeyDown);



});

onUnmounted(() => {
    // 注销全局按键监听
    window.removeEventListener('keydown', handleKeyDown);
});
</script>

<template>
    <div class="content-container h-full p-2 md:p-5">
        <div class="flex flex-col gap-4 h-full">
            <RepoHeader :selected-account="selectedAccount" :current-path="isNewFile ? fullPath : currentPath"
                :is-new-file="isNewFile" :accounts="store.accounts" @path-click="handlePathClick"
                @root-click="handleRootClick" @update:selected-account="handleAccountChange">
                <div class="flex items-center justify-between w-full">
                    <div>
                        <t-input v-if="isNewFile" v-model="newFileName" placeholder="请输入文件名" class="w-20" />
                    </div>
                    <div class="flex gap-2">
                        <t-button variant="outline" @click="toggleDiff">
                            {{ showDiff ? '隐藏对比' : '显示对比' }}
                        </t-button>
                        <t-button theme="primary" @click="handleSave" :loading="loading">
                            保存
                        </t-button>
                        <t-button v-if="!isNewFile" theme="danger" @click="handleDelete" :loading="loading">
                            删除
                        </t-button>
                    </div>
                </div>
            </RepoHeader>
            <t-card bordered class="h-full">
                <template #content>
                    <div class="flex flex-col h-full">
                        <div class="editor-container flex-1">
                            <MonacoEditor v-model:value="contentText"
                                :original-value="showDiff ? originalText : undefined" :language="getLanguageFromPath"
                                :options="{ tabSize: 2 }" />
                        </div>
                    </div>
                </template>
            </t-card>
        </div>

        <t-dialog v-model:visible="showCommitDialog" header="提交更改" :confirm-on-enter="true" @confirm="handleConfirmSave"
            @close="handleCancelSave">
            <template #body>
                <div class="flex flex-col gap-2">
                    <div class="mb-2">请输入提交信息：</div>
                    <t-input v-model:value="commitMessage" placeholder="描述此次更改的内容" :autofocus="true" />
                </div>
            </template>
            <template #footer>
                <t-button theme="default" @click="handleCancelSave">
                    取消
                </t-button>
                <t-button theme="primary" @click="handleConfirmSave" :loading="loading">
                    确认
                </t-button>
            </template>
        </t-dialog>

        <t-dialog v-model:visible="showDeleteDialog" header="确认删除" :confirm-on-enter="true"
            @confirm="handleConfirmDelete" @close="handleCancelDelete">
            <template #body>
                <div class="p-2">
                    确定要删除此文件吗？此操作不可恢复。
                </div>
            </template>
            <template #footer>
                <t-button theme="default" @click="handleCancelDelete">
                    取消
                </t-button>
                <t-button theme="primary" @click="handleConfirmDelete" :loading="loading">
                    确认
                </t-button>
            </template>
        </t-dialog>
    </div>
</template>

<style scoped>
.content-container {
    width: 100%;
}

:deep(.t-card__body) {
    height: 100%;
}

.editor-container {
    border: 1px solid var(--td-component-border);
}
</style>
