import { createRequire } from 'module';
import PocketBase from 'pocketbase';

const require = createRequire(import.meta.url);

let runtimeConfig = {};
try {
    runtimeConfig = require('../pocket-base/bai_api_pb_hooks/bai_api_shared/config/runtime.js');
} catch (_error) {
    runtimeConfig = {};
}

const PB_URL = (process.env.PB_URL || 'https://bai-api.blv-oa.com/pb').replace(/\/+$/, '');
const AUTH_TOKEN = process.env.POCKETBASE_AUTH_TOKEN || runtimeConfig.POCKETBASE_AUTH_TOKEN || '';
const OWNER_AUTH_RULE = '@request.auth.id != ""';
const SOFT_DELETE_RULE = 'is_delete = 0';

if (!AUTH_TOKEN) {
    console.error('❌ 缺少 POCKETBASE_AUTH_TOKEN，无法执行方案相关建表。');
    process.exit(1);
}

const pb = new PocketBase(PB_URL);

const collections = [
    {
        name: 'tbl_scheme_template',
        type: 'base',
        listRule: `${OWNER_AUTH_RULE} && scheme_template_owner = @request.auth.openid && ${SOFT_DELETE_RULE}`,
        viewRule: `${OWNER_AUTH_RULE} && scheme_template_owner = @request.auth.openid && ${SOFT_DELETE_RULE}`,
        createRule: `${OWNER_AUTH_RULE} && @request.body.scheme_template_owner = @request.auth.openid`,
        updateRule: `${OWNER_AUTH_RULE} && scheme_template_owner = @request.auth.openid && ${SOFT_DELETE_RULE}`,
        deleteRule: `${OWNER_AUTH_RULE} && scheme_template_owner = @request.auth.openid && ${SOFT_DELETE_RULE}`,
        fields: [
            { name: 'scheme_template_id', type: 'text', required: true, autogeneratePattern: 'SCHTPL-[0-9]{13}-[A-Za-z0-9]{6}' },
            { name: 'scheme_template_icon', type: 'text' },
            { name: 'scheme_template_label', type: 'text' },
            { name: 'scheme_template_name', type: 'text', required: true },
            { name: 'scheme_template_owner', type: 'text', required: true },
            { name: 'scheme_template_status', type: 'text' },
            { name: 'scheme_template_solution_type', type: 'text' },
            { name: 'scheme_template_solution_feature', type: 'text' },
            { name: 'scheme_template_product_list', type: 'json' },
            { name: 'scheme_template_description', type: 'text' },
            { name: 'scheme_template_remark', type: 'text' },
            { name: 'is_delete', type: 'number', default: 0, min: 0, max: 1, onlyInt: true },
        ],
        indexes: [
            'CREATE UNIQUE INDEX idx_tbl_scheme_template_scheme_template_id ON tbl_scheme_template (scheme_template_id)',
            'CREATE INDEX idx_tbl_scheme_template_scheme_template_owner ON tbl_scheme_template (scheme_template_owner)',
            'CREATE INDEX idx_tbl_scheme_template_scheme_template_name ON tbl_scheme_template (scheme_template_name)',
            'CREATE INDEX idx_tbl_scheme_template_scheme_template_label ON tbl_scheme_template (scheme_template_label)',
            'CREATE INDEX idx_tbl_scheme_template_scheme_template_status ON tbl_scheme_template (scheme_template_status)',
            'CREATE INDEX idx_tbl_scheme_template_solution_type ON tbl_scheme_template (scheme_template_solution_type)',
            'CREATE INDEX idx_tbl_scheme_template_solution_feature ON tbl_scheme_template (scheme_template_solution_feature)',
            'CREATE INDEX idx_tbl_scheme_template_owner_status ON tbl_scheme_template (scheme_template_owner, scheme_template_status)',
        ],
    },
    {
        name: 'tbl_scheme',
        type: 'base',
        listRule: `${OWNER_AUTH_RULE} && scheme_owner = @request.auth.openid && ${SOFT_DELETE_RULE}`,
        viewRule: `${OWNER_AUTH_RULE} && scheme_owner = @request.auth.openid && ${SOFT_DELETE_RULE}`,
        createRule: `${OWNER_AUTH_RULE} && @request.body.scheme_owner = @request.auth.openid`,
        updateRule: `${OWNER_AUTH_RULE} && scheme_owner = @request.auth.openid && ${SOFT_DELETE_RULE}`,
        deleteRule: `${OWNER_AUTH_RULE} && scheme_owner = @request.auth.openid && ${SOFT_DELETE_RULE}`,
        fields: [
            { name: 'scheme_id', type: 'text', required: true, autogeneratePattern: 'SCHEME-[0-9]{13}-[A-Za-z0-9]{6}' },
            { name: 'scheme_name', type: 'text', required: true },
            { name: 'scheme_owner', type: 'text', required: true },
            { name: 'scheme_share_status', type: 'text' },
            { name: 'scheme_expires_at', type: 'date' },
            { name: 'scheme_hotel_type', type: 'text' },
            { name: 'scheme_solution_type', type: 'text' },
            { name: 'scheme_solution_feature', type: 'text' },
            { name: 'scheme_room_type', type: 'json' },
            { name: 'scheme_curtains', type: 'text' },
            { name: 'scheme_voice_device', type: 'text' },
            { name: 'scheme_ac_type', type: 'text' },
            { name: 'scheme_template_highend', type: 'text' },
            { name: 'scheme_template_midend', type: 'text' },
            { name: 'scheme_template_lowend', type: 'text' },
            { name: 'scheme_status', type: 'text' },
            { name: 'scheme_remark', type: 'text' },
            { name: 'is_delete', type: 'number', default: 0, min: 0, max: 1, onlyInt: true },
        ],
        indexes: [
            'CREATE UNIQUE INDEX idx_tbl_scheme_scheme_id ON tbl_scheme (scheme_id)',
            'CREATE INDEX idx_tbl_scheme_scheme_owner ON tbl_scheme (scheme_owner)',
            'CREATE INDEX idx_tbl_scheme_scheme_name ON tbl_scheme (scheme_name)',
            'CREATE INDEX idx_tbl_scheme_scheme_share_status ON tbl_scheme (scheme_share_status)',
            'CREATE INDEX idx_tbl_scheme_scheme_expires_at ON tbl_scheme (scheme_expires_at)',
            'CREATE INDEX idx_tbl_scheme_scheme_hotel_type ON tbl_scheme (scheme_hotel_type)',
            'CREATE INDEX idx_tbl_scheme_scheme_solution_type ON tbl_scheme (scheme_solution_type)',
            'CREATE INDEX idx_tbl_scheme_scheme_solution_feature ON tbl_scheme (scheme_solution_feature)',
            'CREATE INDEX idx_tbl_scheme_scheme_status ON tbl_scheme (scheme_status)',
            'CREATE INDEX idx_tbl_scheme_owner_status ON tbl_scheme (scheme_owner, scheme_status)',
        ],
    },
    {
        name: 'tbl_scheme_share',
        type: 'base',
        listRule: `${OWNER_AUTH_RULE} && scheme_share_owner = @request.auth.openid && ${SOFT_DELETE_RULE}`,
        viewRule: `${OWNER_AUTH_RULE} && scheme_share_owner = @request.auth.openid && ${SOFT_DELETE_RULE}`,
        createRule: `${OWNER_AUTH_RULE} && @request.body.scheme_share_owner = @request.auth.openid`,
        updateRule: `${OWNER_AUTH_RULE} && scheme_share_owner = @request.auth.openid && ${SOFT_DELETE_RULE}`,
        deleteRule: `${OWNER_AUTH_RULE} && scheme_share_owner = @request.auth.openid && ${SOFT_DELETE_RULE}`,
        fields: [
            { name: 'scheme_share_id', type: 'text', required: true, autogeneratePattern: 'SCHSHARE-[0-9]{13}-[A-Za-z0-9]{6}' },
            { name: 'scheme_id', type: 'text', required: true },
            { name: 'scheme_share_owner', type: 'text', required: true },
            { name: 'scheme_share_to', type: 'text', required: true },
            { name: 'scheme_share_acceptance_status', type: 'text' },
            { name: 'scheme_share_expires_at', type: 'date' },
            { name: 'scheme_share_permission', type: 'text' },
            { name: 'scheme_share_remark', type: 'text' },
            { name: 'is_delete', type: 'number', default: 0, min: 0, max: 1, onlyInt: true },
        ],
        indexes: [
            'CREATE UNIQUE INDEX idx_tbl_scheme_share_scheme_share_id ON tbl_scheme_share (scheme_share_id)',
            'CREATE INDEX idx_tbl_scheme_share_scheme_id ON tbl_scheme_share (scheme_id)',
            'CREATE INDEX idx_tbl_scheme_share_scheme_share_owner ON tbl_scheme_share (scheme_share_owner)',
            'CREATE INDEX idx_tbl_scheme_share_scheme_share_to ON tbl_scheme_share (scheme_share_to)',
            'CREATE INDEX idx_tbl_scheme_share_acceptance_status ON tbl_scheme_share (scheme_share_acceptance_status)',
            'CREATE INDEX idx_tbl_scheme_share_expires_at ON tbl_scheme_share (scheme_share_expires_at)',
            'CREATE INDEX idx_tbl_scheme_share_owner_to ON tbl_scheme_share (scheme_share_owner, scheme_share_to)',
            'CREATE UNIQUE INDEX idx_tbl_scheme_share_unique_map ON tbl_scheme_share (scheme_share_owner, scheme_id, scheme_share_to)',
        ],
    },
];

