<script setup lang="ts">
import { ref, onMounted, computed, h } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import {
    Card,
    Typography,
    Button,
    List,
    Space,
    Spin,
    Input,
    message,
    Tag,
    Modal,
    Tabs,
    InputNumber,
    Select,
    Upload,
    Steps,
    Table,
} from 'ant-design-vue'
import { apiClient, isAxiosError, API } from '../router/api'
import { useUserStore } from '../stores/userStore'
import type { Organization } from '../types/organization'
import type { User } from '../types/user'
import type { InviteToken } from '../types/organization'
import type { Role } from '../types/organization'
import type { TrainingFile } from '../types/organization'
import { InboxOutlined, DeleteOutlined, ReloadOutlined } from '@ant-design/icons-vue'

const route = useRoute()
const router = useRouter()
const auth = useUserStore()

const organizationUuid = route.params.organizationUuid as string
const organization = ref<Organization | null>(null)
const members = ref<User[]>([])
const invites = ref<InviteToken[]>([])
const newInviteMaxUses = ref<number>(1)
const Roles = ref<Role[]>([])
const trainingFiles = ref<TrainingFile[]>([])
const memberSearch = ref('')
const roleSearch = ref('')
const loading = ref(false)
const deletingRoleUuid = ref<string | null>(null)
const roleModalVisible = ref(false)
const roleMembersModalVisible = ref(false)
const selectedRoleForMembers = ref<Role | null>(null)
const selectedRoleMembers = ref<User[]>([])
const roleWizardStep = ref(0)
const creatingRoleWizard = ref(false)
const createdRoleForWizard = ref<Role | null>(null)
const wizardSelectedFile = ref<File | null>(null)
const wizardFileDescription = ref('')
const wizardUploading = ref(false)
const wizardUploadedFiles = ref<TrainingFile[]>([])
const uploadModalVisible = ref(false)
const uploadRoleUuid = ref('')
const uploadSelectedFile = ref<File | null>(null)
const uploadFileDescription = ref('')
const uploadingFile = ref(false)
const createRoleForm = ref({
    name: '',
    description: '',
})
const inviteModalVisible = ref(false)
const newInviteUrl = ref('')
const editingDescription = ref(false)
const newDescription = ref('')
const ORGANIZATION_WIDE_SCOPE = '__organization_wide__'

const uploadRoleOptions = computed(() => [
    { label: 'Organization-wide (all roles)', value: ORGANIZATION_WIDE_SCOPE },
    ...Roles.value.map((role) => ({ label: role.name, value: role.uuid })),
])

const filteredMembers = computed(() => {
    const query = memberSearch.value.trim().toLowerCase()
    if (!query) return members.value
    return members.value.filter((member) => {
        const fullName = `${member.first_name} ${member.last_name}`.toLowerCase()
        return fullName.includes(query)
    })
})

const filteredRoles = computed(() => {
    const query = roleSearch.value.trim().toLowerCase()
    if (!query) return Roles.value
    return Roles.value.filter((role) => {
        const name = role.name?.toLowerCase() || ''
        const description = role.description?.toLowerCase() || ''
        return name.includes(query) || description.includes(query)
    })
})

const memberEmptyMessage = computed(() => {
    if (members.value.length === 0) return 'No members in this organization yet.'
    if (memberSearch.value.trim()) return 'No members match your search.'
    return 'No members in this organization yet.'
})

const roleEmptyMessage = computed(() => {
    if (Roles.value.length === 0) return 'No Roles in this organization yet.'
    if (roleSearch.value.trim()) return 'No roles match your search.'
    return 'No Roles in this organization yet.'
})

const fetchOrganization = async () => {
    loading.value = true
    try {
        const response = await apiClient.get<Organization>(API.organization.byId(organizationUuid))
        organization.value = response.data
        newDescription.value = response.data.description
    } catch (error) {
        console.error('Failed to fetch organization:', error)
        message.error('Failed to load organization details')
    } finally {
        loading.value = false
    }
}

const fetchMembers = async () => {
    try {
        const response = await apiClient.get<User[]>(API.organization.members.list(organizationUuid))
        members.value = response.data
    } catch (error) {
        console.error('Failed to fetch members:', error)
    }
}

const fetchInvites = async () => {
    try {
        const response = await apiClient.get<InviteToken[]>(API.invites.list(organizationUuid))
        invites.value = response.data
    } catch (error) {
        console.error('Failed to fetch invites:', error)
    }
}

const fetchRoles = async () => {
    try {
        const response = await apiClient.get<Role[]>(API.roles.list(organizationUuid))
        Roles.value = response.data as unknown as Role[]
    } catch (error) {
        console.error('Failed to fetch Roles:', error)
    }
}

