import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import PocketBase from 'pocketbase';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

function readEnvFile(filePath) {
    if (!fs.existsSync(filePath)) return {};

    const content = fs.readFileSync(filePath, 'utf8');
    const result = {};

    for (const rawLine of content.split(/\r?\n/)) {
        const line = rawLine.trim();
        if (!line || line.startsWith('#')) continue;
        const index = line.indexOf('=');
        if (index === -1) continue;
        const key = line.slice(0, index).trim();
        const value = line.slice(index + 1).trim();
        result[key] = value;
    }

    return result;
}

const backendEnv = readEnvFile(path.resolve(__dirname, '..', 'back-end', '.env'));
const PB_URL = (process.env.PB_URL || backendEnv.POCKETBASE_API_URL || 'http://127.0.0.1:8090').replace(/\/+$/, '');
const ADMIN_EMAIL = process.env.PB_ADMIN_EMAIL || backendEnv.PB_ADMIN_EMAIL || '';
const ADMIN_PASSWORD = process.env.PB_ADMIN_PASSWORD || backendEnv.PB_ADMIN_PASSWORD || '';
const AUTH_TOKEN = process.env.POCKETBASE_AUTH_TOKEN || backendEnv.POCKETBASE_AUTH_TOKEN || '';

const pb = new PocketBase(PB_URL);
const SOFT_DELETE_RULE = 'is_delete = 0';

