import { useState, useEffect, useMemo } from "react";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from "@/components/ui/collapsible";
import {
  Search,
  ChevronRight,
  GitBranch,
  Upload,
  FolderOpen,
  Settings2,
  Play,
  Package,
  Globe,
  Shield,
  Loader2,
} from "lucide-react";
import { toast } from "sonner";
import { api } from "@/shared/config/database";

import { useProjects } from "./hooks/useTaskForm";
import { useZipFile, formatFileSize } from "./hooks/useZipFile";
import TerminalProgressDialog from "./TerminalProgressDialog";
import FileSelectionDialog from "./FileSelectionDialog";

import { runRepositoryAudit } from "@/features/projects/services/repoScan";
import {
  scanZipFile,
  scanStoredZipFile,
  validateZipFile,
} from "@/features/projects/services/repoZipScan";
import { isRepositoryProject, isZipProject } from "@/shared/utils/projectUtils";
import type { Project } from "@/shared/types";

interface CreateTaskDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onTaskCreated: () => void;
  preselectedProjectId?: string;
}

const DEFAULT_EXCLUDES = [
  "node_modules/**",
  ".git/**",
  "dist/**",
  "build/**",
  "*.log",
];

export default function CreateTaskDialog({
  open,
  onOpenChange,
  onTaskCreated,
  preselectedProjectId,
}: CreateTaskDialogProps) {
  const [selectedProjectId, setSelectedProjectId] = useState<string>("");
  const [searchTerm, setSearchTerm] = useState("");
  const [branch, setBranch] = useState("main");
  const [branches, setBranches] = useState<string[]>([]);
  const [loadingBranches, setLoadingBranches] = useState(false);
  const [excludePatterns, setExcludePatterns] = useState(DEFAULT_EXCLUDES);
  const [selectedFiles, setSelectedFiles] = useState<string[] | undefined>();
  const [showAdvanced, setShowAdvanced] = useState(false);
  const [showFileSelection, setShowFileSelection] = useState(false);
  const [creating, setCreating] = useState(false);
  const [uploading, setUploading] = useState(false);
  const [showTerminal, setShowTerminal] = useState(false);
  const [currentTaskId, setCurrentTaskId] = useState<string | null>(null);

  const { projects, loading, loadProjects } = useProjects();
  const selectedProject = projects.find((p) => p.id === selectedProjectId);
  const zipState = useZipFile(selectedProject, projects);

  // 加载分支列表
  useEffect(() => {
    const loadBranches = async () => {
      if (!selectedProject || !isRepositoryProject(selectedProject)) {
        setBranches([]);
        return;
      }

      setLoadingBranches(true);
      try {
        const result = await api.getProjectBranches(selectedProject.id);
        setBranches(result.branches);
        if (result.default_branch) {
          setBranch(result.default_branch);
        }
      } catch (error) {
        console.error("加载分支失败:", error);
        setBranches([selectedProject.default_branch || "main"]);
      } finally {
        setLoadingBranches(false);
      }
    };

    loadBranches();
  }, [selectedProject?.id]);

  const filteredProjects = useMemo(() => {
    if (!searchTerm) return projects;
    const term = searchTerm.toLowerCase();
    return projects.filter(
      (p) =>
        p.name.toLowerCase().includes(term) ||
        p.description?.toLowerCase().includes(term)
    );
  }, [projects, searchTerm]);

  useEffect(() => {
    if (open) {
      loadProjects();
      if (preselectedProjectId) {
        setSelectedProjectId(preselectedProjectId);
      }
      setSearchTerm("");
      setShowAdvanced(false);
      zipState.reset();
    }
  }, [open, preselectedProjectId]);



  const handleStartScan = async () => {
    if (!selectedProject) {
      toast.error("请选择项目");
      return;
    }

    try {
      setCreating(true);
      let taskId: string;

      if (isZipProject(selectedProject)) {
        if (zipState.useStoredZip && zipState.storedZipInfo?.has_file) {
          taskId = await scanStoredZipFile({
            projectId: selectedProject.id,
            excludePatterns,
            createdBy: "local-user",
            filePaths: selectedFiles,
          });
        } else if (zipState.zipFile) {
          taskId = await scanZipFile({
            projectId: selectedProject.id,
            zipFile: zipState.zipFile,
            excludePatterns,
            createdBy: "local-user",
          });
        } else {
          toast.error("请上传 ZIP 文件");
          return;
        }
      } else {
        if (!selectedProject.repository_url) {
          toast.error("仓库地址为空");
          return;
        }
        taskId = await runRepositoryAudit({
          projectId: selectedProject.id,
          repoUrl: selectedProject.repository_url,
          branch,
          exclude: excludePatterns,
          createdBy: "local-user",
          filePaths: selectedFiles,
        });
      }

      onOpenChange(false);
      onTaskCreated();
      setCurrentTaskId(taskId);
      setShowTerminal(true);
      toast.success("扫描任务已启动");

      setSelectedProjectId("");
      setSelectedFiles(undefined);
      setExcludePatterns(DEFAULT_EXCLUDES);
    } catch (error) {
      const msg = error instanceof Error ? error.message : "未知错误";
      toast.error(`启动失败: ${msg}`);
    } finally {
      setCreating(false);
    }
  };

  const canStart = useMemo(() => {
    if (!selectedProject) return false;
    if (isZipProject(selectedProject)) {
      return (
        (zipState.useStoredZip && zipState.storedZipInfo?.has_file) ||
        !!zipState.zipFile
      );
    }
    return !!selectedProject.repository_url && !!branch.trim();
  }, [selectedProject, zipState, branch]);

  return (
    <>
      <Dialog open={open} onOpenChange={onOpenChange}>
        <DialogContent className="!w-[min(90vw,520px)] !max-w-none max-h-[85vh] flex flex-col p-0 gap-0 bg-white border-2 border-black rounded-none shadow-[6px_6px_0px_0px_rgba(0,0,0,1)]">
          {/* Header - 机械风 */}
          <DialogHeader className="px-5 py-4 border-b-2 border-black bg-gray-100 flex-shrink-0">
            <DialogTitle className="flex items-center gap-3 font-mono font-bold uppercase text-base tracking-wide">
              <Shield className="w-5 h-5" />
              开始代码审计
            </DialogTitle>
          </DialogHeader>

          <div className="flex-1 overflow-y-auto p-5 space-y-5">
            {/* 项目选择 */}
            <div className="space-y-3">
              <div className="flex items-center justify-between">
                <span className="text-sm font-mono font-bold uppercase">
                  选择项目
                </span>
                <Badge
                  variant="outline"
                  className="rounded-none border-black font-mono text-xs"
                >
                  {filteredProjects.length} 个
                </Badge>
              </div>

              {/* 搜索框 */}
              <div className="relative">
                <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-500" />
                <Input
                  placeholder="搜索项目..."
                  value={searchTerm}
                  onChange={(e) => setSearchTerm(e.target.value)}
                  className="pl-9 h-10 rounded-none border-2 border-black font-mono focus:ring-0 focus:border-black"
                />
              </div>

              {/* 项目列表 */}
              <ScrollArea className="h-[180px] border-2 border-black bg-gray-50">
                {loading ? (
                  <div className="flex items-center justify-center h-full">
                    <div className="animate-spin h-6 w-6 border-2 border-black border-t-transparent" />
                  </div>
                ) : filteredProjects.length === 0 ? (
                  <div className="flex flex-col items-center justify-center h-full text-gray-500 font-mono">
                    <Package className="w-8 h-8 mb-2 opacity-50" />
                    <span className="text-sm">
                      {searchTerm ? "未找到" : "暂无项目"}
                    </span>
                  </div>
                ) : (
                  <div className="p-1">
                    {filteredProjects.map((project) => (
                      <ProjectCard
                        key={project.id}
                        project={project}
                        selected={selectedProjectId === project.id}
                        onSelect={() => setSelectedProjectId(project.id)}
                      />
                    ))}
                  </div>
                )}
              </ScrollArea>
            </div>

            {/* 配置区域 */}
            {selectedProject && (
              <div className="space-y-4">
                <span className="text-sm font-mono font-bold uppercase">
                  配置
                </span>

                {isRepositoryProject(selectedProject) ? (
                  <div className="flex items-center gap-3 p-3 border-2 border-black bg-blue-50">
                    <GitBranch className="w-5 h-5 text-blue-700" />
                    <span className="font-mono text-sm font-bold w-12">
                      分支
                    </span>
                    {loadingBranches ? (
                      <div className="flex items-center gap-2 flex-1">
                        <Loader2 className="w-4 h-4 animate-spin text-blue-600" />
                        <span className="text-sm text-blue-600 font-mono">加载中...</span>
                      </div>
                    ) : (
                      <Select value={branch} onValueChange={setBranch}>
                        <SelectTrigger className="h-9 flex-1 rounded-none border-2 border-black font-mono focus:ring-0">
                          <SelectValue placeholder="选择分支" />
                        </SelectTrigger>
                        <SelectContent className="rounded-none border-2 border-black shadow-[4px_4px_0px_0px_rgba(0,0,0,1)]">
                          {branches.map((b) => (
                            <SelectItem key={b} value={b} className="font-mono">
                              {b}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    )}
                  </div>
                ) : (
                  <ZipUploadCard 
                    zipState={zipState} 
                    onUpload={async () => {
                      if (!zipState.zipFile || !selectedProject) return;
                      setUploading(true);
                      try {
                        await api.uploadProjectZip(selectedProject.id, zipState.zipFile);
                        toast.success("文件上传成功");
                        zipState.switchToStored();
                        loadProjects();
                      } catch (error) {
                        const msg = error instanceof Error ? error.message : "上传失败";
                        toast.error(msg);
                      } finally {
                        setUploading(false);
                      }
                    }}
                    uploading={uploading}
                  />
                )}

                {/* 高级选项 */}
                <Collapsible open={showAdvanced} onOpenChange={setShowAdvanced}>
                  <CollapsibleTrigger className="flex items-center gap-2 text-sm font-mono text-gray-600 hover:text-black transition-colors">
                    <ChevronRight
                      className={`w-4 h-4 transition-transform ${showAdvanced ? "rotate-90" : ""}`}
                    />
                    <Settings2 className="w-4 h-4" />
                    <span className="uppercase font-bold">高级选项</span>
                  </CollapsibleTrigger>
                  <CollapsibleContent className="mt-3 space-y-3">
                    {/* 排除模式 */}
                    <div className="p-3 border-2 border-dashed border-gray-400 bg-gray-50 space-y-2">
                      <span className="font-mono text-xs uppercase font-bold text-gray-600">
                        排除模式
                      </span>
                      <div className="flex flex-wrap gap-1.5">
                        {excludePatterns.map((p) => (
                          <Badge
                            key={p}
                            variant="secondary"
                            className="rounded-none border border-black bg-white text-gray-800 font-mono text-xs cursor-pointer hover:bg-red-100 hover:text-red-700"
                            onClick={() =>
                              setExcludePatterns((prev) =>
                                prev.filter((x) => x !== p)
                              )
                            }
                          >
                            {p} ×
                          </Badge>
                        ))}
                      </div>
                      <Input
                        placeholder="添加排除模式，回车确认"
                        className="h-8 rounded-none border-2 border-black font-mono text-sm focus:ring-0"
                        onKeyDown={(e) => {
                          if (e.key === "Enter" && e.currentTarget.value) {
                            const val = e.currentTarget.value.trim();
                            if (val && !excludePatterns.includes(val)) {
                              setExcludePatterns((prev) => [...prev, val]);
                            }
                            e.currentTarget.value = "";
                          }
                        }}
                      />
                    </div>

                    {/* 文件选择 */}
                    {(() => {
                      const isRepo = isRepositoryProject(selectedProject);
                      const isZip = isZipProject(selectedProject);
                      const hasStoredZip = zipState.storedZipInfo?.has_file;
                      const useStored = zipState.useStoredZip;
                      
                      // 可以选择文件的条件：仓库项目 或 ZIP项目使用已存储文件
                      const canSelectFiles = isRepo || (isZip && useStored && hasStoredZip);
                      
                      return (
                        <div className="flex items-center justify-between p-3 border-2 border-dashed border-gray-400 bg-gray-50">
                          <div>
                            <p className="font-mono text-xs uppercase font-bold text-gray-600">
                              扫描范围
                            </p>
                            <p className="text-sm font-bold mt-1">
                              {selectedFiles
                                ? `已选 ${selectedFiles.length} 个文件`
                                : "全部文件"}
                            </p>
                          </div>
                          <div className="flex gap-2">
                            {selectedFiles && canSelectFiles && (
                              <Button
                                size="sm"
                                variant="ghost"
                                onClick={() => setSelectedFiles(undefined)}
                                className="h-8 text-xs text-red-600 hover:bg-red-50 rounded-none"
                              >
                                重置
                              </Button>
                            )}
                            <Button
                              size="sm"
                              variant="outline"
                              onClick={() => setShowFileSelection(true)}
                              disabled={!canSelectFiles}
                              className="h-8 text-xs rounded-none border-2 border-black font-mono font-bold disabled:opacity-50"
                            >
                              <FolderOpen className="w-3 h-3 mr-1" />
                              选择文件
                            </Button>
                          </div>
                        </div>
                      );
                    })()}
                  </CollapsibleContent>
                </Collapsible>
              </div>
            )}
          </div>

          {/* Footer - 机械风 */}
          <div className="flex-shrink-0 flex justify-end gap-3 px-5 py-4 bg-gray-100 border-t-2 border-black">
            <Button
              variant="outline"
              onClick={() => onOpenChange(false)}
              disabled={creating}
              className="px-5 h-10 rounded-none border-2 border-black font-mono font-bold uppercase hover:bg-gray-200"
            >
              取消
            </Button>
            <Button
              onClick={handleStartScan}
              disabled={!canStart || creating}
              className="px-5 h-10 rounded-none border-2 border-black bg-primary text-white font-mono font-bold uppercase shadow-[3px_3px_0px_0px_rgba(0,0,0,1)] hover:shadow-[1px_1px_0px_0px_rgba(0,0,0,1)] hover:translate-x-[2px] hover:translate-y-[2px] transition-all disabled:opacity-50 disabled:shadow-none disabled:translate-x-0 disabled:translate-y-0"
            >
              {creating ? (
                <>
                  <div className="animate-spin h-4 w-4 border-2 border-white border-t-transparent mr-2" />
                  启动中...
                </>
              ) : (
                <>
                  <Play className="w-4 h-4 mr-2" />
                  开始扫描
                </>
              )}
            </Button>
          </div>
        </DialogContent>
      </Dialog>

      <TerminalProgressDialog
        open={showTerminal}
        onOpenChange={setShowTerminal}
        taskId={currentTaskId}
        taskType="repository"
      />

      <FileSelectionDialog
        open={showFileSelection}
        onOpenChange={setShowFileSelection}
        projectId={selectedProjectId}
        branch={branch}
        onConfirm={setSelectedFiles}
      />
    </>
  );
}

function ProjectCard({
  project,
  selected,
  onSelect,
}: {
  project: Project;
  selected: boolean;
  onSelect: () => void;
}) {
  const isRepo = isRepositoryProject(project);

  return (
    <div
      className={`flex items-center gap-3 p-3 cursor-pointer border-b border-gray-200 last:border-b-0 transition-all ${
        selected
          ? "bg-primary/10 border-l-4 border-l-primary"
          : "hover:bg-white"
      }`}
      onClick={onSelect}
    >
      <Checkbox
        checked={selected}
        className="rounded-none border-2 border-black data-[state=checked]:bg-primary"
      />

      <div
        className={`p-1.5 border-2 border-black ${
          isRepo ? "bg-blue-100" : "bg-amber-100"
        }`}
      >
        {isRepo ? (
          <Globe className="w-4 h-4 text-blue-700" />
        ) : (
          <Package className="w-4 h-4 text-amber-700" />
        )}
      </div>

      <div className="flex-1 min-w-0 overflow-hidden">
        <div className="flex items-center gap-2">
          <span className="font-bold text-sm truncate">{project.name}</span>
          <Badge
            variant="outline"
            className={`text-[10px] px-1 py-0 rounded-none border font-mono font-bold flex-shrink-0 ${
              isRepo
                ? "bg-blue-50 text-blue-700 border-blue-300"
                : "bg-amber-50 text-amber-700 border-amber-300"
            }`}
          >
            {isRepo ? "REPO" : "ZIP"}
          </Badge>
        </div>
        {project.description && (
          <p className="text-xs text-gray-500 mt-0.5 font-mono line-clamp-2" title={project.description}>
            {project.description}
          </p>
        )}
      </div>
    </div>
  );
}

function ZipUploadCard({
  zipState,
  onUpload,
  uploading,
}: {
  zipState: ReturnType<typeof useZipFile>;
  onUpload: () => void;
  uploading: boolean;
}) {
  if (zipState.loading) {
    return (
      <div className="flex items-center gap-3 p-3 border-2 border-black bg-blue-50">
        <div className="animate-spin h-5 w-5 border-2 border-blue-700 border-t-transparent" />
        <span className="text-sm font-mono font-bold text-blue-800">
          检查文件中...
        </span>
      </div>
    );
  }

  if (zipState.storedZipInfo?.has_file) {
    return (
      <div className="p-3 border-2 border-black bg-green-50 space-y-3">
        <div className="flex items-center gap-3">
          <div className="p-1.5 border-2 border-black bg-green-100">
            <Package className="w-4 h-4 text-green-700" />
          </div>
          <div className="flex-1">
            <p className="text-sm font-bold text-green-900 font-mono">
              {zipState.storedZipInfo.original_filename}
            </p>
            <p className="text-xs text-green-700 font-mono">
              {zipState.storedZipInfo.file_size &&
                formatFileSize(zipState.storedZipInfo.file_size)}
              {zipState.storedZipInfo.uploaded_at &&
                ` · ${new Date(zipState.storedZipInfo.uploaded_at).toLocaleDateString("zh-CN")}`}
            </p>
          </div>
        </div>

        <div className="flex gap-4 pt-2 border-t border-green-300">
          <label className="flex items-center gap-2 cursor-pointer font-mono text-sm">
            <input
              type="radio"
              checked={zipState.useStoredZip}
              onChange={() => zipState.switchToStored()}
              className="w-4 h-4"
            />
            <span className="font-bold text-green-800">使用此文件</span>
          </label>
          <label className="flex items-center gap-2 cursor-pointer font-mono text-sm">
            <input
              type="radio"
              checked={!zipState.useStoredZip}
              onChange={() => zipState.switchToUpload()}
              className="w-4 h-4"
            />
            <span className="font-bold text-green-800">上传新文件</span>
          </label>
        </div>

        {!zipState.useStoredZip && (
          <div className="flex gap-2 items-center">
            <Input
              type="file"
              accept=".zip"
              onChange={(e) => {
                const file = e.target.files?.[0];
                if (file) {
                  const v = validateZipFile(file);
                  if (!v.valid) {
                    toast.error(v.error || "文件无效");
                    e.target.value = "";
                    return;
                  }
                  zipState.handleFileSelect(file, e.target);
                }
              }}
              className="h-9 flex-1 rounded-none border-2 border-black font-mono"
            />
            {zipState.zipFile && (
              <Button
                size="sm"
                onClick={onUpload}
                disabled={uploading}
                className="h-9 px-3 rounded-none border-2 border-black bg-amber-500 hover:bg-amber-600 text-black font-mono font-bold shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]"
              >
                {uploading ? (
                  <Loader2 className="w-4 h-4 animate-spin" />
                ) : (
                  <Upload className="w-4 h-4" />
                )}
              </Button>
            )}
          </div>
        )}
      </div>
    );
  }

  return (
    <div className="p-3 border-2 border-dashed border-amber-500 bg-amber-50">
      <div className="flex items-start gap-3">
        <div className="p-1.5 border-2 border-black bg-amber-100">
          <Upload className="w-4 h-4 text-amber-700" />
        </div>
        <div className="flex-1">
          <p className="text-sm font-bold text-amber-900 font-mono uppercase">
            上传 ZIP 文件
          </p>
          <div className="flex gap-2 items-center mt-2">
            <Input
              type="file"
              accept=".zip"
              onChange={(e) => {
                const file = e.target.files?.[0];
                if (file) {
                  const v = validateZipFile(file);
                  if (!v.valid) {
                    toast.error(v.error || "文件无效");
                    e.target.value = "";
                    return;
                  }
                  zipState.handleFileSelect(file, e.target);
                }
              }}
              className="h-9 flex-1 rounded-none border-2 border-black font-mono"
            />
            {zipState.zipFile && (
              <Button
                size="sm"
                onClick={onUpload}
                disabled={uploading}
                className="h-9 px-3 rounded-none border-2 border-black bg-amber-500 hover:bg-amber-600 text-black font-mono font-bold shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]"
              >
                {uploading ? (
                  <Loader2 className="w-4 h-4 animate-spin" />
                ) : (
                  <Upload className="w-4 h-4" />
                )}
              </Button>
            )}
          </div>
          {zipState.zipFile && (
            <p className="text-xs text-amber-800 mt-2 font-mono font-bold">
              已选: {zipState.zipFile.name} (
              {formatFileSize(zipState.zipFile.size)})
            </p>
          )}
        </div>
      </div>
    </div>
  );
}
