"use client";

import { useMemo, useRef, useState } from "react";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";

type PreviewResponse = {
  previewRows: Array<{
    source_row_number: number;
    primary_country_code: string;
    approved_document_name: string;
    sent_email_name: string;
    opened: number;
    clicked: number;
    sent_date: string | null;
  }>;
  parsedRows: number;
  documentBrandCount?: number;
  sentimentRows?: number;
  sentimentEmailCount?: number;
  detectedCountries: string[];
  warnings: string[];
  errors: string[];
};

type CommitResponse = {
  importId: number;
  insertedRows: number;
  updatedRows: number;
  failedRows: number;
  warnings: string[];
  sentimentRows?: number;
  sentimentEmailCount?: number;
  sentimentUpdatedRows?: number;
};

const MAX_IMPORT_FILE_BYTES = 25 * 1024 * 1024;
const ALLOWED_IMPORT_EXTENSIONS = new Set(["xlsx", "xls", "csv"]);

function getFileValidationError(file: File | null) {
  if (!file) return null;
  const ext = file.name.split(".").pop()?.toLowerCase() ?? "";
  if (!ALLOWED_IMPORT_EXTENSIONS.has(ext)) {
    return "Unsupported file type. Upload .xlsx, .xls, or .csv.";
  }
  if (file.size > MAX_IMPORT_FILE_BYTES) {
    return "File too large. Max size is 25MB.";
  }
  return null;
}

