import { useCallback, useRef, useState } from "react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { format } from "date-fns";
import {
  X, Paperclip, Upload, Trash2, FileText, ImageIcon, Loader2,
  ArrowUpCircle, ArrowDownCircle, ArrowLeftRight, TrendingUp,
} from "lucide-react";
import { cn } from "@/utils/cn";
import { formatCurrency } from "@/utils/currency";
import type { Transaction, AttachmentRef } from "@/api/transactions";
import { uploadAttachment, deleteAttachment, getAttachmentUrl } from "@/api/transactions";

const TYPE_COLORS = {
  income: "text-success",
  expense: "text-destructive",
  transfer: "text-muted-foreground",
  investment: "text-primary",
};

const TYPE_ICONS = {
  income: ArrowUpCircle,
  expense: ArrowDownCircle,
  transfer: ArrowLeftRight,
  investment: TrendingUp,
};

const TYPE_BG = {
  income: "bg-success/10",
  expense: "bg-destructive/10",
  transfer: "bg-secondary",
  investment: "bg-primary/10",
};

function humanFileSize(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

function FileIcon({ mimeType }: { mimeType: string }) {
  if (mimeType === "application/pdf") return <FileText className="w-4 h-4 shrink-0" />;
  return <ImageIcon className="w-4 h-4 shrink-0" />;
}

interface Props {
  transaction: Transaction;
  accountName?: string;
  categoryName?: string;
  onClose: () => void;
}

export default function TransactionDetailDrawer({ transaction, accountName, categoryName, onClose }: Props) {
  const qc = useQueryClient();
  const [attachments, setAttachments] = useState<AttachmentRef[]>(transaction.attachment_refs ?? []);
  const [dragging, setDragging] = useState(false);
  const [uploadError, setUploadError] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const Icon = TYPE_ICONS[transaction.type] ?? ArrowDownCircle;

  const uploadMutation = useMutation({
    mutationFn: (file: File) => uploadAttachment(transaction.id, file),
    onSuccess: (ref) => {
      setAttachments((prev) => [...prev, ref]);
      qc.invalidateQueries({ queryKey: ["transactions"] });
      setUploadError(null);
    },
    onError: (err: any) => {
      setUploadError(err?.response?.data?.detail ?? "Upload failed");
    },
  });

  const deleteMutation = useMutation({
    mutationFn: (attachmentId: string) => deleteAttachment(transaction.id, attachmentId),
    onSuccess: (_data, attachmentId) => {
      setAttachments((prev) => prev.filter((a) => a.id !== attachmentId));
      qc.invalidateQueries({ queryKey: ["transactions"] });
    },
  });

  const handleFiles = useCallback((files: FileList | null) => {
    if (!files) return;
    setUploadError(null);
    for (const file of Array.from(files)) {
      uploadMutation.mutate(file);
    }
  }, [uploadMutation]);

  const onDragOver = (e: React.DragEvent) => { e.preventDefault(); setDragging(true); };
  const onDragLeave = () => setDragging(false);
  const onDrop = (e: React.DragEvent) => {
    e.preventDefault();
    setDragging(false);
    handleFiles(e.dataTransfer.files);
  };

  return (
    <>
      {/* Backdrop */}
      <div
        className="fixed inset-0 z-40 bg-black/40"
        onClick={onClose}
      />

      {/* Drawer */}
      <div className="fixed right-0 top-0 bottom-0 z-50 w-full max-w-md bg-card border-l border-border shadow-2xl flex flex-col overflow-hidden">
        {/* Header */}
        <div className="flex items-center justify-between px-5 py-4 border-b border-border shrink-0">
          <div className="flex items-center gap-3 min-w-0">
            <div className={cn("w-9 h-9 rounded-full flex items-center justify-center shrink-0", TYPE_BG[transaction.type])}>
              <Icon className={cn("w-4 h-4", TYPE_COLORS[transaction.type])} />
            </div>
            <div className="min-w-0">
              <p className="font-semibold truncate">{transaction.description}</p>
              <p className="text-xs text-muted-foreground">
                {format(new Date(transaction.date), "dd MMMM yyyy")}
              </p>
            </div>
          </div>
          <button onClick={onClose} className="ml-2 shrink-0 text-muted-foreground hover:text-foreground p-1 rounded transition-colors">
            <X className="w-5 h-5" />
          </button>
        </div>

        {/* Body */}
        <div className="flex-1 overflow-y-auto p-5 space-y-5">
          {/* Amount */}
          <div className="bg-secondary/50 rounded-xl p-4 text-center">
            <p className={cn("text-3xl font-bold tabular-nums", TYPE_COLORS[transaction.type])}>
              {transaction.amount >= 0 ? "+" : ""}
              {formatCurrency(transaction.amount, transaction.currency)}
            </p>
            {transaction.amount_base !== null && transaction.currency !== transaction.base_currency && (
              <p className="text-xs text-muted-foreground mt-1">
                ≈ {formatCurrency(transaction.amount_base, transaction.base_currency)}
              </p>
            )}
          </div>

          {/* Detail rows */}
          <div className="space-y-2 text-sm">
            {[
              ["Account", accountName ?? "—"],
              ["Category", categoryName ?? "Uncategorised"],
              ["Status", transaction.status.charAt(0).toUpperCase() + transaction.status.slice(1)],
              ["Type", transaction.type.charAt(0).toUpperCase() + transaction.type.slice(1)],
              ...(transaction.merchant ? [["Merchant", transaction.merchant]] : []),
              ...(transaction.notes ? [["Notes", transaction.notes]] : []),
            ].map(([label, value]) => (
              <div key={label} className="flex justify-between gap-4 py-1.5 border-b border-border/50 last:border-0">
                <span className="text-muted-foreground shrink-0">{label}</span>
                <span className="text-right break-words">{value}</span>
              </div>
            ))}
            {transaction.tags.length > 0 && (
              <div className="flex justify-between gap-4 py-1.5">
                <span className="text-muted-foreground shrink-0">Tags</span>
                <div className="flex flex-wrap gap-1 justify-end">
                  {transaction.tags.map((t) => (
                    <span key={t} className="text-xs bg-secondary px-2 py-0.5 rounded-full">{t}</span>
                  ))}
                </div>
              </div>
            )}
          </div>

          {/* Attachments */}
          <div>
            <div className="flex items-center gap-2 mb-3">
              <Paperclip className="w-4 h-4 text-muted-foreground" />
              <h3 className="text-sm font-semibold">Receipts & Attachments</h3>
              <span className="text-xs text-muted-foreground ml-auto">{attachments.length}/10</span>
            </div>

            {/* Existing attachments */}
            {attachments.length > 0 && (
              <div className="space-y-2 mb-3">
                {attachments.map((att) => (
                  <div
                    key={att.id}
                    className="flex items-center gap-3 bg-secondary/50 rounded-lg px-3 py-2 group"
                  >
                    <FileIcon mimeType={att.mime_type} />
                    <div className="flex-1 min-w-0">
                      <a
                        href={getAttachmentUrl(transaction.id, att.id)}
                        target="_blank"
                        rel="noopener noreferrer"
                        className="text-sm font-medium truncate hover:text-primary transition-colors block"
                        download={att.filename}
                      >
                        {att.filename}
                      </a>
                      <p className="text-xs text-muted-foreground">{humanFileSize(att.size)}</p>
                    </div>
                    <button
                      onClick={() => deleteMutation.mutate(att.id)}
                      disabled={deleteMutation.isPending}
                      className="shrink-0 text-muted-foreground hover:text-destructive opacity-0 group-hover:opacity-100 transition-all p-1 rounded"
                    >
                      {deleteMutation.isPending ? (
                        <Loader2 className="w-3.5 h-3.5 animate-spin" />
                      ) : (
                        <Trash2 className="w-3.5 h-3.5" />
                      )}
                    </button>
                  </div>
                ))}
              </div>
            )}

            {/* Drop zone */}
            {attachments.length < 10 && (
              <div
                onDragOver={onDragOver}
                onDragLeave={onDragLeave}
                onDrop={onDrop}
                onClick={() => fileInputRef.current?.click()}
                className={cn(
                  "border-2 border-dashed rounded-xl p-5 text-center cursor-pointer transition-colors select-none",
                  dragging
                    ? "border-primary bg-primary/5"
                    : "border-border hover:border-primary/50 hover:bg-secondary/30"
                )}
              >
                {uploadMutation.isPending ? (
                  <div className="flex flex-col items-center gap-2 text-muted-foreground">
                    <Loader2 className="w-6 h-6 animate-spin" />
                    <p className="text-sm">Uploading…</p>
                  </div>
                ) : (
                  <div className="flex flex-col items-center gap-2 text-muted-foreground">
                    <Upload className="w-6 h-6" />
                    <p className="text-sm font-medium">Drop files here or click to browse</p>
                    <p className="text-xs">JPEG, PNG, WebP, PDF — max 10 MB</p>
                  </div>
                )}
              </div>
            )}

            <input
              ref={fileInputRef}
              type="file"
              multiple
              accept=".jpg,.jpeg,.png,.webp,.pdf,image/jpeg,image/png,image/webp,application/pdf"
              className="sr-only"
              onChange={(e) => handleFiles(e.target.files)}
            />

            {uploadError && (
              <p className="text-destructive text-xs mt-2">{uploadError}</p>
            )}
          </div>
        </div>
      </div>
    </>
  );
}
