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

const router = useRouter()
const route = useRoute()
const organizationUuid = route.params.organizationUuid as string

const organization = ref<Organization | null>(null)
const roles = ref<Role[]>([])
const members = ref<Array<{ uuid: string; is_manager?: boolean }>>([])
const trainingFiles = ref<TrainingFile[]>([])
const loading = ref(false)
const uploading = ref(false)
const showUploadModal = ref(false)
const auth = useUserStore()

const isManager = computed(() => {
    if (!auth.user || !organization.value) return false
    if ((organization.value as Organization & { is_manager?: boolean }).is_manager === true)
        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 fetchOrganization = async () => {
    loading.value = true
    try {
        const response = await apiClient.get<Organization>(API.organization.byId(organizationUuid))
        organization.value = response.data
    } catch (error) {
        console.error('Failed to fetch organization:', error)
        message.error('Failed to load organization details')
    } finally {
        loading.value = false
    }
}

const fetchRoles = async () => {
    if (!organization.value?.uuid) return
    try {
        const response = await apiClient.get<Role[]>(API.organization.roles.list(organization.value.uuid))
        roles.value = response.data
    } catch (error) {
        console.error('Failed to fetch roles:', error)
    }
}

const fetchUserRoleMemberships = async () => {
    if (!organization.value?.uuid) return
    try {
        const response = await apiClient.get<Role[]>(API.organization.roles.mine())
        const mine = Array.isArray(response.data) ? response.data : []
        const orgUuid = organization.value.uuid
        const joinedRoles = mine.filter((role) => role.organization?.uuid === orgUuid)
        auth.setJoinedRoles(joinedRoles)
    } catch (err) {
        console.error('Failed to fetch user role memberships', err)
    }
}

const isRoleJoined = (roleUuid: string | undefined) => {
    if (!roleUuid) return false
    return auth.userJoinedRoles.some((role) => role.uuid === roleUuid)
}

const fetchMembers = async () => {
    if (!organization.value?.uuid) return
    try {
        const response = await apiClient.get<Array<{ uuid: string; is_manager?: boolean }>>(
            API.organization.members.list(organization.value.uuid),
        )
        members.value = response.data
    } catch (error) {
        console.error('Failed to fetch members:', error)
    }
}

const selectRole = async (roleUuid: string) => {
    if (!organization.value?.uuid) {
        message.error('Organization not loaded')
        return
    }
    if (!auth.user?.uuid) {
        try {
            await auth.fetchSession(true)
        } catch {
            message.error('You must be signed in to join a role')
            return
        }
    }
    if (auth.userJoinedRoles.some((role) => role.uuid === roleUuid)) {
        message.info('You are already a member of this role')
        return
    }

    try {
        await apiClient.post(API.organization.roles.join(organization.value.uuid, roleUuid))
        message.success('Successfully joined role')
        if (!auth.userJoinedRoles.some((role) => role.uuid === roleUuid)) {
            auth.setJoinedRoles([
                ...auth.userJoinedRoles,
                roles.value.find((role) => role.uuid === roleUuid)!,
            ])
        }
    } catch (error) {
        console.error('Failed to join role:', error)
        if (isAxiosError(error)) {
            message.error(error.response?.data?.error || 'Failed to join role')
        }
    }
}

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

const beforeUpload = (file: File) => {
    const allowedExtensions = ['txt', 'pdf', 'md', 'csv', 'json', 'docx', 'doc']
    const fileExtension = file.name.split('.').pop()?.toLowerCase()

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

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

    return false
}

const selectedFile = ref<File | null>(null)
const fileDescription = ref('')
const selectedRoleUuid = ref<string>('')

const handleOpenUploadModal = () => {
    if (!isManager.value) {
        message.error('Only managers can upload training files')
        return
    }

    if (roles.value.length === 0) {
        message.error('No roles found for this organization. Create a role first in Manage Organization.')
        return
    }

    showUploadModal.value = true
}

const handleFileSelected = (file: File) => {
    selectedFile.value = file
}

const handleFileUploadClick = async () => {
    if (!selectedFile.value) {
        message.error('Please select a file to upload')
        return
    }
    if (!selectedRoleUuid.value) {
        message.error('Please select a role for this training file')
        return
    }

    await handleFileUpload(selectedFile.value, fileDescription.value)
    selectedFile.value = null
    fileDescription.value = ''
    selectedRoleUuid.value = ''
}

const handleFileUpload = async (file: File, description: string = '') => {
    if (!organization.value?.uuid) {
        message.error('Organization not loaded')
        return
    }

    uploading.value = true
    try {
        const formData = new FormData()
        formData.append('file', file)
        formData.append('file_name', file.name)
        formData.append('description', description)
        if (selectedRoleUuid.value) {
            formData.append('role', selectedRoleUuid.value)
        }

        const response = await apiClient.post<TrainingFile>(
            API.knowledge.trainingFiles.list(),
            formData,
            {
                headers: {
                    'Content-Type': 'multipart/form-data',
                },
            },
        )

        message.success(`File "${file.name}" uploaded successfully`)
        trainingFiles.value.unshift(response.data)
        showUploadModal.value = false
    } catch (error) {
        console.error('Failed to upload file:', 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')
        }
    } finally {
        uploading.value = false
    }
}

const deleteFile = async (uuid: string, fileName: string) => {
    if (!organization.value?.uuid) {
        message.error('Organization not loaded')
        return
    }

    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((f) => f.uuid !== uuid)
            } catch (error) {
                console.error('Failed to delete file:', error)
                message.error('Failed to delete file')
            }
        },
    })
}

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',
        dataIndex: 'file_name',
        key: 'file_name',
    },
    {
        title: 'Uploaded By',
        key: 'uploaded_by',
        customRender: ({ record }: { record: TrainingFile }) => {
            if (!record.uploaded_by) return '-'
            const full_name = `${record.uploaded_by.first_name} ${record.uploaded_by.last_name}`
            return full_name
        },
    },
    {
        title: 'Size',
        dataIndex: 'file_size',
        key: 'file_size',
        customRender: ({ value }: { value: number }) => formatFileSize(value || 0),
    },
    {
        title: 'Role',
        key: 'role',
        customRender: ({ record }: { record: TrainingFile }) => record.role?.name || '-',
    },
    {
        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 }) => {
            if (isManager.value || auth.user?.uuid === record.uploaded_by?.uuid) {
                return h(
                    Button,
                    {
                        danger: true,
                        size: 'small',
                        icon: h(DeleteOutlined),
                        onClick: () => deleteFile(record.uuid, record.file_name),
                    },
                    () => 'Delete',
                )
            }
            return null
        },
    },
]

