import * as vscode from 'vscode';
import { ApiClient } from './apiClient';
import { checkCppServiceConnection, sendFileToCppService } from './localClient';

export interface FileEntry {
    key: string; // 文件路径
    name: string; // 显示名称
    isFile: boolean;
    content?: string; // 文件内容
    lastLoaded?: Date; // 最后加载时间
}

export class FileModel {
    private fileList = new Map<string, FileEntry>();
    private apiClient: ApiClient;
    private config: vscode.WorkspaceConfiguration;
    private isConnected = false;

    constructor() {
        this.apiClient = new ApiClient();
        this.config = vscode.workspace.getConfiguration('squirrel');
    }

    // 更新配置
    updateConfig() {
        this.config = vscode.workspace.getConfiguration('squirrel');
        const baseUrl = this.config.get<string>('api.baseUrl', 'http://localhost');
        const port = this.config.get<number>('api.port', 8080);
        this.apiClient.updateConfig(baseUrl, port);
    }

    // 连接到API
    async connect(): Promise<boolean> {
        try {
            this.updateConfig();
            const baseUrl = this.config.get<string>('api.baseUrl', 'http://localhost');
            const port = this.config.get<number>('api.port', 8080);
            const defaultDir = this.config.get<string>('defaultDirectory', 'sqr');

            console.log(`尝试连接到: ${baseUrl}:${port}, 目录: ${defaultDir}`);

            // 首先检查版本号
            console.log('正在检查 pvfUtility 版本号...');
            const version = await this.apiClient.getVersion();
            console.log(`pvfUtility 版本: ${version}`);

            // 测试连接并获取文件列表
            const filesData = await this.apiClient.getFileList(defaultDir);
            console.log(`API返回数据: ${JSON.stringify(filesData)}`);

            // 将字符串按换行符分割成数组
            const files = filesData.split(/\r?\n/).filter((file: string) => file.trim() !== '');
            console.log(`成功获取到 ${files.length} 个文件`);

            this.fileList.clear();

            files.forEach((filePath: string) => {
                const entry: FileEntry = {
                    key: filePath,
                    name: filePath.split('/').pop() || filePath,
                    isFile: true
                };
                this.fileList.set(filePath, entry);
            });

            // 自动加载所有文件内容
            console.log('开始自动加载所有文件内容...');
            await this.loadAllFileContents();

            this.isConnected = true;
            return true;
        } catch (error) {
            console.error('连接失败详细信息:', error);
            this.isConnected = false;
            return false;
        }
    }

    // 是否已连接
    getIsConnected(): boolean {
        return this.isConnected;
    }

    // 获取指定目录的子文件（支持树形结构）
    getChildren(parentKey?: string): FileEntry[] {
        if (!parentKey) {
            // 获取根目录内容
            const folders = new Map<string, string>(); // folderKey -> name
            const files: FileEntry[] = [];

            for (const key of this.fileList.keys()) {
                const idx = key.indexOf('/');
                if (idx === -1) {
                    // 根目录文件
                    const entry = this.fileList.get(key);
                    if (entry) files.push(entry);
                } else {
                    // 根目录文件夹
                    const folder = key.substring(0, idx);
                    if (!folders.has(folder)) folders.set(folder, folder);
                }
            }

            const dirs: FileEntry[] = [...folders.keys()].map(k => ({
                key: k,
                name: k,
                isFile: false
            }));

            return [...files, ...dirs].sort((a, b) =>
                (a.isFile === b.isFile) ?
                a.name.localeCompare(b.name, 'en', { sensitivity: 'base' }) :
                (a.isFile ? 1 : -1)
            );
        }

        // 获取子目录内容
        const prefix = parentKey.endsWith('/') ? parentKey : parentKey + '/';
        const seenFolders = new Set<string>();
        const result: FileEntry[] = [];

        for (const key of this.fileList.keys()) {
            if (!key.startsWith(prefix)) continue;
            const rest = key.substring(prefix.length);
            const slash = rest.indexOf('/');

            if (slash === -1) {
                // 直接子文件
                const entry = this.fileList.get(key);
                if (entry) result.push(entry);
            } else {
                // 子文件夹
                const childFolder = rest.substring(0, slash);
                const childKey = prefix + childFolder;
                if (!seenFolders.has(childKey)) {
                    seenFolders.add(childKey);
                    result.push({
                        key: childKey,
                        name: childFolder,
                        isFile: false
                    });
                }
            }
        }

        result.sort((a, b) =>
            (a.isFile === b.isFile) ?
            a.name.localeCompare(b.name, 'en', { sensitivity: 'base' }) :
            (a.isFile ? 1 : -1)
        );

        return result;
    }

    // 获取文件内容
    async getFileContent(filePath: string): Promise<string | undefined> {
        const entry = this.fileList.get(filePath);
        if (!entry) {
            return undefined;
        }

        // 如果已经加载过内容，直接返回
        if (entry.content) {
            return entry.content;
        }

        try {
            // 获取编码设置
            const encodingType = this.config.get<string>('nutEncoding', 'UTF8');
            const contents = await this.apiClient.getFileContents([filePath], encodingType);
            const content = contents[filePath];

            if (content !== undefined) {
                entry.content = content;
                entry.lastLoaded = new Date();
                return content;
            }
        } catch (error) {
            vscode.window.showErrorMessage(`获取文件内容失败: ${error}`);
        }

        return undefined;
    }

