<template>
    <div class="tenants-page">
        <a-card class="mb-4">
            <template #title>租户管理</template>
            <template #extra>
                <a-button v-permission="'tenant:create'" type="primary" @click="handleAdd">新增租户</a-button>
            </template>
        </a-card>
        <a-table :columns="columns" :data-source="dataSource" :loading="loading" :pagination="pagination"
            @change="handleTableChange">
            <template #bodyCell="{ column, record }">
                <template v-if="column.key === 'code'">
                    <a-tag color="blue">{{ record.code }}</a-tag>
                </template>
                <template v-if="column.key === 'domain'">
                    <span>{{ record.domain || '-' }}</span>
                </template>
                <template v-if="column.key === 'isSuper'">
                    <a-tag :color="record.isSuper === 1 ? 'red' : 'default'">
                        {{ record.isSuper === 1 ? '超级租户' : '普通租户' }}
                    </a-tag>
                </template>
                <template v-if="column.key === 'validState'">
                    <a-tag :color="record.validState === 1 ? 'green' : 'red'">
                        {{ record.validState === 1 ? '有效' : '失效' }}
                    </a-tag>
                </template>
                <template v-if="column.key === 'statistics'">
                    <span>用户: {{ record._count?.users || 0 }} | 角色: {{ record._count?.roles || 0 }}</span>
                </template>
                <template v-if="column.key === 'menus'">
                    <a-tag v-for="tenantMenu in record.menus" :key="tenantMenu.id" class="mr-1">
                        {{ tenantMenu.menu.name }}
                    </a-tag>
                    <span v-if="!record.menus || record.menus.length === 0">-</span>
                </template>
                <template v-if="column.key === 'createTime'">
                    <span>{{ formatDate(record.createTime) }}</span>
                </template>
                <template v-if="column.key === 'action'">
                    <a-space>
                        <a-button v-permission="'tenant:update'" type="link" size="small" @click="handleEdit(record)">
                            编辑
                        </a-button>
                        <a-button v-permission="'tenant:delete'" v-if="record.isSuper !== 1" type="link" size="small"
                            danger @click="handleDelete(record)">
                            删除
                        </a-button>
                        <a-tooltip v-if="record.isSuper === 1" title="超级租户不允许删除">
                            <a-button type="link" size="small" disabled>
                                删除
                            </a-button>
                        </a-tooltip>
                    </a-space>
                </template>
            </template>
        </a-table>

        <!-- 新增/编辑租户弹窗 -->
        <a-modal v-model:open="modalVisible" :title="modalTitle" :confirm-loading="submitLoading" @ok="handleSubmit"
            @cancel="handleCancel" width="900px" :loading="detailLoading">
            <a-tabs v-model:activeKey="activeTab">
                <a-tab-pane key="basic" tab="基本信息">
                    <a-form ref="formRef" :model="form" :rules="rules" :label-col="{ span: 6 }"
                        :wrapper-col="{ span: 18 }">
                        <a-form-item label="租户名称" name="name">
                            <a-input v-model:value="form.name" placeholder="请输入租户名称" :maxlength="50" />
                        </a-form-item>
                        <a-form-item label="租户编码" name="code">
                            <a-input v-model:value="form.code" placeholder="请输入租户编码（用于访问链接）" :maxlength="50"
                                :disabled="!!editingId" />
                        </a-form-item>
                        <a-form-item label="租户域名" name="domain">
                            <a-input v-model:value="form.domain" placeholder="请输入租户域名（可选，用于子域名访问）" :maxlength="100" />
                        </a-form-item>
                        <a-form-item label="描述" name="description">
                            <a-textarea v-model:value="form.description" placeholder="请输入租户描述" :rows="3"
                                :maxlength="500" />
                        </a-form-item>
                        <a-form-item v-if="editingId" label="状态" name="validState">
                            <a-radio-group v-model:value="form.validState">
                                <a-radio :value="1">有效</a-radio>
                                <a-radio :value="2">失效</a-radio>
                            </a-radio-group>
                        </a-form-item>
                    </a-form>
                </a-tab-pane>
                <a-tab-pane key="menus" tab="菜单分配">
                    <div v-if="menusLoading" style="text-align: center; padding: 40px;">
                        <a-spin size="large" />
                    </div>
                    <div v-else>
                        <div v-for="parentMenu in topLevelMenus" :key="parentMenu.id" class="menu-group">
                            <div class="menu-group-header">
                                <a-checkbox :checked="isMenuAllChecked(parentMenu)"
                                    :indeterminate="isMenuIndeterminate(parentMenu)"
                                    @change="handleMenuCheckAll(parentMenu, $event)">
                                    <strong>{{ parentMenu.name }}</strong>
                                    <span v-if="parentMenu.path" class="menu-path">({{ parentMenu.path }})</span>
                                </a-checkbox>
                            </div>
                            <div v-if="parentMenu.children && parentMenu.children.length > 0" class="menu-items">
                                <a-row :gutter="[16, 8]">
                                    <a-col :span="8" v-for="childMenu in parentMenu.children" :key="childMenu.id">
                                        <a-checkbox :checked="form.menuIds?.includes(childMenu.id)"
                                            @change="handleChildMenuChange(childMenu.id, $event)">
                                            {{ childMenu.name }}
                                            <span v-if="childMenu.path" class="menu-path">({{ childMenu.path
                                                }})</span>
                                        </a-checkbox>
                                    </a-col>
                                </a-row>
                            </div>
                        </div>
                        <div v-if="topLevelMenus.length === 0" style="text-align: center; padding: 40px; color: #999">
                            暂无菜单数据
                        </div>
                    </div>
                </a-tab-pane>
            </a-tabs>
        </a-modal>
    </div>