const fetchTrainingFiles = async () => {
    try {
        const response = await apiClient.get<TrainingFile[]>(API.knowledge.trainingFiles.list(), {
            params: { organization_uuid: organizationUuid },
        })
        trainingFiles.value = response.data
    } catch (error) {
        console.error('Failed to fetch training files:', error)
    }
}

const getScopeLabel = (file: TrainingFile) => (file.role?.name ? file.role.name : 'Organization-wide')


const resetRoleWizard = () => {
    roleWizardStep.value = 0
    createRoleForm.value = { name: '', description: '' }
    createdRoleForWizard.value = null
    wizardSelectedFile.value = null
    wizardFileDescription.value = ''
    wizardUploadedFiles.value = []
    creatingRoleWizard.value = false
    wizardUploading.value = false
}

const closeRoleWizard = () => {
    roleModalVisible.value = false
    resetRoleWizard()
}

const openRoleWizard = () => {
    resetRoleWizard()
    roleModalVisible.value = true
}

const hasDuplicateRoleName = (name: string) =>
    Roles.value.some((role) => role.name.trim().toLowerCase() === name.trim().toLowerCase())

const allowedExtensions = ['txt', 'pdf', 'md', 'csv', 'json', 'docx', 'doc']
const maxUploadBytes = 50 * 1024 * 1024

const validateUploadFile = (file: File): boolean => {
    const extension = file.name.split('.').pop()?.toLowerCase()

    if (!extension || !allowedExtensions.includes(extension)) {
        message.error(
            `File type ".${extension}" is not allowed. Allowed types: ${allowedExtensions.join(', ')}`,
        )
        return false
    }

    if (file.size > maxUploadBytes) {
        message.error(
            `File size must not exceed 50MB. Current size: ${(file.size / 1024 / 1024).toFixed(2)}MB`,
        )
        return false
    }

    return true
}

const uploadTrainingFile = async (
    roleUuid: string | null,
    file: File,
    description: string,
): Promise<TrainingFile | null> => {
    const formData = new FormData()
    formData.append('file', file)
    formData.append('file_name', file.name)
    formData.append('description', description)
    formData.append('organization_uuid', organizationUuid)
    if (roleUuid) {
        formData.append('role_uuid', roleUuid)
    }

    try {
        const response = await apiClient.post<TrainingFile>(API.knowledge.trainingFiles.list(), formData, {
            headers: {
                'Content-Type': 'multipart/form-data',
            },
        })
        return response.data
    } catch (error) {
        if (isAxiosError(error)) {
            const errorMsg =
                error.response?.data?.error ||
                error.response?.data?.file?.[0] ||
                'Failed to upload file'
            message.error(errorMsg)
        } else {
            message.error('Failed to upload file')
        }
        return null
    }
}

const getTrainingFilesByRole = (roleUuid: string): TrainingFile[] =>
    trainingFiles.value.filter((file) => file.role?.uuid === roleUuid)

const organizationWideTrainingFiles = computed(() =>
    trainingFiles.value.filter((file) => !file.role?.uuid),
)

const deleteTrainingFile = async (uuid: string, fileName: string) => {
    Modal.confirm({
        title: 'Delete File',
        content: `Are you sure you want to delete "${fileName}"? This action cannot be undone.`,
        okText: 'Delete',
        okType: 'danger',
        cancelText: 'Cancel',
        onOk: async () => {
            try {
                await apiClient.delete(API.knowledge.trainingFiles.byId(uuid))
                message.success('File deleted successfully')
                trainingFiles.value = trainingFiles.value.filter((file) => file.uuid !== uuid)
            } catch (error) {
                console.error('Failed to delete file:', error)
                message.error('Failed to delete file')
            }
        },
    })
}

const retryIngestion = async (uuid: string) => {
    try {
        const response = await apiClient.post<TrainingFile>(API.knowledge.trainingFiles.retry(uuid))
        const idx = trainingFiles.value.findIndex((f) => f.uuid === uuid)
        if (idx !== -1) trainingFiles.value[idx] = response.data
        message.success('Ingestion re-queued')
    } catch (error) {
        console.error('Failed to retry ingestion:', error)
        message.error('Failed to retry ingestion')
    }
}

const canDeleteTrainingFile = (record: TrainingFile): boolean => {
    if (auth.user?.uuid === record.uploaded_by?.uuid) return true
    if (organization.value?.owner?.uuid === auth.user?.uuid) return true
    return members.value.some((member) => member.uuid === auth.user?.uuid && member.is_manager)
}

