"use client";

import React, { useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "@/store/store";
import {
  setUploadedFiles,
  setBriefText,
  setDecomposedFiles,
  setWizardStep,
  WizardUploadedFile,
} from "@/store/slices/wizardSlice";
import { Upload, X, FileText, ChevronRight, Plus, Link } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { toast } from "sonner";
import { cn } from "@/lib/utils";
import { OverlayLoader } from "@/components/ui/overlay-loader";
import Wrapper from "@/components/Wrapper";
import { WizardApi } from "../../services/api/wizard";

const ACCEPTED_TYPES = [
  "application/pdf",
  "text/plain",
  "application/vnd.openxmlformats-officedocument.presentationml.presentation",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "text/csv",
  "image/png",
  "image/jpeg",
  "image/webp",
];

const ACCEPT_STRING = ".pdf,.txt,.pptx,.docx,.xlsx,.csv,.png,.jpg,.jpeg,.webp";

function formatFileSize(bytes: number): string {
  if (!bytes || bytes === 0) return "0 B";
  const k = 1024;
  const sizes = ["B", "KB", "MB", "GB"];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i];
}

function getTypeBadge(type: string): string {
  if (type.includes("pdf")) return "PDF";
  if (type.includes("word")) return "DOCX";
  if (type.includes("presentation")) return "PPTX";
  if (type.includes("spreadsheet") || type.includes("csv")) return "DATA";
  if (type.includes("image")) return "IMG";
  if (type.includes("text")) return "TXT";
  return "FILE";
}