</template>

<script setup lang="ts">
import { ref, reactive, nextTick, onMounted, computed } from 'vue'
import { message, Modal } from 'ant-design-vue'
import type { TableColumnsType, FormInstance } from 'ant-design-vue'
import {
    tenantsApi,
    type Tenant,
    type CreateTenantForm,
    type UpdateTenantForm,
} from '@/api/tenants'
import { menusApi, type Menu } from '@/api/menus'
import { useListRequest } from '@/composables/useListRequest'
import { useAuthStore } from '@/stores/auth'

const authStore = useAuthStore()

const submitLoading = ref(false)
const detailLoading = ref(false)
const menusLoading = ref(false)
const modalVisible = ref(false)
const modalTitle = ref('新增租户')
const formRef = ref<FormInstance>()
const editingId = ref<number | null>(null)
const activeTab = ref('basic')

// 菜单相关
const allMenus = ref<Menu[]>([])
const topLevelMenus = computed(() => {
    // 构建菜单树结构，返回的已经是根菜单列表
    return buildMenuTree(allMenus.value)
})

// 使用列表请求组合函数
const {
    loading,
    dataSource,
    pagination,
    handleTableChange,
    refresh: refreshList,
} = useListRequest<Tenant>({
    requestFn: tenantsApi.getList,
    errorMessage: '获取租户列表失败',
})

const form = reactive<CreateTenantForm & { validState?: number; menuIds?: number[] }>({
    name: '',
    code: '',
    domain: '',
    description: '',
    validState: 1,
    menuIds: [],
})

const rules = {
    name: [
        { required: true, message: '请输入租户名称', trigger: 'blur' },
        { max: 50, message: '租户名称不能超过50个字符', trigger: 'blur' },
    ],
    code: [
        { required: true, message: '请输入租户编码', trigger: 'blur' },
        { max: 50, message: '租户编码不能超过50个字符', trigger: 'blur' },
        {
            pattern: /^[a-z][a-z0-9_-]*$/,
            message: '租户编码只能包含小写字母、数字、下划线和连字符，且必须以字母开头',
            trigger: 'blur',
        },
    ],
    domain: [
        { max: 100, message: '域名不能超过100个字符', trigger: 'blur' },
    ],
    description: [
        { max: 500, message: '描述不能超过500个字符', trigger: 'blur' },
    ],
}