const formatFileSize = (bytes: number) => {
    if (bytes === 0) return '0 Bytes'
    const k = 1024
    const sizes = ['Bytes', 'KB', 'MB', 'GB']
    const i = Math.floor(Math.log(bytes) / Math.log(k))
    return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i]
}

const trainingFileColumns = [
    {
        title: 'File Name',
        key: 'file_name',
        customRender: ({ record }: { record: TrainingFile }) =>
            h('a', { href: record.file_url, target: '_blank', rel: 'noopener noreferrer' }, record.file_name),
    },
    {
        title: 'Uploaded By',
        key: 'uploaded_by',
        customRender: ({ record }: { record: TrainingFile }) => {
            if (!record.uploaded_by) return '-'
            return `${record.uploaded_by.first_name} ${record.uploaded_by.last_name}`
        },
    },
    {
        title: 'Size',
        dataIndex: 'file_size',
        key: 'file_size',
        customRender: ({ value }: { value: number }) => formatFileSize(value || 0),
    },
    {
        title: 'Scope',
        key: 'role',
        customRender: ({ record }: { record: TrainingFile }) => getScopeLabel(record),
    },
    {
        title: 'Status',
        dataIndex: 'status',
        key: 'status',
        customRender: ({ value }: { value: string }) => {
            const statusMap: Record<string, { color: string; label: string }> = {
                ingesting: { color: 'processing', label: 'Ingesting' },
                chunked: { color: 'blue', label: 'Chunked' },
                embedded: { color: 'success', label: 'Embedded' },
                failed: { color: 'error', label: 'Failed' },
            }
            const status = statusMap[value] || { color: 'default', label: value }
            return h(Tag, { color: status.color }, () => status.label)
        },
    },
    {
        title: 'Uploaded',
        dataIndex: 'created_at',
        key: 'created_at',
        customRender: ({ value }: { value: string }) => new Date(value).toLocaleDateString(),
    },
    {
        title: 'Action',
        key: 'action',
        customRender: ({ record }: { record: TrainingFile }) => {
            const buttons: ReturnType<typeof h>[] = []
            if (record.status === 'failed' && canDeleteTrainingFile(record)) {
                buttons.push(
                    h(
                        Button,
                        {
                            size: 'small',
                            icon: h(ReloadOutlined),
                            onClick: () => retryIngestion(record.uuid),
                        },
                        () => 'Retry',
                    ),
                )
            }
            if (canDeleteTrainingFile(record)) {
                buttons.push(
                    h(
                        Button,
                        {
                            danger: true,
                            size: 'small',
                            icon: h(DeleteOutlined),
                            onClick: () => deleteTrainingFile(record.uuid, record.file_name),
                        },
                        () => 'Delete',
                    ),
                )
            }
            return buttons.length ? h(Space, { size: 'small' }, () => buttons) : null
        },
    },
]


const createRoleForWizard = async (): Promise<Role | null> => {
    const name = createRoleForm.value.name.trim()
    const description = createRoleForm.value.description.trim()

    if (!name) {
        message.error('Role name is required')
        return null
    }

    if (hasDuplicateRoleName(name)) {
        message.error('A role with this name already exists')
        return null
    }

    creatingRoleWizard.value = true
    try {
        const response = await apiClient.post<Role>(API.roles.list(organizationUuid), { name, description })
        message.success('Role created successfully. You can upload training files now.')
        await fetchRoles()

        if (response.data?.uuid) {
            return response.data
        }

        return Roles.value.find((role) => role.name.trim().toLowerCase() === name.toLowerCase()) || null
    } catch (error) {
        console.error('Failed to create role in wizard:', error)
        if (isAxiosError(error)) {
            message.error(error.response?.data?.error || 'Failed to create role')
        } else {
            message.error('Failed to create role')
        }
        return null
    } finally {
        creatingRoleWizard.value = false
    }
}

const handleRoleWizardOk = async () => {
    if (roleWizardStep.value === 0) {
        const role = await createRoleForWizard()
        if (!role) return
        createdRoleForWizard.value = role
        roleWizardStep.value = 1
        return
    }

    closeRoleWizard()
}

const handleRoleWizardFileSelected = (file: File) => {
    if (!validateUploadFile(file)) {
        wizardSelectedFile.value = null
        return
    }
    wizardSelectedFile.value = file
}

