import { useEffect, useState, forwardRef } from 'react'
import {
  Box,
  Typography,
  Paper,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  CircularProgress,
  Alert,
  Button,
  Drawer,
  TextField,
  Stack,
  IconButton,
  Divider,
  Snackbar,
  Dialog,
  DialogTitle,
  DialogContent,
  DialogActions,
  LinearProgress,
} from '@mui/material'
import MuiAlert, { AlertProps } from '@mui/material/Alert'
import DownloadIcon from '@mui/icons-material/Download'
import UploadIcon from '@mui/icons-material/Upload'
import SettingsIcon from '@mui/icons-material/Settings'
import CloseIcon from '@mui/icons-material/Close'
import { useSettingsStore } from '../stores/settingsStore'

const SnackbarAlert = forwardRef<HTMLDivElement, AlertProps>(function SnackbarAlert(
  props,
  ref,
) {
  return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />
})

interface RegistryImage {
  id: number
  name: string
  upload_time: string
  size: number
}

// Format bytes to human readable format
function formatSize(bytes: number): string {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`
}

// Remove registry address prefix from image name for display
// e.g., "registry.loveuer.com/hub.yizhisec.com/external/busybox:1.37.0" 
//    -> "hub.yizhisec.com/external/busybox:1.37.0"
function getDisplayImageName(fullImageName: string): string {
  const firstSlashIndex = fullImageName.indexOf('/')
  if (firstSlashIndex > 0) {
    // Remove everything before the first slash (registry address)
    return fullImageName.substring(firstSlashIndex + 1)
  }
  // No slash found, return original name
  return fullImageName
}

export default function RegistryImageList() {
  const [images, setImages] = useState<RegistryImage[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [settingsOpen, setSettingsOpen] = useState(false)
  const [uploadOpen, setUploadOpen] = useState(false)
  const [selectedFile, setSelectedFile] = useState<File | null>(null)
  const [uploading, setUploading] = useState(false)
  const [uploadProgress, setUploadProgress] = useState(0)
  const [downloadingImage, setDownloadingImage] = useState<string | null>(null)
  const { 
    registryAddress, 
    loading: configLoading, 
    snackbar, 
    fetchConfig, 
    setRegistryAddress,
    hideSnackbar,
    showSnackbar 
  } = useSettingsStore()
  const [registryAddressInput, setRegistryAddressInput] = useState(registryAddress)
  const [saving, setSaving] = useState(false)

  useEffect(() => {
    let abort = false
    async function fetchImages() {
      setLoading(true)
      setError(null)
      try {
        const res = await fetch('/api/v1/registry/image/list')
        if (!res.ok) throw new Error(`HTTP ${res.status}`)
        const result = await res.json()
        // Backend returns: {status, msg, data: {images: [...]}}
        const list: RegistryImage[] = result.data?.images || []
        if (!abort) setImages(list)
      } catch (e: any) {
        if (!abort) setError(e.message)
      } finally {
        if (!abort) setLoading(false)
      }
    }
    fetchImages()
    return () => { abort = true }
  }, [])

  const handleDownload = async (imageName: string) => {
    setDownloadingImage(imageName)
    showSnackbar('正在准备下载，请稍候...', 'info')
    
    try {
      // Use the image name directly as it's already the full repository name from database
      // The imageName already contains the full path like: registry.loveuer.com/hub.yizhisec.com/external/busybox:1.37.0
      // We should NOT modify it based on registry_address setting
      const fullImageName = imageName
      
      showSnackbar('正在连接服务器...', 'info')
      const url = `/api/v1/registry/image/download/${encodeURIComponent(fullImageName)}`
      const response = await fetch(url)
      if (!response.ok) {
        throw new Error(`下载失败: ${response.statusText}`)
      }
      
      showSnackbar('正在接收数据，请稍候...', 'info')
      
      // Get filename from Content-Disposition header or use default
      const contentDisposition = response.headers.get('Content-Disposition')
      let filename = `${imageName.replace(/\//g, '_')}-latest.tar`
      if (contentDisposition) {
        const filenameMatch = contentDisposition.match(/filename="?(.+)"?/i)
        if (filenameMatch) {
          filename = filenameMatch[1]
        }
      }
      
      // Create blob and download
      const blob = await response.blob()
      const downloadUrl = window.URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = downloadUrl
      link.download = filename
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      window.URL.revokeObjectURL(downloadUrl)
      
      showSnackbar('下载完成！', 'success')
    } catch (error: unknown) {
      const err = error as Error
      showSnackbar(`下载失败: ${err.message}`, 'error')
    } finally {
      setDownloadingImage(null)
    }
  }

  const handleSaveSettings = async () => {
    try {
      setSaving(true)
      await setRegistryAddress(registryAddressInput)
      setSettingsOpen(false)
    } catch (error: any) {
      // Error already handled in store
    } finally {
      setSaving(false)
    }
  }

  const handleCloseSettings = () => {
    setRegistryAddressInput(registryAddress)
    setSettingsOpen(false)
  }

  useEffect(() => {
    setRegistryAddressInput(registryAddress)
  }, [registryAddress])

  useEffect(() => {
    fetchConfig()
  }, [fetchConfig])

  const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0]
    if (file && file.name.endsWith('.tar')) {
      setSelectedFile(file)
    } else {
      showSnackbar('请选择 .tar 文件', 'error')
    }
  }

  const handleUpload = async () => {
    if (!selectedFile) {
      showSnackbar('请先选择文件', 'warning')
      return
    }

    setUploading(true)
    setUploadProgress(0)

    try {
      const formData = new FormData()
      formData.append('file', selectedFile)

      const xhr = new XMLHttpRequest()

      xhr.upload.addEventListener('progress', (e) => {
        if (e.lengthComputable) {
          const percentComplete = (e.loaded / e.total) * 100
          setUploadProgress(percentComplete)
        }
      })

      xhr.addEventListener('load', () => {
        if (xhr.status === 200) {
          const result = JSON.parse(xhr.responseText)
          showSnackbar(`上传成功: ${result.data?.repository || ''}`, 'success')
          setUploadOpen(false)
          setSelectedFile(null)
          setUploadProgress(0)
          window.location.reload()
        } else {
          const result = JSON.parse(xhr.responseText)
          showSnackbar(`上传失败: ${result.msg || xhr.statusText}`, 'error')
        }
        setUploading(false)
      })

      xhr.addEventListener('error', () => {
        showSnackbar('上传失败: 网络错误', 'error')
        setUploading(false)
      })

      xhr.open('POST', '/api/v1/registry/image/upload')
      xhr.send(formData)
    } catch (error: unknown) {
      const err = error as Error
      showSnackbar(`上传失败: ${err.message}`, 'error')
      setUploading(false)
    }
  }

  const handleCloseUpload = () => {
    if (!uploading) {
      setUploadOpen(false)
      setSelectedFile(null)
      setUploadProgress(0)
    }
  }

  return (
    <Box>
      <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
        <Typography variant="h5">镜像列表</Typography>
        <Stack direction="row" spacing={2}>
          <Button
            variant="contained"
            startIcon={<UploadIcon />}
            onClick={() => setUploadOpen(true)}
          >
            上传镜像
          </Button>
          <Button
            variant="outlined"
            startIcon={<SettingsIcon />}
            onClick={() => setSettingsOpen(true)}
          >
            设置
          </Button>
        </Stack>
      </Box>
      {loading && <CircularProgress />}
      {error && <Alert severity="error">加载失败: {error}</Alert>}
      {!loading && !error && (
        <Paper>
          <TableContainer>
            <Table size="small">
              <TableHead>
                <TableRow>
                  <TableCell>ID</TableCell>
                  <TableCell>名称</TableCell>
                  <TableCell>上传时间</TableCell>
                  <TableCell>大小</TableCell>
                  <TableCell>操作</TableCell>
                </TableRow>
              </TableHead>
              <TableBody>
                {images.map(img => (
                  <TableRow key={img.id} hover>
                    <TableCell>{img.id}</TableCell>
                    <TableCell>{getDisplayImageName(img.name)}</TableCell>
                    <TableCell>{img.upload_time}</TableCell>
                    <TableCell>{formatSize(img.size)}</TableCell>
                    <TableCell>
                      <Button
                        variant="outlined"
                        size="small"
                        startIcon={downloadingImage === img.name ? <CircularProgress size={16} /> : <DownloadIcon />}
                        onClick={() => handleDownload(img.name)}
                        disabled={downloadingImage === img.name}
                      >
                        {downloadingImage === img.name ? '下载中...' : '下载'}
                      </Button>
                    </TableCell>
                  </TableRow>
                ))}
                {images.length === 0 && (
                  <TableRow>
                    <TableCell colSpan={5} align="center">暂无镜像</TableCell>
                  </TableRow>
                )}
              </TableBody>
            </Table>
          </TableContainer>
        </Paper>
      )}

      {/* Upload Dialog */}
      <Dialog open={uploadOpen} onClose={handleCloseUpload} maxWidth="sm" fullWidth>
        <DialogTitle>上传镜像文件</DialogTitle>
        <DialogContent>
          <Stack spacing={3} sx={{ mt: 2 }}>
            <Alert severity="info">
              请上传 Docker 镜像 tar 文件（使用 docker save 导出的文件）
            </Alert>
            <Button
              variant="outlined"
              component="label"
              fullWidth
              disabled={uploading}
            >
              选择文件
              <input
                type="file"
                accept=".tar"
                hidden
                onChange={handleFileSelect}
              />
            </Button>
            {selectedFile && (
              <Typography variant="body2" color="text.secondary">
                已选择: {selectedFile.name} ({formatSize(selectedFile.size)})
              </Typography>
            )}
            {uploading && (
              <Box>
                <LinearProgress variant="determinate" value={uploadProgress} />
                <Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>
                  上传中: {uploadProgress.toFixed(0)}%
                </Typography>
              </Box>
            )}
          </Stack>
        </DialogContent>
        <DialogActions>
          <Button onClick={handleCloseUpload} disabled={uploading}>
            取消
          </Button>
          <Button 
            onClick={handleUpload} 
            variant="contained" 
            disabled={!selectedFile || uploading}
          >
            {uploading ? '上传中...' : '开始上传'}
          </Button>
        </DialogActions>
      </Dialog>

      {/* Settings Drawer */}
      <Drawer
        anchor="right"
        open={settingsOpen}
        onClose={handleCloseSettings}
        PaperProps={{
          sx: { width: 400, p: 3 }
        }}
      >
        <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
          <Typography variant="h6">镜像设置</Typography>
          <IconButton onClick={handleCloseSettings}>
            <CloseIcon />
          </IconButton>
        </Box>
        <Divider sx={{ mb: 3 }} />
        
        <Stack spacing={3}>
          <TextField
            label="Registry Address"
            placeholder="例如: my-registry.com"
            value={registryAddressInput}
            onChange={(e) => setRegistryAddressInput(e.target.value)}
            fullWidth
            helperText="设置的 registry address 会作用于下载的镜像名称"
            variant="outlined"
            disabled={configLoading || saving}
          />
          
          <Box sx={{ display: 'flex', gap: 2, justifyContent: 'flex-end' }}>
            <Button variant="outlined" onClick={handleCloseSettings} disabled={saving}>
              取消
            </Button>
            <Button variant="contained" onClick={handleSaveSettings} disabled={saving || configLoading}>
              {saving ? '保存中...' : '保存'}
            </Button>
          </Box>
        </Stack>
      </Drawer>

      {/* Snackbar for notifications */}
      <Snackbar
        open={snackbar.open}
        autoHideDuration={3000}
        onClose={hideSnackbar}
        anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
      >
        <SnackbarAlert onClose={hideSnackbar} severity={snackbar.severity}>
          {snackbar.message}
        </SnackbarAlert>
      </Snackbar>
    </Box>
  )
}