const collections = [
    {
        name: 'tbl_auth_users',
        type: 'auth',
        listRule: '@request.auth.usergroups_id = "ROLE-1774666070666-9dDrTB" && is_delete = 0',
        viewRule: '@request.auth.usergroups_id = "ROLE-1774666070666-9dDrTB" && is_delete = 0',
        createRule: '',
        updateRule: '',
        deleteRule: '@request.auth.usergroups_id = "ROLE-1774666070666-9dDrTB"',
        fields: [
            { name: 'users_convers_id', type: 'text' },
            { name: 'openid', type: 'text', required: true },
            { name: 'org_id', type: 'number' },
            { name: 'users_rank_level', type: 'number' },
            { name: 'users_status', type: 'number' },
            { name: 'users_auth_type', type: 'number' },

            { name: 'users_id', type: 'text' },
            { name: 'users_name', type: 'text' },
            { name: 'users_idtype', type: 'text' },
            { name: 'users_id_number', type: 'text' },
            { name: 'users_phone', type: 'text' },
            { name: 'users_level', type: 'text' },
            { name: 'users_type', type: 'text' },
            { name: 'users_tag', type: 'text' },
            { name: 'users_status', type: 'text' },
            { name: 'company_id', type: 'text' },
            { name: 'users_parent_id', type: 'text' },
            { name: 'users_promo_code', type: 'text' },
            { name: 'users_id_pic_a', type: 'text' },
            { name: 'users_id_pic_b', type: 'text' },
            { name: 'users_title_picture', type: 'text' },
            { name: 'users_picture', type: 'text' },
            { name: 'is_delete', type: 'number', default: 0, min: 0, max: 1, onlyInt: true },
            { name: 'usergroups_id', type: 'text' }
        ],
        indexes: [
            'CREATE UNIQUE INDEX idx_tbl_auth_users_users_convers_id ON tbl_auth_users (users_convers_id)',
            'CREATE UNIQUE INDEX idx_tbl_auth_users_openid ON tbl_auth_users (openid)',
            'CREATE INDEX idx_tbl_auth_users_org_id ON tbl_auth_users (org_id)',
            'CREATE INDEX idx_tbl_auth_users_users_rank_level ON tbl_auth_users (users_rank_level)',
            'CREATE INDEX idx_tbl_auth_users_users_status ON tbl_auth_users (users_status)',
            'CREATE INDEX idx_tbl_auth_users_users_auth_type ON tbl_auth_users (users_auth_type)',

            // Allow unbound users with empty phone while still speeding up phone lookups.
            'CREATE INDEX idx_tbl_auth_users_users_phone ON tbl_auth_users (users_phone)',
            'CREATE INDEX idx_tbl_auth_users_company_id ON tbl_auth_users (company_id)',
            'CREATE INDEX idx_tbl_auth_users_usergroups_id ON tbl_auth_users (usergroups_id)',
            'CREATE INDEX idx_tbl_auth_users_users_parent_id ON tbl_auth_users (users_parent_id)'
        ]
    },
    {
        name: 'tbl_auth_resources',
        type: 'base',
        listRule: SOFT_DELETE_RULE,
        viewRule: SOFT_DELETE_RULE,
        fields: [
            { name: 'res_id', type: 'text', required: true },
            { name: 'table_name', type: 'text', required: true },
            { name: 'column_name', type: 'text' },
            { name: 'res_type', type: 'text', required: true },
            { name: 'is_delete', type: 'number', default: 0, min: 0, max: 1, onlyInt: true }
        ],
        indexes: [
            'CREATE UNIQUE INDEX idx_tbl_auth_resources_res_id ON tbl_auth_resources (res_id)',
            'CREATE INDEX idx_tbl_auth_resources_table_name ON tbl_auth_resources (table_name)',
            'CREATE INDEX idx_tbl_auth_resources_res_type ON tbl_auth_resources (res_type)',
            'CREATE UNIQUE INDEX idx_tbl_auth_resources_unique_res ON tbl_auth_resources (table_name, column_name, res_type)'
        ]
    },
    {
        name: 'tbl_auth_roles',
        type: 'base',
        listRule: SOFT_DELETE_RULE,
        viewRule: SOFT_DELETE_RULE,
        fields: [
            { name: 'role_id', type: 'text', required: true },
            { name: 'role_name', type: 'text', required: true },
            { name: 'role_code', type: 'text' },
            { name: 'role_status', type: 'number' },
            { name: 'role_remark', type: 'text' },
            { name: 'is_delete', type: 'number', default: 0, min: 0, max: 1, onlyInt: true }
        ],
        indexes: [
            'CREATE UNIQUE INDEX idx_tbl_auth_roles_role_id ON tbl_auth_roles (role_id)',
            'CREATE UNIQUE INDEX idx_tbl_auth_roles_role_name ON tbl_auth_roles (role_name)',
            'CREATE UNIQUE INDEX idx_tbl_auth_roles_role_code ON tbl_auth_roles (role_code)'
        ]
    },
    {
        name: 'tbl_auth_role_perms',
        type: 'base',
        listRule: SOFT_DELETE_RULE,
        viewRule: SOFT_DELETE_RULE,
        fields: [
            { name: 'role_perm_id', type: 'text', required: true },
            { name: 'role_id', type: 'text', required: true },
            { name: 'res_id', type: 'text', required: true },
            { name: 'access_level', type: 'number', required: true },
            { name: 'priority', type: 'number' },
            { name: 'is_delete', type: 'number', default: 0, min: 0, max: 1, onlyInt: true }
        ],
        indexes: [
            'CREATE UNIQUE INDEX idx_tbl_auth_role_perms_role_perm_id ON tbl_auth_role_perms (role_perm_id)',
            'CREATE INDEX idx_tbl_auth_role_perms_role_id ON tbl_auth_role_perms (role_id)',
            'CREATE INDEX idx_tbl_auth_role_perms_res_id ON tbl_auth_role_perms (res_id)',
            'CREATE UNIQUE INDEX idx_tbl_auth_role_perms_unique_map ON tbl_auth_role_perms (role_id, res_id)'
        ]
    },
    {
        name: 'tbl_auth_user_overrides',
        type: 'base',
        listRule: SOFT_DELETE_RULE,
        viewRule: SOFT_DELETE_RULE,
        fields: [
            { name: 'override_id', type: 'text', required: true },
            { name: 'users_convers_id', type: 'text', required: true },
            { name: 'res_id', type: 'text', required: true },
            { name: 'access_level', type: 'number', required: true },
            { name: 'priority', type: 'number' },
            { name: 'is_delete', type: 'number', default: 0, min: 0, max: 1, onlyInt: true }
        ],
        indexes: [
            'CREATE UNIQUE INDEX idx_tbl_auth_user_overrides_override_id ON tbl_auth_user_overrides (override_id)',
            'CREATE INDEX idx_tbl_auth_user_overrides_users_convers_id ON tbl_auth_user_overrides (users_convers_id)',
            'CREATE INDEX idx_tbl_auth_user_overrides_res_id ON tbl_auth_user_overrides (res_id)',
            'CREATE UNIQUE INDEX idx_tbl_auth_user_overrides_unique_map ON tbl_auth_user_overrides (users_convers_id, res_id)'
        ]
    },
    {
        name: 'tbl_auth_row_scopes',
        type: 'base',
        listRule: SOFT_DELETE_RULE,
        viewRule: SOFT_DELETE_RULE,
        fields: [
            { name: 'scope_id', type: 'text', required: true },
            { name: 'target_type', type: 'text', required: true },
            { name: 'target_id', type: 'text', required: true },
            { name: 'table_name', type: 'text', required: true },
            { name: 'filter_sql', type: 'editor', required: true },
            { name: 'is_delete', type: 'number', default: 0, min: 0, max: 1, onlyInt: true }
        ],
        indexes: [
            'CREATE UNIQUE INDEX idx_tbl_auth_row_scopes_scope_id ON tbl_auth_row_scopes (scope_id)',
            'CREATE INDEX idx_tbl_auth_row_scopes_target_type ON tbl_auth_row_scopes (target_type)',
            'CREATE INDEX idx_tbl_auth_row_scopes_target_id ON tbl_auth_row_scopes (target_id)',
            'CREATE INDEX idx_tbl_auth_row_scopes_table_name ON tbl_auth_row_scopes (table_name)'
        ]
    }
];