const uploadFileFromWizard = async () => {
    const roleUuid = createdRoleForWizard.value?.uuid
    if (!roleUuid) {
        message.error('Role is not available for upload')
        return
    }

    if (!wizardSelectedFile.value) {
        message.error('Please select a file to upload')
        return
    }

    wizardUploading.value = true
    try {
        const uploaded = await uploadTrainingFile(
            roleUuid,
            wizardSelectedFile.value,
            wizardFileDescription.value,
        )
        if (!uploaded) return

        trainingFiles.value.unshift(uploaded)
        wizardUploadedFiles.value.unshift(uploaded)
        message.success(`File "${wizardSelectedFile.value.name}" uploaded successfully`)
        wizardSelectedFile.value = null
        wizardFileDescription.value = ''
    } finally {
        wizardUploading.value = false
    }
}

const openUploadModal = (role?: Role) => {
    uploadRoleUuid.value = role?.uuid || ORGANIZATION_WIDE_SCOPE
    uploadSelectedFile.value = null
    uploadFileDescription.value = ''
    uploadModalVisible.value = true
}

const handleUploadModalFileSelected = (file: File) => {
    if (!validateUploadFile(file)) {
        uploadSelectedFile.value = null
        return
    }
    uploadSelectedFile.value = file
}

const handleUploadModalOk = async () => {
    if (!uploadSelectedFile.value) {
        message.error('Please select a file to upload')
        return
    }

    const selectedRoleUuid =
        uploadRoleUuid.value === ORGANIZATION_WIDE_SCOPE ? null : uploadRoleUuid.value

    uploadingFile.value = true
    try {
        const uploaded = await uploadTrainingFile(
            selectedRoleUuid,
            uploadSelectedFile.value,
            uploadFileDescription.value,
        )
        if (!uploaded) return

        trainingFiles.value.unshift(uploaded)
        message.success(`File "${uploadSelectedFile.value.name}" uploaded successfully`)
        uploadModalVisible.value = false
        uploadSelectedFile.value = null
        uploadFileDescription.value = ''
    } finally {
        uploadingFile.value = false
    }
}

const deleteRole = async (role: Role) => {
    Modal.confirm({
        title: 'Delete role',
        content: `Are you sure you want to delete "${role.name}"?`,
        okText: 'Delete',
        okType: 'danger',
        cancelText: 'Cancel',
        onOk: async () => {
            deletingRoleUuid.value = role.uuid
            try {
                await apiClient.delete(API.roles.remove(organizationUuid, role.uuid))
                message.success('Role deleted successfully')
                await fetchRoles()
            } catch (error) {
                console.error('Failed to delete role:', error)
                if (isAxiosError(error)) {
                    message.error(error.response?.data?.error || 'Failed to delete role')
                } else {
                    message.error('Failed to delete role')
                }
            } finally {
                deletingRoleUuid.value = null
            }
        },
    })
}

const openRoleMembersModal = (role: Role) => {
    selectedRoleForMembers.value = role
    selectedRoleMembers.value = Array.isArray(role.members) ? role.members : []
    roleMembersModalVisible.value = true
}

const createInvite = async () => {
    try {
        const response = await apiClient.post<InviteToken>(
            API.invites.create(organizationUuid, newInviteMaxUses.value),
        )
        newInviteUrl.value = response.data.invite_url
        inviteModalVisible.value = true
        fetchInvites()
    } catch (error) {
        console.error('Failed to create invite:', error)
        message.error('Failed to create invite')
    }
}

const fallbackCopyText = (text: string): boolean => {
    const textarea = document.createElement('textarea')
    textarea.value = text
    textarea.setAttribute('readonly', 'true')
    textarea.style.position = 'fixed'
    textarea.style.opacity = '0'
    textarea.style.pointerEvents = 'none'
    document.body.appendChild(textarea)
    textarea.focus()
    textarea.select()

    const copied = document.execCommand('copy')
    document.body.removeChild(textarea)
    return copied
}

const copyToClipboard = async (text: string): Promise<boolean> => {
    const safeText = String(text || '').trim()
    if (!safeText) return false

    if (window.isSecureContext && window.navigator.clipboard?.writeText) {
        try {
            await window.navigator.clipboard.writeText(safeText)
            return true
        } catch {
            // Fall through to legacy copy for restricted browser contexts.
        }
    }

    return fallbackCopyText(safeText)
}

const copyInviteUrl = async () => {
    const copied = await copyToClipboard(newInviteUrl.value)
    if (copied) {
        message.success('Invite URL copied to clipboard')
        return
    }
    message.error('Could not copy invite URL. Please copy it manually.')
}

const copyUrl = async (url: string) => {
    const copied = await copyToClipboard(url)
    if (copied) {
        message.success('Copied to clipboard')
        return
    }
    message.error('Could not copy URL. Please copy it manually.')
}