function normalizeFieldPayload(field, existingField) {
    const payload = existingField
        ? Object.assign({}, existingField)
        : {
            name: field.name,
            type: field.type,
        };

    if (existingField && existingField.id) {
        payload.id = existingField.id;
    }

    payload.name = field.name;
    payload.type = field.type;

    if (typeof field.required !== 'undefined') {
        payload.required = field.required;
    }

    if (field.type === 'autodate') {
        payload.onCreate = typeof field.onCreate === 'boolean' ? field.onCreate : true;
        payload.onUpdate = typeof field.onUpdate === 'boolean' ? field.onUpdate : false;
    }

    if (field.type === 'date') {
        payload.required = !!field.required;
    }

    return payload;
}

function buildCollectionPayload(collectionData, existingCollection) {
    if (!existingCollection) {
        return {
            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.map((field) => normalizeFieldPayload(field, null)),
            indexes: collectionData.indexes,
        };
    }

    const targetFieldMap = new Map(collectionData.fields.map((field) => [field.name, field]));
    const fields = (existingCollection.fields || []).map((existingField) => {
        const targetField = targetFieldMap.get(existingField.name);
        if (!targetField) {
            return existingField;
        }

        targetFieldMap.delete(existingField.name);
        return normalizeFieldPayload(targetField, existingField);
    });

    for (const field of targetFieldMap.values()) {
        fields.push(normalizeFieldPayload(field, null));
    }

    return {
        name: collectionData.name,
        type: collectionData.type,
        listRule: Object.prototype.hasOwnProperty.call(collectionData, 'listRule') ? collectionData.listRule : existingCollection.listRule,
        viewRule: Object.prototype.hasOwnProperty.call(collectionData, 'viewRule') ? collectionData.viewRule : existingCollection.viewRule,
        createRule: Object.prototype.hasOwnProperty.call(collectionData, 'createRule') ? collectionData.createRule : existingCollection.createRule,
        updateRule: Object.prototype.hasOwnProperty.call(collectionData, 'updateRule') ? collectionData.updateRule : existingCollection.updateRule,
        deleteRule: Object.prototype.hasOwnProperty.call(collectionData, 'deleteRule') ? collectionData.deleteRule : existingCollection.deleteRule,
        fields: fields,
        indexes: collectionData.indexes,
    };
}

