"use client";

import {
  Dialog,
  DialogBackdrop,
  DialogPanel,
  DialogTitle,
  Transition,
  TransitionChild,
} from "@headlessui/react";
import { Fragment, useRef, useState, DragEvent } from "react";
import * as XLSX from "xlsx";
import {
  XMarkIcon,
  DocumentTextIcon,
  ArrowDownTrayIcon,
  CloudArrowUpIcon,
  InformationCircleIcon,
  ArrowRightIcon,
  CheckCircleIcon,
  ExclamationCircleIcon,
} from "@heroicons/react/24/outline";
import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
import { useCreateBulkUpload } from "@/lib/bulkUpload/client";

const MAX_FILE_SIZE_MB = 50;
const ALLOWED_EXTENSIONS = [".csv", ".xlsx", ".xls"];
const CONTENT_TYPES: Record<string, string> = {
  ".csv": "text/csv",
  ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  ".xls": "application/vnd.ms-excel",
};

interface BulkUploadComingSoonModalProps {
  isOpen: boolean;
  onClose: () => void;
  portfolioId: string;
}

function downloadTemplate() {
  const ws = XLSX.utils.aoa_to_sheet([["Internal Reference (Optional)", "Address", "Postcode"]]);
  const wb = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(wb, ws, "Properties");
  XLSX.writeFile(wb, "bulk_upload_template.xlsx");
}

function getFileExtension(filename: string): string {
  return filename.slice(filename.lastIndexOf(".")).toLowerCase();
}

function generateS3Key(userId: string, portfolioId: string, ext: string): string {
  const timestamp = new Date().toISOString().replace(/[:.-]/g, "");
  return `bulk-addresses/${userId}/${portfolioId}/${timestamp}/addresses${ext}`;
}

function validateFile(file: File): string | null {
  const sizeMB = file.size / (1024 * 1024);
  if (sizeMB > MAX_FILE_SIZE_MB) {
    return `File too large. Max ${MAX_FILE_SIZE_MB}MB.`;
  }
  const ext = getFileExtension(file.name);
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
    return "Only CSV or Excel files allowed.";
  }
  return null;
}