const revokeInvite = async (inviteUuid: string) => {
    try {
        await apiClient.delete(API.invites.revoke(organizationUuid, inviteUuid))
        message.success('Invite revoked')
        fetchInvites()
    } catch (error) {
        console.error('Failed to revoke invite:', error)
        message.error('Failed to revoke invite')
    }
}

const removeMember = async (userUuid: string) => {
    try {
        await apiClient.post(API.organization.members.remove(organizationUuid, userUuid))
        message.success('Member removed')
        fetchMembers()
    } catch (error) {
        console.error('Failed to remove member:', error)
        if (isAxiosError(error)) {
            message.error(error.response?.data?.error || 'Failed to remove member')
        }
    }
}

const saveDescription = async () => {
    try {
        await apiClient.patch(API.organization.byId(organizationUuid), {
            description: newDescription.value,
        })
        message.success('Description updated')
        editingDescription.value = false
        fetchOrganization()
    } catch (error) {
        console.error('Failed to update description:', error)
        message.error('Failed to update description')
    }
}

onMounted(async () => {
    await fetchOrganization()
    await fetchMembers()
    await fetchInvites()
    await fetchRoles()
    await fetchTrainingFiles()

    const currentUserUuid = auth.user?.uuid
    const isOwner = organization.value?.owner?.uuid === currentUserUuid
    const myMembership = members.value.find((member) => member.uuid === currentUserUuid)
    const isEmployer = myMembership?.is_manager

    if (!isOwner && !isEmployer) {
        message.error('You do not have permission to manage this organization')
        router.replace(`/organization/${organizationUuid}`)
    }
})
</script>

