import * as React from "react";
import * as XLSX from "xlsx";

import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { FileText, X, Download, DatabaseIcon } from "lucide-react";
import { useMutation } from "@tanstack/react-query";
import { apiRequest, queryClient } from "@/lib/queryClient";
import { toast } from "@/hooks/use-toast";
import { QK_PAYMENTS_RECENT_BASE } from "@/components/payments/payments-recent-table";
import {
  MultipleFileUploadZone,
  MultipleFileUploadZoneHandle,
} from "../file-upload/multiple-file-upload-zone";

type Row    = Record<string, string>;
type Header = Record<string, string>;

const COLUMNS: { key: string; label: string }[] = [
  { key: "Patient Name",     label: "Patient Name" },
  { key: "Member #",         label: "Member #" },
  { key: "ICN",              label: "ICN" },
  { key: "Submitted Code",   label: "Submitted Code" },
  { key: "Paid Code",        label: "Paid Code" },
  { key: "Tooth",            label: "Tooth" },
  { key: "Date of Service",  label: "Date of Service" },
  { key: "Submitted Amount", label: "Submitted ($)" },
  { key: "Allowed Amount",   label: "Allowed ($)" },
  { key: "Paid Amount",      label: "Paid ($)" },
];

const SUMMARY_FIELDS = [
  "Source File",
  "Payee ID",
  "Business NPI",
  "Run #",
  "RA #",
  "RA Date",
  "Claim Detail Amount",
  "Claim Adjustment Amount",
  "Misc. Adjustment Amount",
  "Payment Amount",
];

// Convert a string value to a number if it looks numeric, otherwise keep as string.
// Handles: "36.00" → 36, "$14,369.00" → 14369, "($3,107.39)" → -3107.39
function toExcelValue(val: string): string | number {
  if (!val) return "";
  const stripped = val
    .replace(/\$/g, "")
    .replace(/,/g, "")
    .replace(/^\((.+)\)$/, "-$1")  // (3,107.39) → -3107.39
    .trim();
  const num = Number(stripped);
  return stripped !== "" && !isNaN(num) ? num : val;
}

function downloadExcel(rows: Row[], headers: Header[], sourceFileName: string) {
  const wb = XLSX.utils.book_new();

  // Sheet 1 — RA Summary (one row per uploaded PDF)
  if (headers.length > 0) {
    const summaryData = headers.map((h) => {
      const out: Record<string, string | number> = {};
      SUMMARY_FIELDS.forEach((f) => { out[f] = toExcelValue(h[f] ?? ""); });
      return out;
    });
    const wsSummary = XLSX.utils.json_to_sheet(summaryData, {
      header: SUMMARY_FIELDS,
    });
    XLSX.utils.book_append_sheet(wb, wsSummary, "RA Summary");
  }

  // Sheet 2 — Payment Data (one row per ICN)
  const data = rows.map((row) => {
    const out: Record<string, string | number> = {};
    COLUMNS.forEach(({ key, label }) => { out[label] = toExcelValue(row[key] ?? ""); });
    return out;
  });
  const wsData = XLSX.utils.json_to_sheet(data, {
    header: COLUMNS.map((c) => c.label),
  });
  XLSX.utils.book_append_sheet(wb, wsData, "Payment Data");

  const name = sourceFileName.replace(/\.pdf$/i, "") || "payment_extract";
  XLSX.writeFile(wb, `${name}.xlsx`);
}