async function validateHeaders(file: File): Promise<{ error: string | null; headers: string[] }> {
  const ext = getFileExtension(file.name);
  let headers: string[] = [];

  if (ext === ".csv") {
    const text = await file.text();
    const firstLine = text.split(/\r?\n/)[0] ?? "";
    headers = firstLine.split(",").map((h) => h.trim().replace(/^["']|["']$/g, ""));
  } else {
    const buffer = await file.arrayBuffer();
    const wb = XLSX.read(buffer, { sheetRows: 1 });
    const sheet = wb.Sheets[wb.SheetNames[0]];
    const rows = XLSX.utils.sheet_to_json<unknown[]>(sheet, { header: 1, defval: "" });
    headers = ((rows[0] as unknown[]) ?? []).map((h) => String(h ?? "").trim());
  }

  headers = headers.filter((h) => h.length > 0);

  const normalised = headers.map((h) => h.toLowerCase());
  const hasAddress = normalised.some((h) => h.startsWith("address"));
  const hasPostcode = normalised.some((h) => h === "postcode");

  if (!hasAddress && !hasPostcode) {
    return { error: "Missing required columns: Address and Postcode.", headers };
  }
  if (!hasAddress) {
    return { error: "Missing required column: Address (or Address 1, Address 2, etc.).", headers };
  }
  if (!hasPostcode) {
    return { error: 'Missing required column: "Postcode".', headers };
  }
  return { error: null, headers };
}

export default function BulkUploadComingSoonModal({
  isOpen,
  onClose,
  portfolioId,
}: BulkUploadComingSoonModalProps) {
  const session = useSession();
  const router = useRouter();
  const fileInputRef = useRef<HTMLInputElement>(null);
  const createUpload = useCreateBulkUpload();

  const [isDragging, setIsDragging] = useState(false);
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const [sourceHeaders, setSourceHeaders] = useState<string[]>([]);
  const [validationError, setValidationError] = useState<string | null>(null);
  const [validating, setValidating] = useState(false);
  const [uploadProgress, setUploadProgress] = useState<number | null>(null);

  const uploading = createUpload.isPending;
  const uploadError = createUpload.error
    ? "Upload failed. Please try again, or contact a Domna representative if the issue persists."
    : null;

  async function handleFile(file: File) {
    createUpload.reset();
    setSelectedFile(null);
    setValidationError(null);

    const sizeOrTypeError = validateFile(file);
    if (sizeOrTypeError) {
      setValidationError(sizeOrTypeError);
      return;
    }

    setValidating(true);
    const { error: headerError, headers } = await validateHeaders(file);
    setValidating(false);

    if (headerError) {
      setValidationError(headerError);
      return;
    }

    setSourceHeaders(headers);
    setSelectedFile(file);
  }

  function handleDragOver(e: DragEvent<HTMLDivElement>) {
    e.preventDefault();
    setIsDragging(true);
  }

  function handleDragLeave() {
    setIsDragging(false);
  }

  function handleDrop(e: DragEvent<HTMLDivElement>) {
    e.preventDefault();
    setIsDragging(false);
    const file = e.dataTransfer.files[0];
    if (file) handleFile(file);
  }

  function handleInputChange(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    if (file) handleFile(file);
  }

  function handleClose() {
    setSelectedFile(null);
    setSourceHeaders([]);
    setValidationError(null);
    setValidating(false);
    setUploadProgress(null);
    createUpload.reset();
    onClose();
  }

  function handleUpload() {
    const userId = String(session.data?.user?.dbId ?? "");
    if (!selectedFile || !userId) return;

    const ext = getFileExtension(selectedFile.name);
    const contentType = CONTENT_TYPES[ext] ?? "application/octet-stream";
    const fileKey = generateS3Key(userId, portfolioId, ext);
    setUploadProgress(0);

    createUpload.mutate(
      {
        file: selectedFile,
        portfolioId,
        userId,
        sourceHeaders,
        contentType,
        fileKey,
        onProgress: setUploadProgress,
      },
      {
        onSuccess: ({ id: uploadId }) => {
          router.push(`/portfolio/${portfolioId}/bulk-upload/${uploadId}/map-columns`);
          onClose();
        },
        onSettled: () => setUploadProgress(null),
      }
    );
  }

  const canUpload = !!selectedFile && !uploading && !validating;

  return (
    <Transition appear show={isOpen} as={Fragment}>
      <Dialog as="div" className="relative z-[9999]" onClose={handleClose}>
        {/* Backdrop */}
        <TransitionChild
          as={Fragment}
          enter="ease-out duration-200"
          enterFrom="opacity-0"
          enterTo="opacity-100"
          leave="ease-in duration-150"
          leaveFrom="opacity-100"
          leaveTo="opacity-0"
        >
          <DialogBackdrop className="fixed inset-0 bg-gray-900/40 backdrop-blur-sm" />
        </TransitionChild>

        {/* Panel */}
        <div className="fixed inset-0 flex items-center justify-center p-4">
          <TransitionChild
            as={Fragment}
            enter="ease-out duration-200"
            enterFrom="opacity-0 scale-95 translate-y-2"
            enterTo="opacity-100 scale-100 translate-y-0"
            leave="ease-in duration-150"
            leaveFrom="opacity-100 scale-100 translate-y-0"
            leaveTo="opacity-0 scale-95 translate-y-2"
          >
            <DialogPanel className="w-full max-w-2xl bg-white rounded-2xl shadow-[0_40px_60px_-15px_rgba(21,29,33,0.15)] overflow-hidden flex flex-col">

              {/* Header */}
              <div className="px-10 pt-10 pb-6 flex justify-between items-start">
                <div>
                  <DialogTitle className="text-2xl font-extrabold text-gray-900 tracking-tight mb-2">
                    Bulk Upload: New Properties
                  </DialogTitle>
                  <p className="text-sm text-gray-500 leading-relaxed max-w-md">
                    This workflow is designed for adding new residential or commercial
                    assets to your portfolio. Upload your dataset to begin the
                    transformation.
                  </p>
                </div>
                <button
                  onClick={handleClose}
                  className="p-2 hover:bg-gray-100 rounded-full transition-colors ml-4 shrink-0"
                >
                  <XMarkIcon className="h-5 w-5 text-gray-400" />
                </button>
              </div>

              {/* Content */}
              <div className="px-10 py-2 space-y-5">

                {/* Template section */}
                <div className="bg-gray-50 p-5 rounded-xl flex items-center justify-between">
                  <div className="flex items-center gap-4">
                    <div className="w-11 h-11 rounded-lg bg-gray-100 flex items-center justify-center shrink-0">
                      <DocumentTextIcon className="h-6 w-6 text-midblue" />
                    </div>
                    <div>
                      <p className="text-sm font-semibold text-gray-900">Required Template Format</p>
                      <p className="text-xs text-gray-500 mt-0.5">
                        Must contain:{" "}
                        <span className="font-medium text-midblue">
                          Address, Postcode
                        </span>
                      </p>
                    </div>
                  </div>
                  <button
                    onClick={downloadTemplate}
                    className="flex items-center gap-1.5 text-xs font-semibold text-midblue hover:text-gray-900 transition-colors shrink-0 ml-4"
                  >
                    <ArrowDownTrayIcon className="h-4 w-4" />
                    Download template
                  </button>
                </div>

                {/* Dropzone */}
                <div
                  onClick={() => !uploading && fileInputRef.current?.click()}
                  onDragOver={handleDragOver}
                  onDragLeave={handleDragLeave}
                  onDrop={handleDrop}
                  className={`border-2 border-dashed rounded-2xl p-12 flex flex-col items-center justify-center transition-colors ${
                    uploading || validating
                      ? "border-gray-200 bg-gray-50 cursor-default"
                      : validationError
                      ? "border-red-300 bg-red-50 cursor-pointer"
                      : isDragging
                      ? "border-midblue bg-blue-50 cursor-copy"
                      : selectedFile
                      ? "border-green-400 bg-green-50 cursor-pointer"
                      : "border-gray-200 hover:border-gray-300 hover:bg-gray-50 cursor-pointer"
                  }`}
                >
                  <input
                    ref={fileInputRef}
                    type="file"
                    accept=".csv,.xlsx,.xls"
                    className="hidden"
                    onChange={handleInputChange}
                    onClick={(e) => e.stopPropagation()}
                  />

                  {validating ? (
                    <>
                      <div className="w-14 h-14 rounded-full bg-gray-100 flex items-center justify-center mb-4">
                        <span className="h-6 w-6 rounded-full border-2 border-midblue border-t-transparent animate-spin" />
                      </div>
                      <p className="text-base font-bold text-gray-900 mb-1">Checking headers…</p>
                      <p className="text-xs text-gray-400">Validating column structure</p>
                    </>
                  ) : uploading ? (
                    <>
                      <div className="w-14 h-14 rounded-full bg-gray-100 flex items-center justify-center mb-4">
                        <CloudArrowUpIcon className="h-7 w-7 text-midblue" />
                      </div>
                      <p className="text-base font-bold text-gray-900 mb-1">Uploading…</p>
                      <p className="text-xs text-gray-400 mb-4">{selectedFile?.name}</p>
                      <div className="w-full max-w-xs bg-gray-200 rounded-full h-2">
                        <div
                          className="bg-midblue h-2 rounded-full transition-all duration-200"
                          style={{ width: `${uploadProgress ?? 0}%` }}
                        />
                      </div>
                      <p className="text-xs text-gray-400 mt-1">{uploadProgress ?? 0}%</p>
                    </>
                  ) : validationError ? (
                    <>
                      <ExclamationCircleIcon className="h-14 w-14 text-red-400 mb-4" />
                      <p className="text-base font-bold text-red-600 mb-1">{validationError}</p>
                      <p className="text-xs text-gray-400">Click to choose a different file</p>
                    </>
                  ) : selectedFile ? (
                    <>
                      <CheckCircleIcon className="h-14 w-14 text-green-400 mb-4" />
                      <p className="text-base font-bold text-gray-900 mb-1">{selectedFile.name}</p>
                      <p className="text-xs text-gray-400">Click to change file</p>
                    </>
                  ) : (
                    <>
                      <div className="w-14 h-14 rounded-full bg-gray-100 flex items-center justify-center mb-4">
                        <CloudArrowUpIcon className="h-7 w-7 text-midblue" />
                      </div>
                      <p className="text-base font-bold text-gray-900 mb-1">
                        Drag and drop CSV or XLSX
                      </p>
                      <p className="text-xs text-gray-400">
                        or <span className="text-midblue font-semibold">click to browse</span> · Max {MAX_FILE_SIZE_MB}MB
                      </p>
                    </>
                  )}
                </div>

                {/* Upload error */}
                {uploadError && (
                  <p className="text-xs text-red-500 flex items-center gap-1.5">
                    <ExclamationCircleIcon className="h-4 w-4 shrink-0" />
                    {uploadError}
                  </p>
                )}

                {/* Info strip */}
                <div className="flex items-center gap-3 text-xs text-gray-500 bg-gray-50 px-4 py-3 rounded-lg">
                  <InformationCircleIcon className="h-4 w-4 text-midblue shrink-0" />
                  <span>
                    Properties will be automatically validated against national
                    architectural databases.
                  </span>
                </div>
              </div>

              {/* Footer */}
              <div className="px-10 py-7 mt-4 flex items-center justify-between bg-gray-50/50">
                <div className="flex items-center gap-4">
                  <button
                    onClick={handleClose}
                    className="text-sm font-semibold text-gray-400 hover:text-gray-700 transition-colors"
                  >
                    Cancel and Exit
                  </button>
                  <button
                    onClick={() => { handleClose(); router.push(`/portfolio/${portfolioId}/bulk-upload`); }}
                    className="text-sm font-semibold text-midblue hover:text-gray-900 transition-colors"
                  >
                    View previous uploads
                  </button>
                </div>
                <div className="flex items-center gap-3">
                  <button
                    onClick={handleUpload}
                    disabled={!canUpload}
                    className={`flex items-center gap-2 px-7 py-2.5 rounded-2xl bg-gradient-to-br from-[#14163d] to-[#15173e] text-white text-sm font-bold transition-opacity ${
                      canUpload ? "opacity-100 hover:opacity-90" : "opacity-40 cursor-not-allowed"
                    }`}
                  >
                    {uploading ? (
                      <>
                        <span className="h-4 w-4 rounded-full border-2 border-white border-t-transparent animate-spin" />
                        Uploading…
                      </>
                    ) : (
                      <>
                        Upload File
                        <ArrowRightIcon className="h-4 w-4" />
                      </>
                    )}
                  </button>
                </div>
              </div>

            </DialogPanel>
          </TransitionChild>
        </div>
      </Dialog>
    </Transition>
  );
}