onMounted(async () => {
    await auth.fetchSession(true)
    await fetchOrganization()
    await fetchMembers()
    await fetchRoles()
    await fetchUserRoleMemberships()
    await fetchTrainingFiles()
})
</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">{{ organization.name }}</Typography.Title>
                    <Button
                        v-if="isManager"
                        type="primary"
                        @click="router.push(`/organization/${organization.uuid}/manage`)"
                    >
                        Manage Organization
                    </Button>
                </div>

                <Typography.Paragraph v-if="organization.description">
                    {{ organization.description }}
                </Typography.Paragraph>
                <Typography.Paragraph v-else type="secondary">
                    No description provided
                </Typography.Paragraph>

                <Space direction="vertical" :size="4" style="margin: 1rem 0">
                    <div>
                        <Typography.Text strong>Owner:</Typography.Text>
                        {{ organization.owner?.first_name }} {{ organization.owner?.last_name }}
                    </div>
                    <div>
                        <Typography.Text strong>Members:</Typography.Text>
                        {{ organization.member_count ?? 0 }}
                    </div>
                    <div>
                        <Typography.Text strong>Roles:</Typography.Text>
                        {{ organization.role_count ?? 0 }}
                    </div>
                </Space>

                <Divider />

                <Typography.Title :level="4" class="section-title">Training Files</Typography.Title>

                <div style="margin-bottom: 1rem">
                    <Button
                        type="primary"
                        :disabled="!isManager"
                        @click="handleOpenUploadModal"
                        style="margin-bottom: 1rem"
                    >
                        Upload Training File
                    </Button>
                    <Typography.Paragraph
                        v-if="isManager && roles.length === 0"
                        type="secondary"
                        style="margin: 0.25rem 0 0"
                    >
                        Create a role in Manage Organization before uploading training files.
                    </Typography.Paragraph>
                </div>

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

                <Divider />

                <Typography.Title :level="4" class="section-title">
                    Available Roles
                </Typography.Title>

                <div v-if="roles.length > 0">
                    <List :data-source="roles" :bordered="false">
                        <template #renderItem="{ item }">
                            <List.Item class="role-item">
                                <List.Item.Meta :title="item.name" />
                                <Space>
                                    <Tag color="cyan">{{ item.member_count ?? 0 }} members</Tag>
                                    <Button
                                        type="default"
                                        size="small"
                                        @click="router.push(`/onboarding/${item.uuid}`)"
                                    >
                                        Start Onboarding
                                    </Button>
                                    <Button
                                        v-if="item.uuid && !isRoleJoined(item.uuid)"
                                        type="primary"
                                        size="small"
                                        :disabled="isManager"
                                        @click="selectRole(item.uuid)"
                                    >
                                        Join Role
                                    </Button>
                                    <Button v-else size="small" disabled>Joined</Button>
                                </Space>
                            </List.Item>
                        </template>
                    </List>
                </div>
                <Typography.Paragraph v-else type="secondary">
                    No roles available in this organization.
                </Typography.Paragraph>
            </Card>
        </Spin>

        <Modal
            v-model:open="showUploadModal"
            title="Upload Training File"
            width="600px"
            ok-text="Upload"
            cancel-text="Cancel"
            :ok-button-props="{ loading: uploading, disabled: !selectedFile || !selectedRoleUuid }"
            @ok="handleFileUploadClick"
            @cancel="showUploadModal = false"
        >
            <div style="display: flex; flex-direction: column; gap: 1rem">
                <Typography.Text>
                    Supported formats:
                    <strong>txt, pdf, md, csv, json, docx, doc</strong>
                    (Max 50MB)
                </Typography.Text>
                <div>
                    <Typography.Text strong>Role</Typography.Text>
                    <Select
                        v-model:value="selectedRoleUuid"
                        placeholder="Select a role"
                        style="width: 100%"
                        :options="roles.map((role) => ({ label: role.name, value: role.uuid }))"
                    />
                </div>
                <Upload.Dragger
                    accept=".txt,.pdf,.md,.csv,.json,.docx,.doc"
                    :before-upload="
                        (file) => {
                            beforeUpload(file)
                            handleFileSelected(file)
                            return false
                        }
                    "
                    :multiple="false"
                    :auto-upload="false"
                >
                    <p class="ant-upload-drag-icon">
                        <InboxOutlined />
                    </p>
                    <p class="ant-upload-text">Click or drag file to this area to upload</p>
                    <p class="ant-upload-hint">
                        {{ selectedFile ? selectedFile.name : 'Single file upload' }}
                    </p>
                </Upload.Dragger>
            </div>
        </Modal>
    </div>
</template>

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

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

.section-title {
    margin-top: 1.5rem !important;
    margin-bottom: 1rem !important;
}

.role-item :deep(.ant-list-item-meta-title),
.role-item :deep(.ant-list-item-meta-description) {
    background: #0f172a;
    border: 1px solid #1f2937;
    color: #e5e7eb;
}
</style>