export default function PaymentUploadDocumentsBlock() {
  const MAX_FILES = 10;
  const ACCEPTED_FILE_TYPES = "application/pdf";

  const uploadZoneRef = React.useRef<MultipleFileUploadZoneHandle | null>(null);
  const [filesForUI, setFilesForUI] = React.useState<File[]>([]);
  const [isUploading] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);

  // ── shared extract helper ────────────────────────────────────────────────
  const extractData = async (files: File[]): Promise<{ rows: Row[]; headers: Header[] }> => {
    const formData = new FormData();
    files.forEach((file) => formData.append("files", file, file.name));
    const res = await apiRequest("POST", "/api/payment-pdf/extract", formData);
    if (!res.ok) {
      const err = await res.json().catch(() => ({}));
      throw new Error(err?.error || "Failed to extract PDF data");
    }
    const data = (await res.json()) as { rows: Row[]; headers: Header[] };
    return { rows: data.rows ?? [], headers: data.headers ?? [] };
  };

  const getFiles = () => {
    const files = uploadZoneRef.current?.getFiles() ?? [];
    if (!files.length) {
      setError("Please upload at least one PDF file.");
      return null;
    }
    setError(null);
    return files;
  };

  // ── Extract & Download ───────────────────────────────────────────────────
  const downloadMutation = useMutation({
    mutationFn: async (files: File[]) => {
      const { rows, headers } = await extractData(files);
      return { rows, headers, sourceName: files[0]?.name ?? "payment_extract" };
    },
    onSuccess: ({ rows, headers, sourceName }) => {
      if (rows.length === 0) {
        toast({ title: "No data", description: "No rows were extracted from the PDF.", variant: "destructive" });
        return;
      }
      downloadExcel(rows, headers, sourceName);
      toast({ title: "Downloaded", description: `${rows.length} rows exported to Excel.` });
    },
    onError: (err: any) => {
      toast({ title: "Error", description: err.message, variant: "destructive" });
    },
  });

  // ── Extract & Import ─────────────────────────────────────────────────────
  const importMutation = useMutation({
    mutationFn: async (files: File[]) => {
      const { rows } = await extractData(files);
      if (rows.length === 0) throw new Error("No rows extracted from the PDF.");
      const res = await apiRequest("POST", "/api/payment-pdf/import", { rows });
      if (!res.ok) {
        const err = await res.json().catch(() => ({}));
        throw new Error(err?.error || "Import failed");
      }
      return res.json();
    },
    onSuccess: async (data) => {
      toast({
        title: "Imported",
        description: `${data.paymentIds?.length ?? 0} payment(s) created successfully.`,
      });
      await queryClient.invalidateQueries({ queryKey: QK_PAYMENTS_RECENT_BASE });
    },
    onError: (err: any) => {
      toast({ title: "Error", description: err.message, variant: "destructive" });
    },
  });

  const handleZoneFilesChange = React.useCallback((files: File[]) => {
    setFilesForUI(files);
    setError(null);
  }, []);

  const removeUploadedFile = React.useCallback((index: number) => {
    uploadZoneRef.current?.removeFile(index);
  }, []);

  const busy = downloadMutation.isPending || importMutation.isPending;

  return (
    <div className="mb-8">
      <Card>
        <CardHeader>
          <CardTitle>Upload Payment Documents</CardTitle>
          <CardDescription>
            Upload up to 10 MassHealth remittance PDFs. Extract and download as
            Excel, or import directly into the database.
          </CardDescription>
        </CardHeader>

        <CardContent>
          <div className="bg-gray-100 p-4 rounded-md space-y-4">
            <MultipleFileUploadZone
              ref={uploadZoneRef}
              isUploading={isUploading}
              acceptedFileTypes={ACCEPTED_FILE_TYPES}
              maxFiles={MAX_FILES}
              onFilesChange={handleZoneFilesChange}
            />

            {filesForUI.length > 0 && (
              <div>
                <p className="text-sm text-gray-600 mb-2">
                  Uploaded ({filesForUI.length}/{MAX_FILES})
                </p>
                <ul className="space-y-2 max-h-48 overflow-auto">
                  {filesForUI.map((file, idx) => (
                    <li
                      key={`${file.name}-${file.size}-${idx}`}
                      className="flex items-center justify-between border rounded-md p-2 bg-white"
                    >
                      <div className="flex items-center gap-3">
                        <FileText className="h-6 w-6 text-blue-500" />
                        <div className="text-left">
                          <p className="font-medium text-blue-700 truncate">{file.name}</p>
                          <p className="text-sm text-gray-500">
                            {(file.size / 1024 / 1024).toFixed(2)} MB
                          </p>
                        </div>
                      </div>
                      <Button variant="ghost" size="sm" onClick={() => removeUploadedFile(idx)}>
                        <X className="h-4 w-4" />
                      </Button>
                    </li>
                  ))}
                </ul>
              </div>
            )}
          </div>

          <div className="mt-4 flex gap-3">
            {/* Extract & Download */}
            <Button
              className="flex-1 h-12 gap-2 bg-blue-600 hover:bg-blue-700 text-white"
              type="button"
              disabled={busy || !filesForUI.length}
              onClick={() => {
                const files = getFiles();
                if (files) downloadMutation.mutate(files);
              }}
            >
              <Download className="h-4 w-4" />
              {downloadMutation.isPending ? "Extracting…" : "Extract & Download"}
            </Button>

            {/* Extract & Import */}
            <Button
              className="flex-1 h-12 gap-2 bg-teal-600 hover:bg-teal-700 text-white"
              type="button"
              disabled={busy || !filesForUI.length}
              onClick={() => {
                const files = getFiles();
                if (files) importMutation.mutate(files);
              }}
            >
              <DatabaseIcon className="h-4 w-4" />
              {importMutation.isPending ? "Importing…" : "Extract & Import"}
            </Button>
          </div>

          {error && <p className="mt-3 text-sm text-red-600">{error}</p>}
        </CardContent>
      </Card>
    </div>
  );
}