<template>
    <div class="page">
        <Spin :spinning="loading" tip="Loading organization...">
            <Card v-if="organization" class="panel" :bordered="false">
                <div class="header">
                    <Typography.Title :level="2">Manage {{ organization.name }}</Typography.Title>
                    <Button type="default" @click="router.push(`/organization/${organizationUuid}`)">
                        Back to Organization
                    </Button>
                </div>

                <Tabs>
                    <Tabs.TabPane key="details" tab="Details">
                        <div class="section">
                            <Typography.Title :level="4" style="color: #1f2937 !important">
                                Description
                            </Typography.Title>
                            <div v-if="!editingDescription">
                                <Typography.Paragraph>
                                    {{ organization.description || 'No description provided' }}
                                </Typography.Paragraph>
                                <Button @click="editingDescription = true" size="small">
                                    Edit Description
                                </Button>
                            </div>
                            <div v-else>
                                <Input.TextArea
                                    v-model:value="newDescription"
                                    :rows="4"
                                    placeholder="Enter organization description"
                                />
                                <Space style="margin-top: 0.5rem">
                                    <Button type="primary" @click="saveDescription">Save</Button>
                                    <Button @click="editingDescription = false">Cancel</Button>
                                </Space>
                            </div>
                        </div>
                    </Tabs.TabPane>

                    <Tabs.TabPane key="members" tab="Members">
                        <div class="section">
                            <div class="section-header">
                                <Typography.Title :level="4" style="color: #1f2937 !important">
                                    Members ({{ filteredMembers.length }})
                                </Typography.Title>
                                <Input
                                    v-model:value="memberSearch"
                                    allow-clear
                                    class="search-input"
                                    placeholder="Search members by name"
                                    style="max-width: 280px"
                                />
                            </div>

                            <List
                                v-if="filteredMembers.length > 0"
                                :data-source="filteredMembers"
                                :bordered="false"
                            >
                                <template #renderItem="{ item }">
                                    <List.Item class="member-item">
                                        <List.Item.Meta
                                            :title="`${item.first_name} ${item.last_name}`"
                                            :description="item.email_address"
                                        />
                                        <Space>
                                            <Tag v-if="item.uuid === organization.owner.uuid" color="blue">
                                                Owner
                                            </Tag>
                                            <Tag v-else :color="item.is_manager ? 'purple' : 'default'">
                                                {{ item.is_manager ? 'Manager' : 'Member' }}
                                            </Tag>
                                            <Button
                                                v-if="item.uuid !== organization.owner.uuid"
                                                danger
                                                size="small"
                                                @click="removeMember(item.uuid)"
                                            >
                                                Remove
                                            </Button>
                                        </Space>
                                    </List.Item>
                                </template>
                            </List>
                            <Typography.Paragraph v-else type="secondary">
                                {{ memberEmptyMessage }}
                            </Typography.Paragraph>
                        </div>
                    </Tabs.TabPane>

                    <Tabs.TabPane key="invites" tab="Invites">
                        <div class="section">
                            <div class="section-header">
                                <Typography.Title :level="4" style="color: #1f2937 !important">
                                    Invite Tokens
                                </Typography.Title>
                                <Space>
                                    <InputNumber v-model:value="newInviteMaxUses" :min="1" />
                                    <Button type="primary" @click="createInvite">
                                        Create Invite
                                    </Button>
                                </Space>
                            </div>

                            <List
                                v-if="invites.length > 0"
                                :data-source="invites"
                                :bordered="false"
                            >
                                <template #renderItem="{ item }">
                                    <List.Item class="invite-item">
                                        <List.Item.Meta
                                            :title="`Created by ${item.created_by.first_name} ${item.created_by.last_name}`"
                                            :description="`Expires: ${new Date(item.expires_at).toLocaleDateString()}`"
                                        />
                                        <Space>
                                            <Tag :color="item.is_valid ? 'green' : 'red'">
                                                {{ item.is_valid ? 'Valid' : 'Expired' }}
                                            </Tag>
                                            <Tag class="white-tag">
                                                Uses: {{ item.uses || 0 }} /
                                                {{ item.max_uses || 1 }}
                                            </Tag>
                                            <Button size="small" @click="copyUrl(item.invite_url)">
                                                Copy URL
                                            </Button>
                                            <Button
                                                danger
                                                size="small"
                                                @click="revokeInvite(item.uuid)"
                                            >
                                                Revoke
                                            </Button>
                                        </Space>
                                    </List.Item>
                                </template>
                            </List>
                            <Typography.Paragraph v-else type="secondary">
                                No active invites. Create one to invite new members.
                            </Typography.Paragraph>
                        </div>
                    </Tabs.TabPane>

                    <Tabs.TabPane key="Roles" tab="Roles">
                        <div class="section">
                            <div class="section-header">
                                <Typography.Title :level="4" style="color: #1f2937 !important">
                                    Roles ({{ filteredRoles.length }})
                                </Typography.Title>
                                <Space>
                                    <Input
                                        v-model:value="roleSearch"
                                        allow-clear
                                        class="search-input"
                                        placeholder="Search roles by name or description"
                                        style="width: 300px"
                                    />
                                    <Button @click="openUploadModal()">
                                        Upload Training File
                                    </Button>
                                    <Button type="primary" @click="openRoleWizard">
                                        Create Role
                                    </Button>
                                </Space>
                            </div>

                            <List
                                v-if="filteredRoles.length > 0"
                                :data-source="filteredRoles"
                                :bordered="false"
                            >
                                <template #renderItem="{ item }">
                                    <List.Item class="Role-item">
                                        <div class="role-content">
                                            <div class="role-head">
                                                <List.Item.Meta
                                                    :title="item.name"
                                                    :description="item.description || 'No description'"
                                                />
                                                <Space>
                                                    <Tag>{{ item.member_count }} members</Tag>
                                                    <Tag color="blue">{{ getTrainingFilesByRole(item.uuid).length }} files</Tag>
                                                    <Button size="small" @click="openUploadModal(item)">
                                                        Upload Files
                                                    </Button>
                                                    <Button size="small" @click="openRoleMembersModal(item)">
                                                        View Members
                                                    </Button>
                                                    <Button
                                                        danger
                                                        size="small"
                                                        :loading="deletingRoleUuid === item.uuid"
                                                        @click="deleteRole(item)"
                                                    >
                                                        Delete
                                                    </Button>
                                                </Space>
                                            </div>

                                            <div class="role-files">
                                                <Typography.Text strong>Training files for this role</Typography.Text>
                                                <List
                                                    v-if="getTrainingFilesByRole(item.uuid).length > 0"
                                                    :data-source="getTrainingFilesByRole(item.uuid)"
                                                    size="small"
                                                    :bordered="false"
                                                >
                                                    <template #renderItem="{ item: file }">
                                                        <List.Item>
                                                            <Space style="display: flex; justify-content: space-between; width: 100%">
                                                                <Typography.Text>{{ file.file_name }}</Typography.Text>
                                                                <Tag>{{ formatFileSize(file.file_size || 0) }}</Tag>
                                                            </Space>
                                                        </List.Item>
                                                    </template>
                                                </List>
                                                <Typography.Paragraph v-else type="secondary" style="margin: 0.5rem 0 0">
                                                    No training files uploaded for this role yet.
                                                </Typography.Paragraph>
                                            </div>
                                        </div>
                                    </List.Item>
                                </template>
                            </List>
                            <div v-if="organizationWideTrainingFiles.length > 0" class="role-files" style="margin-top: 1rem">
                                <Typography.Text strong>
                                    Organization-wide training files (applies to all roles)
                                </Typography.Text>
                                <List
                                    :data-source="organizationWideTrainingFiles"
                                    size="small"
                                    :bordered="false"
                                >
                                    <template #renderItem="{ item: file }">
                                        <List.Item>
                                            <Space style="display: flex; justify-content: space-between; width: 100%">
                                                <Typography.Text>{{ file.file_name }}</Typography.Text>
                                                <Tag color="geekblue">Organization-wide</Tag>
                                            </Space>
                                        </List.Item>
                                    </template>
                                </List>
                            </div>
                            <Typography.Paragraph
                                v-if="filteredRoles.length === 0 && organizationWideTrainingFiles.length === 0"
                                type="secondary"
                            >
                                {{ roleEmptyMessage }}
                            </Typography.Paragraph>
                        </div>
                    </Tabs.TabPane>

                    <Tabs.TabPane key="files" tab="Files">
                        <div class="section">
                            <div class="section-header">
                                <Typography.Title :level="4" style="color: #1f2937 !important">
                                    Training Files ({{ trainingFiles.length }})
                                </Typography.Title>
                                <Button @click="openUploadModal()">Upload Training File</Button>
                            </div>

                            <Table
                                v-if="trainingFiles.length > 0"
                                :columns="trainingFileColumns"
                                :data-source="trainingFiles"
                                :pagination="{ pageSize: 10 }"
                                :row-key="(record: TrainingFile) => record.uuid"
                                size="small"
                            />
                            <Typography.Paragraph v-else type="secondary">
                                No training files uploaded yet.
                            </Typography.Paragraph>
                        </div>
                    </Tabs.TabPane>
                </Tabs>
            </Card>
        </Spin>

        <Modal
            v-model:open="roleModalVisible"
            :title="roleWizardStep === 0 ? 'Create Role' : 'Upload Training Files'"
            :ok-text="roleWizardStep === 0 ? 'Next' : 'Finish'"
            cancel-text="Cancel"
            :ok-button-props="{ loading: roleWizardStep === 0 ? creatingRoleWizard : false }"
            @ok="handleRoleWizardOk"
            @cancel="closeRoleWizard"
        >
            <Steps :current="roleWizardStep" size="small" style="margin-bottom: 1rem">
                <Steps.Step title="Role Details" />
                <Steps.Step title="Training Files" />
            </Steps>

            <div v-if="roleWizardStep === 0" style="display: flex; flex-direction: column; gap: 0.75rem">
                <Input
                    v-model:value="createRoleForm.name"
                    placeholder="Role name"
                    :maxlength="100"
                    @pressEnter="handleRoleWizardOk"
                />
                <Input.TextArea
                    v-model:value="createRoleForm.description"
                    placeholder="Role description"
                    :rows="4"
                    :maxlength="1000"
                />
            </div>

            <div v-else style="display: flex; flex-direction: column; gap: 0.75rem">
                <Typography.Paragraph type="secondary" style="margin-bottom: 0">
                    Upload optional training files for
                    <strong>{{ createdRoleForWizard?.name }}</strong>
                    . You can also do this later. Use the main Upload Training File modal for
                    organization-wide files.
                </Typography.Paragraph>

                <Input.TextArea
                    v-model:value="wizardFileDescription"
                    placeholder="Optional file description"
                    :rows="2"
                    :maxlength="500"
                />

                <Upload.Dragger
                    accept=".txt,.pdf,.md,.csv,.json,.docx,.doc"
                    :before-upload="
                        (file) => {
                            handleRoleWizardFileSelected(file)
                            return false
                        }
                    "
                    :multiple="false"
                    :auto-upload="false"
                    :file-list="[]"
                >
                    <p class="ant-upload-drag-icon">
                        <InboxOutlined />
                    </p>
                    <p class="ant-upload-text">Click or drag file to this area to select</p>
                    <p class="ant-upload-hint">
                        {{ wizardSelectedFile ? wizardSelectedFile.name : 'Single file upload' }}
                    </p>
                </Upload.Dragger>

                <Button
                    type="primary"
                    :disabled="!wizardSelectedFile"
                    :loading="wizardUploading"
                    @click="uploadFileFromWizard"
                >
                    Upload Selected File
                </Button>

                <div v-if="wizardUploadedFiles.length > 0" class="uploaded-list">
                    <Typography.Text strong>Uploaded in this setup:</Typography.Text>
                    <List :data-source="wizardUploadedFiles" :bordered="false" size="small">
                        <template #renderItem="{ item }">
                            <List.Item>
                                <List.Item.Meta :title="item.file_name" :description="item.role?.name" />
                            </List.Item>
                        </template>
                    </List>
                </div>
            </div>
        </Modal>

        <Modal
            v-model:open="uploadModalVisible"
            title="Upload Training File"
            ok-text="Upload"
            cancel-text="Cancel"
            :ok-button-props="{ loading: uploadingFile, disabled: !uploadSelectedFile }"
            @ok="handleUploadModalOk"
            @cancel="uploadModalVisible = false"
        >
            <div style="display: flex; flex-direction: column; gap: 0.75rem">
                <Typography.Text>
                    Supported formats:
                    <strong>txt, pdf, md, csv, json, docx, doc</strong>
                    (Max 50MB)
                </Typography.Text>

                <div>
                    <Typography.Text strong>Scope</Typography.Text>
                    <Select
                        v-model:value="uploadRoleUuid"
                        placeholder="Select training scope"
                        style="width: 100%"
                        :options="uploadRoleOptions"
                    />
                    <Typography.Paragraph type="secondary" style="margin: 0.5rem 0 0">
                        Organization-wide files apply to every role in this organization.
                    </Typography.Paragraph>
                </div>

                <Input.TextArea
                    v-model:value="uploadFileDescription"
                    placeholder="Optional file description"
                    :rows="2"
                    :maxlength="500"
                />

                <Upload.Dragger
                    accept=".txt,.pdf,.md,.csv,.json,.docx,.doc"
                    :before-upload="
                        (file) => {
                            handleUploadModalFileSelected(file)
                            return false
                        }
                    "
                    :multiple="false"
                    :auto-upload="false"
                    :file-list="[]"
                >
                    <p class="ant-upload-drag-icon">
                        <InboxOutlined />
                    </p>
                    <p class="ant-upload-text">Click or drag file to this area to select</p>
                    <p class="ant-upload-hint">
                        {{ uploadSelectedFile ? uploadSelectedFile.name : 'Single file upload' }}
                    </p>
                </Upload.Dragger>
            </div>
        </Modal>

        <Modal
            v-model:open="inviteModalVisible"
            title="Invite Created"
            @ok="inviteModalVisible = false"
        >
            <div>
                <Typography.Paragraph>
                    Share this URL with people you want to invite:
                </Typography.Paragraph>
                <Input
                    :value="newInviteUrl"
                    readonly
                    @click="copyInviteUrl"
                    style="cursor: pointer"
                />
                <Button type="primary" block style="margin-top: 1rem" @click="copyInviteUrl">
                    Copy to Clipboard
                </Button>
            </div>
        </Modal>

        <Modal
            v-model:open="roleMembersModalVisible"
            :title="`Members in ${selectedRoleForMembers?.name || 'Role'}`"
            :footer="null"
        >
            <List
                v-if="selectedRoleMembers.length > 0"
                :data-source="selectedRoleMembers"
                :bordered="false"
            >
                <template #renderItem="{ item }">
                    <List.Item>
                        <List.Item.Meta
                            :title="`${item.first_name} ${item.last_name}`"
                            :description="item.email_address"
                        />
                        <Tag :color="item.is_manager ? 'purple' : 'default'">
                            {{ item.is_manager ? 'Manager' : 'Member' }}
                        </Tag>
                    </List.Item>
                </template>
            </List>
            <Typography.Paragraph v-else type="secondary">
                No members assigned to this role yet.
            </Typography.Paragraph>
        </Modal>
    </div>
</template>

<style scoped>
.page {
    padding: 1rem;
}

.header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 1rem;
}

.section {
    margin: 2rem 0;
}

.section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 1rem;
}

.role-content {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.role-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
}

.role-files {
    background: #f8fafc;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    padding: 0.75rem;
}

.white-tag {
    background-color: #ffffff !important;
    color: #000000 !important;
}

:deep(.ant-typography),
:deep(.ant-typography p),
:deep(.ant-typography span),
:deep(.ant-typography h4),
:deep(.ant-list-item),
:deep(.ant-list-item-meta-title),
:deep(.ant-list-item-meta-description),
:deep(.ant-tabs-tab),
:deep(.ant-input-number),
:deep(.ant-input-number-input) {
    color: #1f2937 !important;
}

:deep(.ant-typography-secondary) {
    color: #6b7280 !important;
}

:deep(.ant-input-number) {
    background: #ffffff;
    border-color: #d0d8e2;
}

:deep(.search-input) {
    background: #ffffff !important;
    border-color: #d0d8e2 !important;
    color: #1f2937 !important;
}

:deep(.search-input::placeholder) {
    color: #6b7280 !important;
}

:deep(.search-input::selection) {
    background: #dbeafe !important;
    color: #1f2937 !important;
}
</style>