async function init() {
    try {
        console.log('🔄 正在连接 PocketBase API...');

        if (AUTH_TOKEN) {
            pb.authStore.save(AUTH_TOKEN, null);
            console.log('✅ 已使用 POCKETBASE_AUTH_TOKEN 载入认证状态。');
        } else if (ADMIN_EMAIL && ADMIN_PASSWORD) {
            await pb.collection('_superusers').authWithPassword(ADMIN_EMAIL, ADMIN_PASSWORD);
            console.log('✅ 已使用超级管理员账号登录。');
        } else {
            throw new Error('缺少 PocketBase API 认证信息，请提供 POCKETBASE_AUTH_TOKEN 或 PB_ADMIN_EMAIL/PB_ADMIN_PASSWORD');
        }

        console.log('🚀 开始初始化 newpb 权限模型表结构...\n');

        for (const collectionData of collections) {
            await createOrUpdateCollection(collectionData);
        }

        await verifyCollections(collections);
        console.log('\n🎉 newpb 权限模型表结构初始化并校验完成！');
    } catch (error) {
        console.error('❌ 初始化失败:', error.response?.data || error.message);
        process.exitCode = 1;
    }
}

async function createOrUpdateCollection(collectionData) {
    console.log(`🔄 正在处理表: ${collectionData.name} ...`);
    const payload = {
        name: collectionData.name,
        type: collectionData.type,
        listRule: Object.prototype.hasOwnProperty.call(collectionData, 'listRule') ? collectionData.listRule : null,
        viewRule: Object.prototype.hasOwnProperty.call(collectionData, 'viewRule') ? collectionData.viewRule : null,
        createRule: Object.prototype.hasOwnProperty.call(collectionData, 'createRule') ? collectionData.createRule : null,
        updateRule: Object.prototype.hasOwnProperty.call(collectionData, 'updateRule') ? collectionData.updateRule : null,
        deleteRule: Object.prototype.hasOwnProperty.call(collectionData, 'deleteRule') ? collectionData.deleteRule : null,
        fields: collectionData.fields,
        indexes: collectionData.indexes,
    };

    try {
        await pb.collections.create(payload);
        console.log(`✅ ${collectionData.name} 创建完成。`);
    } catch (error) {
        const nameErrorCode = error.response?.data?.name?.code;
        if (
            error.status === 400
            && (nameErrorCode === 'validation_not_unique' || nameErrorCode === 'validation_collection_name_exists')
        ) {
            const existing = await pb.collections.getOne(collectionData.name);
            await pb.collections.update(existing.id, payload);
            console.log(`♻️ ${collectionData.name} 已存在，已按最新结构更新。`);
            return;
        }
        console.error(`❌ 处理集合 ${collectionData.name} 失败:`, {
            status: error.status,
            message: error.message,
            response: error.response?.data,
        });
        throw error;
    }
}

async function verifyCollections(targetCollections) {
    console.log('\n🔍 开始校验 newpb 表结构与索引...');

    for (const target of targetCollections) {
        const remote = await pb.collections.getOne(target.name);
        const remoteFieldNames = new Set((remote.fields || []).map((field) => field.name));
        const missingFields = target.fields
            .map((field) => field.name)
            .filter((fieldName) => !remoteFieldNames.has(fieldName));

        const remoteIndexes = new Set(remote.indexes || []);
        const missingIndexes = target.indexes.filter((indexSql) => !remoteIndexes.has(indexSql));

        if (remote.type !== target.type) {
            throw new Error(`${target.name} 类型不匹配，期望 ${target.type}，实际 ${remote.type}`);
        }

        if (missingFields.length === 0 && missingIndexes.length === 0) {
            console.log(`✅ ${target.name} 校验通过。`);
            continue;
        }

        console.log(`❌ ${target.name} 校验失败：`);
        if (missingFields.length > 0) {
            console.log(`  - 缺失字段: ${missingFields.join(', ')}`);
        }
        if (missingIndexes.length > 0) {
            console.log(`  - 缺失索引: ${missingIndexes.join(' | ')}`);
        }

        throw new Error(`${target.name} 结构与预期不一致`);
    }
}

init();