const columns: TableColumnsType = [
    { title: 'ID', dataIndex: 'id', key: 'id', width: 80 },
    { title: '租户名称', dataIndex: 'name', key: 'name' },
    { title: '租户编码', dataIndex: 'code', key: 'code' },
    { title: '域名', dataIndex: 'domain', key: 'domain' },
    { title: '类型', dataIndex: 'isSuper', key: 'isSuper', width: 100 },
    { title: '状态', dataIndex: 'validState', key: 'validState', width: 80 },
    { title: '统计', dataIndex: 'statistics', key: 'statistics', width: 150 },
    { title: '菜单', dataIndex: 'menus', key: 'menus', width: 400 },
    { title: '创建时间', dataIndex: 'createTime', key: 'createTime', width: 180 },
    { title: '操作', key: 'action', width: 250, fixed: 'right' },
]

// 格式化日期
const formatDate = (dateStr?: string) => {
    if (!dateStr) return '-'
    const date = new Date(dateStr)
    return date.toLocaleString('zh-CN', {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
    })
}

// 加载所有菜单
const fetchAllMenus = async () => {
    menusLoading.value = true
    try {
        allMenus.value = await menusApi.getList()
    } catch (error) {
        message.error('获取菜单列表失败')
    } finally {
        menusLoading.value = false
    }
}

// 获取"租户管理"菜单及其所有子菜单的ID集合
const getTenantMenuIds = (): Set<number> => {
    const tenantMenuIds = new Set<number>()
    const tenantMenu = findMenuInTree(allMenus.value, '租户管理')
    if (tenantMenu) {
        collectMenuIds(tenantMenu, tenantMenuIds)
    }
    return tenantMenuIds
}

// 加载租户已分配的菜单
const fetchTenantMenus = async (tenantId: number) => {
    try {
        const tenantMenus = await tenantsApi.getTenantMenus(tenantId)
        // 提取所有菜单ID（包括父菜单和子菜单）
        const extractMenuIds = (menus: Menu[]): number[] => {
            const ids: number[] = []
            menus.forEach((menu) => {
                ids.push(menu.id)
                if (menu.children && menu.children.length > 0) {
                    ids.push(...extractMenuIds(menu.children))
                }
            })
            return ids
        }
        const allMenuIds = extractMenuIds(tenantMenus)
        // 过滤掉"租户管理"菜单的ID
        const tenantMenuIds = getTenantMenuIds()
        form.menuIds = allMenuIds.filter((id) => !tenantMenuIds.has(id))
    } catch (error) {
        message.error('获取租户菜单失败')
    }
}

// 扁平化菜单树（递归提取所有菜单，包括嵌套的 children）
const flattenMenus = (menus: Menu[]): Menu[] => {
    const result: Menu[] = []
    const traverse = (menuList: Menu[]) => {
        menuList.forEach((menu) => {
            // 创建菜单副本，移除 children（稍后会重新构建）
            const { children, ...menuWithoutChildren } = menu
            result.push(menuWithoutChildren as Menu)
            // 递归处理子菜单
            if (children && children.length > 0) {
                traverse(children)
            }
        })
    }
    traverse(menus)
    return result
}

// 递归查找菜单（在树结构中）
const findMenuInTree = (menus: Menu[], name: string): Menu | null => {
    for (const menu of menus) {
        if (menu.name === name) {
            return menu
        }
        if (menu.children && menu.children.length > 0) {
            const found = findMenuInTree(menu.children, name)
            if (found) return found
        }
    }
    return null
}

// 递归收集菜单及其所有子菜单的ID
const collectMenuIds = (menu: Menu, ids: Set<number>) => {
    ids.add(menu.id)
    if (menu.children && menu.children.length > 0) {
        menu.children.forEach((child) => collectMenuIds(child, ids))
    }
}