export default function WizardUploadPage() {
  const router = useRouter();
  const dispatch = useDispatch();
  const { uploadedFiles, briefText } = useSelector((s: RootState) => s.wizard);

  const [localFiles, setLocalFiles] = useState<File[]>([]);
  const [isDragging, setIsDragging] = useState(false);
  const [isProcessing, setIsProcessing] = useState(false);
  const [referenceUrl, setReferenceUrl] = useState("");
  const [isFetchingUrl, setIsFetchingUrl] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(true);
  };

  const handleDragLeave = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(false);
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(false);

    const droppedFiles = Array.from(e.dataTransfer.files);
    addFiles(droppedFiles);
  };

  const handleFileInput = (e: React.ChangeEvent<HTMLInputElement>) => {
    const selected = Array.from(e.target.files || []);
    addFiles(selected);
    // Reset input so same file can be re-selected
    if (fileInputRef.current) fileInputRef.current.value = "";
  };

  const addFiles = (newFiles: File[]) => {
    const invalid = newFiles.filter((f) => !ACCEPTED_TYPES.includes(f.type));
    if (invalid.length > 0) {
      toast.error("Unsupported file type", {
        description: "Please upload PDF, DOCX, PPTX, Excel, CSV, or image files.",
      });
      return;
    }
    setLocalFiles((prev) => [...prev, ...newFiles]);

    const newMeta: WizardUploadedFile[] = newFiles.map((f) => ({
      name: f.name,
      size: f.size,
      type: f.type,
    }));
    dispatch(setUploadedFiles([...uploadedFiles, ...newMeta]));
    toast.success(`${newFiles.length} file(s) added`);
  };

  const removeFile = (index: number) => {
    setLocalFiles((prev) => prev.filter((_, i) => i !== index));
    dispatch(setUploadedFiles(uploadedFiles.filter((_, i) => i !== index)));
  };

  const allFiles = uploadedFiles; // display list from Redux

  const handleFetchUrl = async () => {
    if (!referenceUrl.trim()) {
      toast.error("Please enter a URL");
      return;
    }
    try {
      setIsFetchingUrl(true);
      const text = await WizardApi.fetchUrl(referenceUrl.trim());
      const separator = briefText.trim() ? "\n\n---\n\n" : "";
      dispatch(setBriefText(briefText + separator + text));
      toast.success("URL content fetched and appended to brief");
      setReferenceUrl("");
    } catch (error: any) {
      toast.error("Failed to fetch URL", {
        description: error.message || "Please check the URL and try again.",
      });
    } finally {
      setIsFetchingUrl(false);
    }
  };

  const handleNext = async () => {
    if (!briefText.trim() && allFiles.length === 0) {
      toast.error("Please enter a brief or upload documents");
      return;
    }

    try {
      setIsProcessing(true);

      // Upload files if there are local files to upload
      if (localFiles.length > 0) {
        const serverPaths = await WizardApi.uploadFiles(localFiles);
        // Decompose documents
        const decomposed = await WizardApi.decomposeFiles(serverPaths);
        dispatch(setDecomposedFiles(decomposed));

        // Update server paths on uploaded files
        const updated = uploadedFiles.map((f, i) => ({
          ...f,
          serverPath: serverPaths[i] ?? f.serverPath,
        }));
        dispatch(setUploadedFiles(updated));
        setLocalFiles([]); // Clear local references
      }

      dispatch(setWizardStep(2));
      router.push("/generate/configure");
    } catch (error: any) {
      toast.error("Upload failed", {
        description: error.message || "Please try again.",
      });
    } finally {
      setIsProcessing(false);
    }
  };

  return (
    <Wrapper className="py-8 max-w-4xl">
      <OverlayLoader
        show={isProcessing}
        text="Processing documents..."
        showProgress
        duration={90}
        extra_info={allFiles.length > 3 ? "Large documents may take a minute." : ""}
      />

      <h1 className="text-2xl font-semibold mb-1">Upload Your Brief</h1>
      <p className="text-sm text-gray-500 mb-6">
        Upload your presentation brief (DOCX) and any supporting files, or type your content below.
      </p>

      {/* Drag & Drop Zone */}
      <div
        onClick={() => fileInputRef.current?.click()}
        onDragOver={handleDragOver}
        onDragLeave={handleDragLeave}
        onDrop={handleDrop}
        className={cn(
          "border-2 border-dashed rounded-xl cursor-pointer transition-all",
          "flex flex-col items-center justify-center py-12 px-6",
          isDragging
            ? "border-[#5146E5] bg-[#5146E5]/5"
            : "border-gray-300 bg-white hover:border-gray-400"
        )}
      >
        <Upload
          className={cn(
            "w-10 h-10 mb-3",
            isDragging ? "text-[#5146E5]" : "text-gray-400"
          )}
        />
        <p className="text-gray-600 font-medium mb-1">
          {isDragging ? "Drop files here" : "Drag & drop files here"}
        </p>
        <p className="text-gray-400 text-sm mb-4">
          DOCX, PDF, PPTX, Excel, CSV, Images
        </p>
        <Button
          type="button"
          variant="outline"
          size="sm"
          onClick={(e) => {
            e.stopPropagation();
            fileInputRef.current?.click();
          }}
        >
          <Plus className="w-4 h-4 mr-1" /> Browse Files
        </Button>
        <input
          ref={fileInputRef}
          type="file"
          accept={ACCEPT_STRING}
          multiple
          onChange={handleFileInput}
          className="hidden"
        />
      </div>

      {/* File List */}
      {allFiles.length > 0 && (
        <div className="mt-4 space-y-2">
          <h3 className="text-sm font-medium text-gray-600">
            Files ({allFiles.length})
          </h3>
          {allFiles.map((f, idx) => (
            <div
              key={`${f.name}-${idx}`}
              className="flex items-center gap-3 bg-white rounded-lg border px-4 py-3"
            >
              <FileText className="w-5 h-5 text-[#5146E5] flex-shrink-0" />
              <div className="flex-1 min-w-0">
                <p className="text-sm font-medium truncate">{f.name}</p>
                <p className="text-xs text-gray-400">{formatFileSize(f.size)}</p>
              </div>
              <span className="text-[10px] font-semibold uppercase px-2 py-0.5 rounded bg-gray-100 text-gray-500">
                {getTypeBadge(f.type)}
              </span>
              <button
                onClick={() => removeFile(idx)}
                className="p-1 text-gray-400 hover:text-red-500 transition-colors"
              >
                <X className="w-4 h-4" />
              </button>
            </div>
          ))}
        </div>
      )}

      {/* Reference URL */}
      <div className="mt-6">
        <label className="block text-sm font-medium text-gray-700 mb-2">
          <Link className="w-4 h-4 inline mr-1.5 -mt-0.5" />
          Or add a reference URL
        </label>
        <div className="flex gap-2">
          <Input
            type="text"
            placeholder="https://example.com/article"
            value={referenceUrl}
            onChange={(e) => setReferenceUrl(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === "Enter") {
                e.preventDefault();
                handleFetchUrl();
              }
            }}
            className="flex-1"
          />
          <Button
            type="button"
            variant="outline"
            size="sm"
            onClick={handleFetchUrl}
            disabled={isFetchingUrl || !referenceUrl.trim()}
            className="px-4 whitespace-nowrap"
          >
            {isFetchingUrl ? "Fetching..." : "Fetch"}
          </Button>
        </div>
      </div>

      {/* Brief Text */}
      <div className="mt-6">
        <label className="block text-sm font-medium text-gray-700 mb-2">
          Or describe your presentation
        </label>
        <Textarea
          placeholder="Enter your presentation topic, key points, or paste content here..."
          value={briefText}
          onChange={(e) => dispatch(setBriefText(e.target.value))}
          className="min-h-[120px] resize-y"
        />
      </div>

      {/* Next Button */}
      <div className="mt-8 flex justify-end">
        <Button
          onClick={handleNext}
          disabled={isProcessing}
          className="px-8 py-6 bg-[#5146E5] hover:bg-[#5146E5]/90 text-white font-semibold text-base rounded-full"
        >
          Next: Configure
          <ChevronRight className="w-5 h-5 ml-1" />
        </Button>
      </div>
    </Wrapper>
  );
}