export function UploadClient({
  role,
  allowedCountries,
  selectedScope,
  selectedScopeCountries,
}: {
  role: "admin" | "affiliate";
  allowedCountries: string[];
  selectedScope: string;
  selectedScopeCountries: string[];
}) {
  const [file, setFile] = useState<File | null>(null);
  const [preview, setPreview] = useState<PreviewResponse | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<string | null>(null);
  const [previewLoading, setPreviewLoading] = useState(false);
  const [commitLoading, setCommitLoading] = useState(false);
  const fileInputRef = useRef<HTMLInputElement | null>(null);

  const canCommit = useMemo(
    () =>
      Boolean(
        file &&
          preview &&
          preview.errors.length === 0 &&
          (preview.parsedRows > 0 || (preview.sentimentRows ?? 0) > 0),
      ),
    [file, preview],
  );
  const fileSummary = file
    ? `${file.name} • ${(file.size / (1024 * 1024)).toFixed(2)} MB`
    : "No file selected";

  async function previewFile() {
    if (!file) return;
    const fileError = getFileValidationError(file);
    if (fileError) {
      setError(fileError);
      return;
    }
    setPreviewLoading(true);
    setError(null);
    setSuccess(null);

    try {
      const formData = new FormData();
      formData.append("file", file);
      if (role === "admin" && selectedScope) {
        formData.append("scope", selectedScope);
      }

      const response = await fetch("/api/imports/preview", {
        method: "POST",
        body: formData,
      });

      const payload = (await response.json()) as PreviewResponse & { message?: string };

      if (!response.ok) {
        throw new Error(payload.message ?? "Preview failed.");
      }

      setPreview(payload);
    } catch (err) {
      setPreview(null);
      setError(err instanceof Error ? err.message : "Preview failed.");
    } finally {
      setPreviewLoading(false);
    }
  }

  async function commitFile() {
    if (!file || !preview) return;
    const fileError = getFileValidationError(file);
    if (fileError) {
      setError(fileError);
      return;
    }
    setCommitLoading(true);
    setError(null);
    setSuccess(null);

    try {
      const formData = new FormData();
      formData.append("file", file);
      if (role === "admin" && selectedScope) {
        formData.append("scope", selectedScope);
      }

      const response = await fetch("/api/imports/commit", {
        method: "POST",
        body: formData,
      });

      const payload = (await response.json()) as CommitResponse & { message?: string };
      if (!response.ok) {
        throw new Error(payload.message ?? "Commit failed.");
      }

      const sentimentSummary =
        (payload.sentimentRows ?? 0) > 0
          ? ` Sentiment rows: ${payload.sentimentRows} across ${payload.sentimentEmailCount ?? 0} emails.`
          : "";
      setSuccess(
        `Import #${payload.importId} completed: ${payload.insertedRows} inserted, ${payload.updatedRows} updated, ${payload.failedRows} failed.${sentimentSummary}`,
      );
      setPreview(null);
      setFile(null);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Commit failed.");
    } finally {
      setCommitLoading(false);
    }
  }

  return (
    <div className="space-y-4">
      <Card className="bg-[linear-gradient(160deg,#ffffff_0%,#f6fbff_72%,#fff8ef_100%)]">
        <div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_auto_auto]">
          <div>
            <label className="caption text-xs uppercase tracking-[0.16em] text-slate-500">
              VEEVA Import File
            </label>
            <input
              ref={fileInputRef}
              type="file"
              accept=".xlsx,.xls,.csv"
              onChange={(event) => {
                const nextFile = event.target.files?.[0] ?? null;
                setPreview(null);
                setSuccess(null);
                const fileError = getFileValidationError(nextFile);
                setError(fileError);
                setFile(fileError ? null : nextFile);
              }}
              className="sr-only"
            />
            <div className="mt-2 flex items-center gap-3 rounded-xl border border-[#d6e3f2] bg-white px-3 py-2 shadow-[inset_0_1px_2px_rgba(15,23,42,0.04)]">
              <Button
                type="button"
                variant="secondary"
                className="h-9 rounded-lg px-3 text-xs"
                onClick={() => fileInputRef.current?.click()}
              >
                {file ? "Change file" : "Select file"}
              </Button>
              <p className="min-w-0 flex-1 truncate text-sm text-slate-700">{fileSummary}</p>
              {file ? (
                <button
                  type="button"
                  onClick={() => {
                    setFile(null);
                    setPreview(null);
                    setError(null);
                    setSuccess(null);
                    if (fileInputRef.current) {
                      fileInputRef.current.value = "";
                    }
                  }}
                  className="text-xs font-semibold text-[#2663AC] transition hover:text-[#1d4f8c]"
                >
                  Clear
                </button>
              ) : null}
            </div>
            <p className="mt-2 text-xs text-slate-500">
              {role === "admin"
                ? selectedScope
                  ? `Admin upload scope: ${selectedScope} (${selectedScopeCountries.join(
                      ", ",
                    )}). Rows outside this scope will be rejected.`
                  : "Admin upload scope: all countries. Select a dashboard scope in the Admin Bar to enforce country validation."
                : `Affiliate upload scope: ${allowedCountries.length ? allowedCountries.join(", ") : "None assigned"}.`}
            </p>
            <div className="mt-3 grid gap-2 sm:grid-cols-3">
              {[
                { label: "Accepted", value: ".xlsx .xls .csv" },
                { label: "Max file size", value: "25 MB" },
                { label: "Duplicate handling", value: "Merge existing email rows" },
              ].map((item) => (
                <div
                  key={item.label}
                  className="rounded-2xl border border-[#dbe7f5] bg-white/88 px-3 py-3 shadow-[0_14px_24px_-28px_rgba(38,99,172,0.9)]"
                >
                  <p className="caption text-[10px] uppercase tracking-[0.16em] text-slate-500">{item.label}</p>
                  <p className="mt-1 text-sm font-semibold text-slate-900">{item.value}</p>
                </div>
              ))}
            </div>
          </div>
          <Button
            variant="secondary"
            onClick={previewFile}
            disabled={!file || previewLoading || commitLoading}
            className="self-end"
            loading={previewLoading}
            aria-busy={previewLoading}
          >
            {previewLoading ? "Parsing..." : "Preview"}
          </Button>
          <Button
            onClick={commitFile}
            disabled={!canCommit || commitLoading}
            className="self-end"
            loading={commitLoading}
            aria-busy={commitLoading}
          >
            {commitLoading ? "Committing..." : "Commit Import"}
          </Button>
        </div>
      </Card>

      {error ? (
        <Card className="border-rose-500/50 bg-rose-500/10">
          <p className="text-sm text-rose-700">{error}</p>
        </Card>
      ) : null}

      {success ? (
        <Card className="border-emerald-500/50 bg-emerald-500/10">
          <p className="text-sm text-emerald-700">{success}</p>
        </Card>
      ) : null}

      {preview ? (
        <>
          <Card className="bg-[linear-gradient(160deg,#ffffff_0%,#f5faff_100%)]">
            <div className="flex items-center justify-between gap-3">
              <h3 className="text-sm font-semibold text-slate-900">VEEVA Preview Summary</h3>
              <span className="caption rounded-full border border-[#2663AC]/15 bg-[#2663AC]/10 px-2 py-1 text-[10px] uppercase tracking-[0.16em] text-[#2663AC]">
                Preview
              </span>
            </div>
            <div className="mt-3 grid gap-2 sm:grid-cols-2 xl:grid-cols-5">
              {[
                { label: "Valid rows", value: String(preview.parsedRows) },
                { label: "Sentiment rows", value: String(preview.sentimentRows ?? 0) },
                { label: "Sentiment emails", value: String(preview.sentimentEmailCount ?? 0) },
                { label: "Detected countries", value: preview.detectedCountries.join(", ") || "None" },
                { label: "Brands mapped", value: String(preview.documentBrandCount ?? 0) },
              ].map((item) => (
                <div
                  key={item.label}
                  className="rounded-2xl border border-[#dbe7f5] bg-white/90 px-3 py-3 shadow-[0_14px_24px_-30px_rgba(38,99,172,0.8)]"
                >
                  <p className="caption text-[10px] uppercase tracking-[0.16em] text-slate-500">{item.label}</p>
                  <p className="mt-1 text-sm font-semibold text-slate-900">{item.value}</p>
                </div>
              ))}
            </div>
            {preview.errors.length > 0 ? (
              <div className="mt-3 rounded-lg border border-rose-500/40 bg-rose-500/10 p-3 text-sm text-rose-700">
                {preview.errors.map((item) => (
                  <p key={item}>{item}</p>
                ))}
              </div>
            ) : null}
            {preview.warnings.length > 0 ? (
              <div className="mt-3 max-h-28 space-y-1 overflow-auto rounded-lg border border-amber-500/40 bg-amber-500/10 p-3 text-xs text-amber-700">
                {preview.warnings.map((item) => (
                  <p key={item}>{item}</p>
                ))}
              </div>
            ) : null}
          </Card>

          <div className="overflow-hidden rounded-3xl border border-[#d8e4f3] bg-[linear-gradient(170deg,#ffffff_0%,#f5faff_72%,#fff9f3_100%)] shadow-[0_22px_35px_-30px_rgba(38,99,172,0.75)]">
            <div className="border-b border-[#dbe7f5] px-5 py-4">
              <h3 className="text-sm font-semibold text-slate-900">Parsed VEEVA Rows Preview</h3>
            </div>
            <div className="max-h-[420px] overflow-auto">
              <table className="w-full text-left text-sm">
                <thead className="sticky top-0 z-10 bg-[linear-gradient(120deg,#eef5ff_0%,#f6faff_70%,#fff7ed_100%)] text-[11px] uppercase tracking-[0.16em] text-slate-500">
                  <tr>
                    <th className="px-4 py-2">Source Row</th>
                    <th className="px-4 py-2">Country</th>
                    <th className="px-4 py-2">Sent Email Name</th>
                    <th className="px-4 py-2">Approved Document Name</th>
                    <th className="px-4 py-2">Opened</th>
                    <th className="px-4 py-2">Clicked</th>
                    <th className="px-4 py-2">Sent Date</th>
                  </tr>
                </thead>
                <tbody>
                  {preview.previewRows.length > 0 ? (
                    preview.previewRows.map((row) => (
                      <tr key={`${row.sent_email_name}-${row.source_row_number}`} className="border-t border-[#e2ebf7]">
                        <td className="px-4 py-2 text-slate-600">{row.source_row_number}</td>
                        <td className="px-4 py-2 text-slate-800">{row.primary_country_code}</td>
                        <td className="max-w-[340px] px-4 py-2 text-slate-800">
                          <span className="block whitespace-normal break-words">{row.sent_email_name}</span>
                        </td>
                        <td className="max-w-[320px] px-4 py-2 text-slate-600">
                          <span className="block whitespace-normal break-words">{row.approved_document_name}</span>
                        </td>
                        <td className="px-4 py-2 text-slate-800">{row.opened}</td>
                        <td className="px-4 py-2 text-slate-800">{row.clicked}</td>
                        <td className="px-4 py-2 text-slate-500">
                          {row.sent_date ? new Date(row.sent_date).toLocaleString("en-GB") : "N/A"}
                        </td>
                      </tr>
                    ))
                  ) : (
                    <tr className="border-t border-[#e2ebf7]">
                      <td colSpan={7} className="px-4 py-5 text-center text-sm text-slate-500">
                        No event rows found in this file. If sentiment rows are detected above, commit will still store them.
                      </td>
                    </tr>
                  )}
                </tbody>
              </table>
            </div>
          </div>
        </>
      ) : null}
    </div>
  );
}