// 构建菜单树结构（确保父子关系正确）
const buildMenuTree = (menus: Menu[]): Menu[] => {
    // 先扁平化所有菜单（处理后端可能返回的树形结构）
    const flatMenus = flattenMenus(menus)

    // 过滤掉"租户管理"菜单及其所有子菜单
    const tenantMenuIds = new Set<number>()

    // 在原始菜单树中查找"租户管理"菜单
    const tenantMenu = findMenuInTree(menus, '租户管理')
    if (tenantMenu) {
        // 收集"租户管理"菜单及其所有子菜单的ID
        collectMenuIds(tenantMenu, tenantMenuIds)
    }

    // 从扁平化菜单中移除"租户管理"及其子菜单
    const filteredMenus = flatMenus.filter((menu) => !tenantMenuIds.has(menu.id))

    // 构建菜单树（使用过滤后的菜单）
    const menuMap = new Map<number, Menu>()
    const rootMenus: Menu[] = []

    // 第一遍：创建所有菜单的映射（初始化 children 为空数组）
    filteredMenus.forEach((menu) => {
        menuMap.set(menu.id, { ...menu, children: [] })
    })

    // 第二遍：建立父子关系
    filteredMenus.forEach((menu) => {
        const menuNode = menuMap.get(menu.id)!
        if (menu.parentId && menuMap.has(menu.parentId)) {
            // 有父菜单，添加到父菜单的 children
            const parent = menuMap.get(menu.parentId)!
            if (!parent.children) {
                parent.children = []
            }
            parent.children.push(menuNode)
        } else {
            // 没有父菜单或父菜单不存在，添加到根菜单
            rootMenus.push(menuNode)
        }
    })

    // 对子菜单进行排序
    const sortMenus = (menuList: Menu[]) => {
        menuList.forEach((menu) => {
            if (menu.children && menu.children.length > 0) {
                menu.children.sort((a, b) => (a.sort || 0) - (b.sort || 0))
                sortMenus(menu.children)
            }
        })
        menuList.sort((a, b) => (a.sort || 0) - (b.sort || 0))
    }
    sortMenus(rootMenus)

    return rootMenus
}

// 检查菜单及其子菜单是否全选
const isMenuAllChecked = (menu: Menu): boolean => {
    if (!menu.children || menu.children.length === 0) {
        // 叶子菜单，检查自身是否选中
        return form.menuIds?.includes(menu.id) || false
    }
    // 父菜单，检查所有子菜单是否都选中
    return menu.children.every((child) => form.menuIds?.includes(child.id))
}

// 检查菜单是否部分选中（indeterminate状态）
const isMenuIndeterminate = (menu: Menu): boolean => {
    if (!menu.children || menu.children.length === 0) {
        return false
    }
    const checkedCount = menu.children.filter((child) => form.menuIds?.includes(child.id)).length
    return checkedCount > 0 && checkedCount < menu.children.length
}

// 菜单全选/取消全选
const handleMenuCheckAll = (menu: Menu, e: any) => {
    if (!menu.children || menu.children.length === 0) {
        // 叶子菜单，直接切换自身
        const checked = e.target.checked
        if (checked) {
            if (!form.menuIds?.includes(menu.id)) {
                form.menuIds = [...(form.menuIds || []), menu.id]
            }
        } else {
            form.menuIds = (form.menuIds || []).filter((id) => id !== menu.id)
        }
        return
    }

    // 父菜单，切换所有子菜单
    const checked = e.target.checked
    const childMenuIds = menu.children.map((child) => child.id)

    if (checked) {
        // 全选：添加所有子菜单
        const newIds = [...(form.menuIds || [])]
        childMenuIds.forEach((id) => {
            if (!newIds.includes(id)) {
                newIds.push(id)
            }
        })
        form.menuIds = newIds
    } else {
        // 取消全选：移除所有子菜单
        form.menuIds = (form.menuIds || []).filter((id) => !childMenuIds.includes(id))
    }
}

// 处理子菜单选中/取消选中
const handleChildMenuChange = (menuId: number, e: any) => {
    const checked = e.target.checked
    // 确保 form.menuIds 是数组
    if (!form.menuIds) {
        form.menuIds = []
    }

    if (checked) {
        // 选中：添加到数组（如果不存在）
        if (!form.menuIds.includes(menuId)) {
            form.menuIds = [...form.menuIds, menuId]
        }
    } else {
        // 取消选中：从数组移除
        form.menuIds = form.menuIds.filter((id) => id !== menuId)
    }
}