function normalizeFieldList(fields) {
    return (fields || []).map((field) => ({
        name: field.name,
        type: field.type,
        required: !!field.required,
    }));
}

async function createOrUpdateCollection(collectionData) {
    console.log(`🔄 正在处理表: ${collectionData.name} ...`);

    try {
        const list = await pb.collections.getFullList({
            sort: '-created',
        });
        const existing = list.find((item) => item.name === collectionData.name);

        if (existing) {
            await pb.collections.update(existing.id, buildCollectionPayload(collectionData, existing));
            console.log(`♻️ ${collectionData.name} 已存在，已按最新结构更新。`);
            return;
        }

        await pb.collections.create(buildCollectionPayload(collectionData, null));
        console.log(`✅ ${collectionData.name} 创建完成。`);
    } catch (error) {
        console.error(`❌ 处理集合 ${collectionData.name} 失败:`, {
            status: error.status,
            message: error.message,
            response: error.response,
        });
        throw error;
    }
}

async function getCollectionByName(collectionName) {
    const list = await pb.collections.getFullList({
        sort: '-created',
    });
    return list.find((item) => item.name === collectionName) || null;
}

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

    for (const target of targetCollections) {
        const remote = await getCollectionByName(target.name);
        if (!remote) {
            throw new Error(`${target.name} 不存在`);
        }

        const remoteFields = normalizeFieldList(remote.fields);
        const targetFields = normalizeFieldList(target.fields);
        const remoteFieldMap = new Map(remoteFields.map((field) => [field.name, field.type]));
        const remoteRequiredMap = new Map(remoteFields.map((field) => [field.name, field.required]));
        const missingFields = [];
        const mismatchedTypes = [];
        const mismatchedRequired = [];

        for (const field of targetFields) {
            if (!remoteFieldMap.has(field.name)) {
                missingFields.push(field.name);
                continue;
            }

            if (remoteFieldMap.get(field.name) !== field.type) {
                mismatchedTypes.push(`${field.name}:${remoteFieldMap.get(field.name)}!=${field.type}`);
            }

            if (remoteRequiredMap.get(field.name) !== !!field.required) {
                mismatchedRequired.push(`${field.name}:${remoteRequiredMap.get(field.name)}!=${!!field.required}`);
            }
        }

        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 && !mismatchedTypes.length && !mismatchedRequired.length && !missingIndexes.length) {
            console.log(`✅ ${target.name} 校验通过。`);
            continue;
        }

        console.log(`❌ ${target.name} 校验失败：`);
        if (missingFields.length) {
            console.log(`  - 缺失字段: ${missingFields.join(', ')}`);
        }
        if (mismatchedTypes.length) {
            console.log(`  - 字段类型不匹配: ${mismatchedTypes.join(', ')}`);
        }
        if (mismatchedRequired.length) {
            console.log(`  - 字段必填属性不匹配: ${mismatchedRequired.join(', ')}`);
        }
        if (missingIndexes.length) {
            console.log(`  - 缺失索引: ${missingIndexes.join(' | ')}`);
        }

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

async function init() {
    try {
        console.log(`🔄 正在连接 PocketBase: ${PB_URL}`);
        pb.authStore.save(AUTH_TOKEN, null);
        console.log('✅ 已使用 POCKETBASE_AUTH_TOKEN 载入认证状态。');

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

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

init();
