'use client';

import { useSession } from 'next-auth/react';
import { useState, useEffect, useRef } from 'react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Progress } from '@/components/ui/progress';
import { Textarea } from '@/components/ui/textarea';
import { Card, CardContent } from '@/components/ui/card';
import { Upload, File, X, Send } from 'lucide-react';
import { toast } from 'sonner';
import { formatFileSize } from '@/lib/utils';
import { Loader2 } from 'lucide-react';

const PLAN_LIMITS = {
  free: {
    maxFileSizeMB: 2048,
    maxMonthlyTransferSizeMB: 10240,
    expiryText: '48 hours after sending',
  },
  rookie: {
    maxFileSizeMB: Infinity,
    maxMonthlyTransferSizeMB: 30720,
    expiryText: '7 days after sending',
  },
  pro: {
    maxFileSizeMB: Infinity,
    maxMonthlyTransferSizeMB: 1024 * 1024,
    expiryText: '30 days after sending',
  },
};

const CHUNK_SIZE = 10 * 1024 * 1024; // 10MB chunks

export default function SendPage() {
  const { data: session } = useSession();
  const [files, setFiles] = useState<File[]>([]);
  const [recipient, setRecipient] = useState('');
  const [password, setPassword] = useState('');
  const [message, setMessage] = useState('');
  const [plan, setPlan] = useState<'free' | 'rookie' | 'pro'>('free');
  const [remainingMB, setRemainingMB] = useState(Infinity);
  const [uploadProgress, setUploadProgress] = useState(0);
  const [uploadStep, setUploadStep] = useState('');
  const [uploadMessage, setUploadMessage] = useState('');
  const [currentChunk, setCurrentChunk] = useState(0);
  const [totalChunks, setTotalChunks] = useState(0);
  const dropRef = useRef<HTMLDivElement>(null);
  const totalSize = files.reduce((acc, file) => acc + file.size, 0);
  const totalSizeMB = totalSize / 1024 / 1024;
  const isOverLimit =
    totalSizeMB > PLAN_LIMITS[plan].maxFileSizeMB || totalSizeMB > remainingMB;

  useEffect(() => {
    const fetchPlan = async () => {
      const res = await fetch('/api/usage');
      if (res.ok) {
        const data = await res.json();
        setPlan(data.plan);
        setRemainingMB(data.remainingMB);
      }
    };
    if (session?.user?.email) fetchPlan();
  }, [session]);

  const handleFileAdd = (newFiles: File[]) => {
    const unique = newFiles.filter(
      (newFile) =>
        !files.find(
          (existing) =>
            existing.name === newFile.name && existing.size === newFile.size
        )
    );
    setFiles((prev) => [...prev, ...unique]);
  };

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (!e.target.files) return;
    handleFileAdd(Array.from(e.target.files));
  };

  const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    e.stopPropagation();
    if (e.dataTransfer.files) {
      handleFileAdd(Array.from(e.dataTransfer.files));
    }
    dropRef.current?.classList.remove('border-blue-500');
  };

  const removeFile = (index: number) => {
    setFiles((prev) => prev.filter((_, i) => i !== index));
  };

  const fileInputRef = useRef<HTMLInputElement>(null);
  const triggerFileInput = () => fileInputRef.current?.click();

  const handleSubmit = async () => {
    if (!files.length)
      return setUploadMessage('Please select at least one file');
    if (!recipient || !password)
      return setUploadMessage('All fields are required');
    if (isOverLimit)
      return setUploadMessage('File size exceeds your plan limits');
    const senderEmail = session?.user?.email;
    if (!senderEmail)
      return setUploadMessage('Unable to get sender email. Please log in.');

    try {
      setUploadStep('Preparing files');

      // Chunk counts for every selected file, so progress spans the whole
      // transfer rather than just the first file.
      const perFileChunks = files.map((f) => Math.max(1, Math.ceil(f.size / CHUNK_SIZE)));
      const totalChunksCount = perFileChunks.reduce((a, b) => a + b, 0);
      setTotalChunks(totalChunksCount);

      // Generate upload ID
      const uploadId = crypto.randomUUID();

      // Upload raw chunks - server will encrypt each chunk
      setUploadStep('Uploading');
      let uploadedChunks = 0;

      for (let fileIndex = 0; fileIndex < files.length; fileIndex++) {
        const file = files[fileIndex];
        const fileChunks = perFileChunks[fileIndex];

        for (let i = 0; i < fileChunks; i++) {
          const start = i * CHUNK_SIZE;
          const end = Math.min(start + CHUNK_SIZE, file.size);
          const chunkFile = file.slice(start, end);

          const formData = new FormData();
          formData.append('chunk', chunkFile);
          formData.append('uploadId', uploadId);
          formData.append('fileIndex', fileIndex.toString());
          formData.append('chunkIndex', i.toString());
          formData.append('fileChunks', fileChunks.toString());
          formData.append('fileCount', files.length.toString());
          formData.append('fileName', file.name);

          // Transfer-wide metadata travels with the very first chunk only.
          if (fileIndex === 0 && i === 0) {
            formData.append('email', recipient);
            formData.append('password', password);
            formData.append('filenames', JSON.stringify(files.map((f) => f.name)));
            formData.append('message', message);
          }

          const uploadRes = await fetch('/api/chunk-upload-v2', {
            method: 'POST',
            body: formData,
          });

          if (!uploadRes.ok) {
            const error = await uploadRes.json().catch(() => ({}));
            throw new Error(error.message || `Chunk ${i} of ${file.name} failed`);
          }

          uploadedChunks++;
          setCurrentChunk(uploadedChunks);
          setUploadProgress(Math.round((uploadedChunks / totalChunksCount) * 100));
        }
      }

      // Finalize upload
      setUploadStep('Finalizing');
      const finalRes = await fetch(`/api/chunk-upload-v2?uploadId=${uploadId}`, {
        method: 'PUT',
      });

      if (!finalRes.ok) {
        const error = await finalRes.json().catch(() => ({}));
        throw new Error(error.message || 'Failed to finalize upload');
      }

      setUploadStep('');
      setUploadMessage('Success! 🎉');
      toast.success('Your transfer has been sent successfully!');
      setFiles([]);
      setRecipient('');
      setPassword('');
      setMessage('');
      setUploadProgress(100);
      setTimeout(() => setUploadMessage(''), 3000);
    } catch (err: unknown) {
      console.error(err);
      setUploadStep('');
      setUploadMessage('Error: ' + (err instanceof Error ? err.message : String(err)));
    }
  };

  function UploadStatusToast({
    step,
    progress,
    message,
    currentChunk,
    totalChunks,
  }: {
    step: string;
    progress: number;
    message: string;
    currentChunk: number;
    totalChunks: number;
  }) {
    const showSpinner = ['Uploading', 'Finalizing'].includes(step);
    const isError =
      message.toLowerCase().includes('error') || message.includes('fail');

    if (!step && !message) return null;

    return (
      <div className="w-full p-4 bg-slate-100 dark:bg-slate-800 rounded-lg shadow-md flex flex-col space-y-2">
        <div className="flex items-center gap-2">
          {showSpinner && (
            <Loader2 className="h-4 w-4 animate-spin text-blue-600" />
          )}
          <p
            className={`text-sm font-medium ${
              isError ? 'text-red-600' : 'text-slate-800 dark:text-slate-100'
            }`}
          >
            {step}{currentChunk && totalChunks ? ` (${currentChunk}/${totalChunks})` : ''}
          </p>
        </div>
        {!isError && step === 'Uploading' && (
          <>
            <Progress value={progress} className="h-2" />
            <p className="text-xs text-red-600 font-medium">
              ⚠️ Please do not close this page during upload!
            </p>
          </>
        )}
      </div>
    );
  }

  return (
    <div className="space-y-8">
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
        {/* File Upload Section */}
        <div className="space-y-6">
          <div>
            <h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-4">
              Upload Files
            </h3>
            <div
              ref={dropRef}
              onDrop={handleDrop}
              onDragOver={(e) => {
                e.preventDefault();
                dropRef.current?.classList.add('border-blue-500');
              }}
              onDragLeave={() =>
                dropRef.current?.classList.remove('border-blue-500')
              }
              className="border-2 border-dashed rounded-xl p-8 text-center cursor-pointer transition-all"
            >
              <div className="flex flex-col items-center space-y-4">
                <div className="w-16 h-16 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-full flex items-center justify-center">
                  <Upload className="w-8 h-8 text-white" />
                </div>
                <div>
                  <p className="text-lg font-semibold text-slate-900 dark:text-slate-100">
                    Drag & drop files here
                  </p>
                  <p className="text-sm text-slate-500 dark:text-slate-400">
                    or click to select files
                  </p>
                </div>
                <Button
                  variant="outline"
                  type="button"
                  onClick={triggerFileInput}
                >
                  Select Files
                </Button>
                <input
                  ref={fileInputRef}
                  type="file"
                  multiple
                  onChange={handleFileChange}
                  className="hidden"
                />
              </div>
            </div>

            {/* Files List */}
            {files.length > 0 && (
              <div className="mt-6 space-y-2">
                <h4 className="font-semibold text-slate-900 dark:text-slate-100">
                  Selected Files ({files.length})
                </h4>
                <div className="space-y-2 max-h-40 overflow-y-auto">
                  {files.map((file, i) => (
                    <div
                      key={i}
                      className="flex items-center justify-between p-3 bg-slate-50 dark:bg-slate-900 rounded-lg"
                    >
                      <div className="flex items-center gap-2 flex-1 min-w-0">
                        <File className="w-4 h-4 flex-shrink-0 text-slate-500" />
                        <div className="min-w-0 flex-1">
                          <p className="text-sm font-medium text-slate-900 dark:text-slate-100 truncate">
                            {file.name}
                          </p>
                          <p className="text-xs text-slate-500">
                            {formatFileSize(file.size)}
                          </p>
                        </div>
                      </div>
                      <button
                        onClick={() => removeFile(i)}
                        className="p-1 hover:bg-slate-200 dark:hover:bg-slate-800 rounded"
                      >
                        <X className="w-4 h-4 text-slate-500" />
                      </button>
                    </div>
                  ))}
                </div>
              </div>
            )}

            {/* Size Info */}
            <div className="mt-4 text-sm text-slate-600 dark:text-slate-400">
              <p>Total Size: {formatFileSize(totalSize)}</p>
              {remainingMB !== Infinity && (
                <p>Remaining: {remainingMB.toFixed(2)} MB</p>
              )}
            </div>
          </div>
        </div>

        {/* Transfer Details Section */}
        <div className="space-y-6">
          <div>
            <h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-4">
              Transfer Details
            </h3>
            <Card>
              <CardContent className="pt-6 space-y-4">
                <div>
                  <Label htmlFor="recipient" className="text-slate-700 dark:text-slate-300">
                    Recipient Email
                  </Label>
                  <Input
                    id="recipient"
                    type="email"
                    value={recipient}
                    onChange={(e) => setRecipient(e.target.value)}
                    placeholder="recipient@example.com"
                    className="mt-1"
                  />
                </div>

                <div>
                  <Label htmlFor="password" className="text-slate-700 dark:text-slate-300">
                    Encryption Password
                  </Label>
                  <Input
                    id="password"
                    type="password"
                    value={password}
                    onChange={(e) => setPassword(e.target.value)}
                    placeholder="Create a strong password"
                    className="mt-1"
                  />
                </div>

                <div>
                  <Label htmlFor="message" className="text-slate-700 dark:text-slate-300">
                    Message (optional)
                  </Label>
                  <Textarea
                    id="message"
                    value={message}
                    onChange={(e) => setMessage(e.target.value)}
                    placeholder="Add a message to your recipient..."
                    className="mt-1 resize-none"
                    rows={4}
                  />
                </div>

                {isOverLimit && (
                  <div className="p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded text-red-700 dark:text-red-400 text-sm">
                    ⚠️ File size exceeds your plan limits
                  </div>
                )}

                <Button
                  onClick={handleSubmit}
                  disabled={!files.length || isOverLimit || uploadStep !== ''}
                  className="w-full"
                >
                  <Send className="w-4 h-4 mr-2" />
                  Send Transfer
                </Button>

                {uploadMessage && (
                  <UploadStatusToast
                    step={uploadStep}
                    progress={uploadProgress}
                    message={uploadMessage}
                    currentChunk={currentChunk}
                    totalChunks={totalChunks}
                  />
                )}
              </CardContent>
            </Card>
          </div>
        </div>
      </div>
    </div>
  );
}