    // 保存文件内容
    async saveFileContent(filePath: string, content: string): Promise<boolean> {
        // 先检查C++服务是否可连接
        const isCppServiceConnected = await checkCppServiceConnection();

        if (isCppServiceConnected) {
            // C++服务可连接，先发送进行编译验证
            try {
                const sendSuccess = await sendFileToCppService(filePath, content);
                if (sendSuccess) {
                    // C++编译服务返回200，说明脚本编译通过，允许上传
                    const success = await this.apiClient.uploadFileContent(filePath, content);
                    if (success) {
                        const entry = this.fileList.get(filePath);
                        if (entry) {
                            entry.content = content;
                            entry.lastLoaded = new Date();
                        }
                        return true;
                    }
                } else {
                    // C++编译服务返回非200，说明脚本存在问题，不允许上传
                    vscode.window.showErrorMessage(`脚本编译失败，无法保存文件 ${filePath}。请检查代码错误后再试。`);
                    return false;
                }
            } catch (error) {
                // 向C++服务发送文件过程中出现错误
                vscode.window.showErrorMessage(`发送文件到编译服务时出错: ${error}，但仍尝试直接保存文件`);
                const success = await this.apiClient.uploadFileContent(filePath, content);
                if (success) {
                    const entry = this.fileList.get(filePath);
                    if (entry) {
                        entry.content = content;
                        entry.lastLoaded = new Date();
                    }
                    return true;
                }
            }
        } else {
            // C++服务不可连接，直接执行上传
            try {
                const success = await this.apiClient.uploadFileContent(filePath, content);
                if (success) {
                    const entry = this.fileList.get(filePath);
                    if (entry) {
                        entry.content = content;
                        entry.lastLoaded = new Date();
                    }
                    return true;
                }
            } catch (error) {
                vscode.window.showErrorMessage(`保存文件失败: ${error}`);
            }
        }

        return false;
    }

    // 刷新文件列表
    async refresh(): Promise<boolean> {
        if (!this.isConnected) {
            return false;
        }

        try {
            this.updateConfig();
            const defaultDir = this.config.get<string>('defaultDirectory', 'sqr');
            const filesData = await this.apiClient.getFileList(defaultDir);

            // 将字符串按换行符分割成数组
            const files = filesData.split(/\r?\n/).filter((file: string) => file.trim() !== '');

            this.fileList.clear();
            files.forEach((filePath: string) => {
                const entry: FileEntry = {
                    key: filePath,
                    name: filePath.split('/').pop() || filePath,
                    isFile: true
                };
                this.fileList.set(filePath, entry);
            });

            return true;
        } catch (error) {
            vscode.window.showErrorMessage(`刷新文件列表失败: ${error}`);
            return false;
        }
    }

    // 批量加载所有文件内容
    async loadAllFileContents(): Promise<void> {
        try {
            // 获取所有文件路径
            const filePaths = Array.from(this.fileList.keys());

            if (filePaths.length === 0) {
                console.log('没有文件需要加载');
                return;
            }

            console.log(`准备加载 ${filePaths.length} 个文件的内容`);

            // 获取编码设置
            const encodingType = this.config.get<string>('nutEncoding', 'UTF8');

            // 分批获取文件内容，避免一次性请求过多文件
            const batchSize = 50; // 每批处理50个文件
            for (let i = 0; i < filePaths.length; i += batchSize) {
                const batch = filePaths.slice(i, i + batchSize);
                console.log(`正在加载批次 ${Math.floor(i/batchSize) + 1}/${Math.ceil(filePaths.length/batchSize)}: ${batch.length} 个文件`);

                try {
                    const contents = await this.apiClient.getFileContents(batch, encodingType);

                    // 更新文件内容
                    for (const [filePath, content] of Object.entries(contents)) {
                        const entry = this.fileList.get(filePath);
                        if (entry) {
                            entry.content = content;
                            entry.lastLoaded = new Date();
                        }
                    }

                    console.log(`批次 ${Math.floor(i/batchSize) + 1} 加载完成`);
                } catch (batchError) {
                    console.error(`加载批次 ${Math.floor(i/batchSize) + 1} 失败:`, batchError);
                    // 继续处理下一个批次，不中断整个过程
                }
            }

            console.log('所有文件内容加载完成');
        } catch (error) {
            console.error('批量加载文件内容失败:', error);
            vscode.window.showErrorMessage(`批量加载文件内容失败: ${error}`);
        }
    }

    // 获取文件条目
    getFileEntry(filePath: string): FileEntry | undefined {
        return this.fileList.get(filePath);
    }

    // 获取所有nut文件路径
    getAllNutFiles(): string[] {
        return Array.from(this.fileList.keys())
            .filter(filePath => filePath.endsWith('.nut'));
    }
}