import { useEffect, useMemo, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { AlertCircle, Download, LoaderCircle, Trash2, Upload } from 'lucide-react';
import { toast } from 'sonner';
import { PageHeader } from '@/components/shared/PageHeader';
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { createUniqueBatchId } from '@/lib/batchId';
import { formatDate } from '@/lib/dateUtils';
import { describeSourceFileExtractionStatus } from '@/lib/sourceFileExtractionStatus';
import { formatFileSize } from '@/lib/sourceFileUtils';
import { isSupabaseConfigured, sourceFilesBucket } from '@/lib/supabase';
import { batchIdExists, createSourceFileDownloadUrl, deleteSourceFileById, listSourceFiles, uploadSourceFile } from '@/services/sourceFileService';
import { SourceFileRecord } from '@/types';
import { useAuth } from '@/hooks/useAuth';

const SOURCE_FILES_QUERY_KEY = ['source-files'];
const MAX_FILE_SIZE_BYTES = 20 * 1024 * 1024;
const ACCEPTED_EXTENSIONS = '.pdf,.xlsx,.xls,.doc,.docx,.png,.jpg,.jpeg,.gif,.bmp,.webp';

function renderUploadError(error: unknown) {
  if (error instanceof Error) return error.message;
  if (error && typeof error === 'object' && 'message' in error && typeof (error as { message: unknown }).message === 'string') {
    return (error as { message: string }).message;
  }
  return '上传失败，请检查 Supabase bucket、表和策略配置。';
}

export default function FileUploads() {
  const { user } = useAuth();
  const queryClient = useQueryClient();
  const [batchId, setBatchId] = useState('');
  const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
  const [batchFilter, setBatchFilter] = useState('');
  const [pendingDeleteRecord, setPendingDeleteRecord] = useState<SourceFileRecord | null>(null);
  const uploadedBy = user?.displayName?.trim() || user?.username?.trim() || user?.email?.trim() || '当前用户';

  useEffect(() => {
    if (!isSupabaseConfigured() || batchId.trim()) {
      return;
    }

    void createUniqueBatchId(batchIdExists)
      .then(nextBatchId => setBatchId(nextBatchId))
      .catch(() => {
        setBatchId('');
      });
  }, [batchId]);

  const filesQuery = useQuery({
    queryKey: [...SOURCE_FILES_QUERY_KEY, batchFilter],
    queryFn: () => listSourceFiles(batchFilter || undefined),
    enabled: isSupabaseConfigured(),
  });

  const uploadMutation = useMutation({
    mutationFn: async () => {
      const normalizedBatchId = batchId.trim();
      if (!normalizedBatchId) {
        throw new Error('请先生成批次 ID。');
      }
      if (selectedFiles.length === 0) {
        throw new Error('请至少选择一个文件。');
      }
      if (await batchIdExists(normalizedBatchId)) {
        throw new Error('批次 ID 已存在，请重新生成后再上传。');
      }

      const results: SourceFileRecord[] = [];
      for (const file of selectedFiles) {
        results.push(await uploadSourceFile({
          batchId: normalizedBatchId,
          file,
          uploadedBy,
        }));
      }
      return results;
    },
    onSuccess: records => {
      toast.success(`上传完成，共 ${records.length} 个文件已写入 Storage。`);
      setSelectedFiles([]);
      void createUniqueBatchId(batchIdExists)
        .then(nextBatchId => setBatchId(nextBatchId))
        .catch(() => {
          setBatchId('');
        });
      queryClient.invalidateQueries({ queryKey: SOURCE_FILES_QUERY_KEY });
    },
    onError: error => {
      toast.error(renderUploadError(error));
    },
  });

  const deleteMutation = useMutation<SourceFileRecord | null, Error, SourceFileRecord, { previousQueries: Array<[readonly unknown[], SourceFileRecord[] | undefined]> }>({
    onMutate: async (record: SourceFileRecord) => {
      await queryClient.cancelQueries({ queryKey: SOURCE_FILES_QUERY_KEY });

      const previousQueries = queryClient.getQueriesData<SourceFileRecord[]>({ queryKey: SOURCE_FILES_QUERY_KEY });
      queryClient.setQueriesData<SourceFileRecord[]>({ queryKey: SOURCE_FILES_QUERY_KEY }, current => {
        if (!current) return current;
        return current.filter(item => item.id !== record.id);
      });

      return { previousQueries };
    },
    mutationFn: async (record: SourceFileRecord) => deleteSourceFileById(record.id),
    onSuccess: deletedRecord => {
      if (!deletedRecord) {
        toast.success('文件记录已不存在。');
        return;
      }

      toast.success(`已删除文件：${deletedRecord.file_name}`);
    },
    onError: (error, _record, context) => {
      context?.previousQueries.forEach(([queryKey, data]) => {
        queryClient.setQueryData(queryKey, data);
      });
      toast.error(renderUploadError(error));
    },
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: SOURCE_FILES_QUERY_KEY });
    },
  });

  const filteredFiles = useMemo(() => filesQuery.data ?? [], [filesQuery.data]);

  function handleFileChange(event: React.ChangeEvent<HTMLInputElement>) {
    const files = Array.from(event.target.files ?? []);
    const oversized = files.filter(file => file.size > MAX_FILE_SIZE_BYTES);

    if (oversized.length > 0) {
      toast.error(`以下文件超过 20MB 限制：${oversized.map(file => file.name).join('、')}`);
      event.target.value = '';
      return;
    }

    setSelectedFiles(files);
  }

  async function handleDownload(record: SourceFileRecord) {
    try {
      const signedUrl = await createSourceFileDownloadUrl(record.storage_path);
      window.open(signedUrl, '_blank', 'noopener,noreferrer');
    } catch (error) {
      toast.error(renderUploadError(error));
    }
  }

  function handleDelete(record: SourceFileRecord) {
    setPendingDeleteRecord(record);
  }

  async function handleGenerateBatchId() {
    try {
      setBatchId(await createUniqueBatchId(batchIdExists));
    } catch (error) {
      toast.error(renderUploadError(error));
    }
  }

  return (
    <div className="space-y-6">
      <PageHeader title="原始文件上传">
        <Badge variant="outline">Bucket: {sourceFilesBucket}</Badge>
      </PageHeader>

      {!isSupabaseConfigured() ? (
        <Card className="border-amber-300 bg-amber-50/70">
          <CardHeader>
            <CardTitle className="flex items-center gap-2 text-amber-900">
              <AlertCircle className="h-5 w-5" />
              需要先配置 Supabase 环境变量
            </CardTitle>
            <CardDescription className="text-amber-800">
              请在项目根目录新增 .env.local，并设置 VITE_SUPABASE_URL、VITE_SUPABASE_ANON_KEY、VITE_SUPABASE_SOURCE_FILES_BUCKET。
            </CardDescription>
          </CardHeader>
        </Card>
      ) : null}

      <Card>
        <CardHeader>
          <CardTitle>上传到 Supabase Storage</CardTitle>
          <CardDescription>
            文件会先写入 Storage，再同步写入 source_files 表。建议一个批次上传多份原始采购文件，统一使用同一个 batch_id。
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="grid gap-4 md:grid-cols-3">
            <div className="space-y-2">
              <p className="text-sm font-medium">批次 ID</p>
              <div className="flex gap-2">
                <Input value={batchId} readOnly placeholder="点击生成批次 ID" className="font-mono" />
                <Button type="button" variant="outline" onClick={handleGenerateBatchId} disabled={!isSupabaseConfigured() || uploadMutation.isPending}>
                  生成
                </Button>
              </div>
            </div>
            <div className="space-y-2">
              <p className="text-sm font-medium">上传人</p>
              <Input value={uploadedBy} readOnly className="bg-muted/40" />
            </div>
            <div className="space-y-2">
              <p className="text-sm font-medium">选择文件</p>
              <Input type="file" multiple accept={ACCEPTED_EXTENSIONS} onChange={handleFileChange} />
            </div>
          </div>

          <div className="rounded-lg border border-dashed p-4">
            <p className="text-sm font-medium">待上传文件</p>
            {selectedFiles.length === 0 ? (
              <p className="mt-2 text-sm text-muted-foreground">尚未选择文件。当前限制单文件不超过 20MB。</p>
            ) : (
              <div className="mt-3 space-y-2">
                {selectedFiles.map(file => (
                  <div key={`${file.name}-${file.lastModified}`} className="flex items-center justify-between rounded-md bg-muted/50 px-3 py-2 text-sm">
                    <span className="truncate">{file.name}</span>
                    <span className="text-muted-foreground">{formatFileSize(file.size)}</span>
                  </div>
                ))}
              </div>
            )}
          </div>

          <Button onClick={() => uploadMutation.mutate()} disabled={!isSupabaseConfigured() || uploadMutation.isPending}>
            {uploadMutation.isPending ? <LoaderCircle className="mr-2 h-4 w-4 animate-spin" /> : <Upload className="mr-2 h-4 w-4" />}
            开始上传
          </Button>
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle>已上传文件</CardTitle>
          <CardDescription>
            这里直接读取 source_files 表，刷新后仍然可见。可按批次 ID 过滤验证上传结果。
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="max-w-xs space-y-2">
            <p className="text-sm font-medium">按批次过滤</p>
            <Input value={batchFilter} onChange={event => setBatchFilter(event.target.value)} placeholder="输入批次 ID 过滤" />
          </div>

          {filesQuery.isLoading ? (
            <div className="py-10 text-sm text-muted-foreground">正在读取已上传文件...</div>
          ) : filesQuery.isError ? (
            <div className="py-10 text-sm text-destructive">{renderUploadError(filesQuery.error)}</div>
          ) : filteredFiles.length === 0 ? (
            <div className="py-10 text-sm text-muted-foreground">当前没有已上传文件记录。</div>
          ) : (
            <div className="rounded-md border">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>批次 ID</TableHead>
                    <TableHead>文件名</TableHead>
                    <TableHead>类型</TableHead>
                    <TableHead>识别状态</TableHead>
                    <TableHead>大小</TableHead>
                    <TableHead>上传人</TableHead>
                    <TableHead>上传时间</TableHead>
                    <TableHead className="text-right">操作</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {filteredFiles.map(record => (
                    <TableRow key={record.id}>
                      {(() => {
                        const isDeleting = deleteMutation.isPending && deleteMutation.variables?.id === record.id;

                        return (
                          <>
                      <TableCell className="font-medium">{record.batch_id}</TableCell>
                      <TableCell>{record.file_name}</TableCell>
                      <TableCell>{record.mime_type || '-'}</TableCell>
                      <TableCell>
                        {(() => {
                          const status = describeSourceFileExtractionStatus(record);
                          return (
                            <div className="max-w-44">
                              <span className={`inline-flex items-center rounded border px-1.5 py-0.5 text-xs ${status.badgeClassName}`}>
                                {status.label}
                              </span>
                              {status.detail ? (
                                <p className="mt-1 truncate text-xs text-muted-foreground">{status.detail}</p>
                              ) : null}
                            </div>
                          );
                        })()}
                      </TableCell>
                      <TableCell>{formatFileSize(record.size_bytes)}</TableCell>
                      <TableCell>{record.uploaded_by || '-'}</TableCell>
                      <TableCell>{formatDate(record.uploaded_at)}</TableCell>
                      <TableCell className="text-right">
                        <div className="flex items-center justify-end gap-1">
                          <Button variant="ghost" size="sm" onClick={() => handleDownload(record)} disabled={isDeleting}>
                            <Download className="mr-2 h-4 w-4" />
                            下载
                          </Button>
                          <Button
                            variant="ghost"
                            size="icon"
                            className="h-8 w-8 text-blue-500 hover:text-destructive"
                            onClick={() => handleDelete(record)}
                            disabled={isDeleting}
                            aria-label={`删除 ${record.file_name}`}
                          >
                            {isDeleting ? <LoaderCircle className="h-4 w-4 animate-spin" /> : <Trash2 className="h-4 w-4" />}
                          </Button>
                        </div>
                      </TableCell>
                          </>
                        );
                      })()}
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </div>
          )}
        </CardContent>
      </Card>

      <AlertDialog open={Boolean(pendingDeleteRecord)} onOpenChange={open => { if (!open) setPendingDeleteRecord(null); }}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>确认删除文件</AlertDialogTitle>
            <AlertDialogDescription>
              {pendingDeleteRecord
                ? `确认删除文件“${pendingDeleteRecord.file_name}”吗？该操作会同时删除数据库记录和 Storage 对象。`
                : '该操作会同时删除数据库记录和 Storage 对象。'}
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={deleteMutation.isPending}>取消</AlertDialogCancel>
            <AlertDialogAction
              className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
              disabled={!pendingDeleteRecord || deleteMutation.isPending}
              onClick={event => {
                event.preventDefault();
                if (!pendingDeleteRecord) return;
                deleteMutation.mutate(pendingDeleteRecord, {
                  onSettled: () => setPendingDeleteRecord(null),
                });
              }}
            >
              {deleteMutation.isPending ? '删除中...' : '确认删除'}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