// 新增租户
const handleAdd = () => {
    if (!authStore.hasPermission('tenant:create')) {
        message.error('您没有创建租户的权限')
        return
    }

    modalTitle.value = '新增租户'
    editingId.value = null
    activeTab.value = 'basic'
    modalVisible.value = true
    nextTick(() => {
        formRef.value?.resetFields()
        form.name = ''
        form.code = ''
        form.domain = ''
        form.description = ''
        form.validState = 1
        form.menuIds = []
    })
}

// 编辑租户
const handleEdit = async (record: Tenant) => {
    if (!authStore.hasPermission('tenant:update')) {
        message.error('您没有编辑租户的权限')
        return
    }

    modalTitle.value = '编辑租户'
    editingId.value = record.id
    activeTab.value = 'basic'
    modalVisible.value = true
    detailLoading.value = true

    try {
        // 并行加载租户详情和租户已分配的菜单
        const [detail] = await Promise.all([
            tenantsApi.getDetail(record.id),
        ])

        form.name = detail.name
        form.code = detail.code
        form.domain = detail.domain || ''
        form.description = detail.description || ''
        form.validState = detail.validState
        form.menuIds = []

        // 加载租户已分配的菜单
        await fetchTenantMenus(record.id)
    } catch (error) {
        message.error('获取租户详情失败')
        modalVisible.value = false
    } finally {
        detailLoading.value = false
    }
}

// 删除租户
const handleDelete = (record: Tenant) => {
    if (!authStore.hasPermission('tenant:delete')) {
        message.error('您没有删除租户的权限')
        return
    }

    if (record.isSuper === 1) {
        message.error('不能删除超级租户')
        return
    }

    Modal.confirm({
        title: '确认删除',
        content: `确定要删除租户 "${record.name}" 吗？删除后该租户的所有数据将被删除，此操作不可恢复。`,
        okText: '确定',
        okType: 'danger',
        cancelText: '取消',
        onOk: async () => {
            try {
                await tenantsApi.delete(record.id)
                message.success('删除成功')
                refreshList()
            } catch (error: any) {
                const errorMessage = error?.response?.data?.message || '删除失败'
                message.error(errorMessage)
            }
        },
    })
}

// 提交表单
const handleSubmit = async () => {
    try {
        await formRef.value?.validate()
        submitLoading.value = true

        // 过滤掉"租户管理"菜单的ID
        const tenantMenuIds = getTenantMenuIds()
        const filteredMenuIds = (form.menuIds || []).filter((id) => !tenantMenuIds.has(id))

        if (editingId.value) {
            // 编辑（包含菜单分配）
            const updateData: UpdateTenantForm = {
                name: form.name,
                code: form.code,
                domain: form.domain || undefined,
                description: form.description || undefined,
                validState: form.validState,
                menuIds: filteredMenuIds,
            }
            await tenantsApi.update(editingId.value, updateData)
            message.success('编辑成功')
        } else {
            // 新增（可以同时分配菜单）
            const createData: CreateTenantForm = {
                name: form.name,
                code: form.code,
                domain: form.domain || undefined,
                description: form.description || undefined,
                menuIds: filteredMenuIds,
            }
            await tenantsApi.create(createData)
            message.success('新增成功')
        }

        modalVisible.value = false
        refreshList()
    } catch (error: any) {
        if (error?.errorFields) {
            // 表单验证错误
            return
        }
        const errorMessage =
            error?.response?.data?.message ||
            (editingId.value ? '编辑失败' : '新增失败')
        message.error(errorMessage)
    } finally {
        submitLoading.value = false
    }
}

// 取消表单
const handleCancel = () => {
    modalVisible.value = false
    formRef.value?.resetFields()
    activeTab.value = 'basic'
    form.menuIds = []
}

// 初始化加载菜单列表
onMounted(() => {
    fetchAllMenus()
})
</script>

<style scoped lang="scss">
.menu-group {
    margin-bottom: 24px;
    padding: 16px;
    border: 1px solid #f0f0f0;
    border-radius: 4px;

    .menu-group-header {
        margin-bottom: 12px;
        padding-bottom: 8px;
        border-bottom: 1px solid #f0f0f0;
    }

    .menu-items {
        padding-left: 24px;
    }

    .menu-path {
        color: #999;
        font-size: 12px;
        margin-left: 4px;
    }
}
</style>
