import { useState, useEffect, useRef, lazy, Suspense } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useAlert } from "../context/AlertContext";
import { useAuth } from "../context/AuthContext";
import { Link as RouterLink, useSearchParams } from "react-router-dom";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import IconButton from "@mui/material/IconButton";
import CircularProgress from "@mui/material/CircularProgress";
import Forbidden from "../components/Forbidden";

import apiFetch from "../utils/api";
import {
  formatCurrency,
  formatMultiCurrency,
  formatDate,
  czechPlural,
  todayLocalStr,
} from "../utils/formatters";
import { normalizeDateStr } from "../utils/attendanceHelpers";
import { usePaginatedQuery } from "../hooks/usePaginatedQuery";
import useTableSort from "../hooks/useTableSort";
import {
  invoiceListOptions,
  invoiceStatsOptions,
  invoiceTotalsOptions,
  type Invoice,
  type CurrencyAmount,
} from "../lib/queries/invoices";
import {
  Button,
  Card,
  DataTable,
  Pagination,
  ConfirmDialog,
  TextField,
  StatusChip,
  StatCard,
  EmptyState,
  LoadingState,
  FilterBar,
  Tabs,
  PageHeader,
  PageEnter,
  type DataColumn,
  type TabDef,
  type StatCardColor,
} from "../ui";
import {
  INVOICE_STATUS,
  statusLabel,
  statusColor,
  statusOptions,
  documentNumberLabel,
} from "../lib/documentStatus";

const ReceivedInvoices = lazy(() => import("./ReceivedInvoices"));
const API_BASE = "/api/admin";

const MONTH_NAMES = [
  "leden",
  "únor",
  "březen",
  "duben",
  "květen",
  "červen",
  "červenec",
  "srpen",
  "září",
  "říjen",
  "listopad",
  "prosinec",
];

function formatCzkWithDetail(
  amounts: CurrencyAmount[],
  totalCzk: number | null | undefined,
): { value: string; detail: string | null } {
  if (!Array.isArray(amounts) || amounts.length === 0)
    return { value: "0 Kč", detail: null };
  const hasForeign = amounts.some((a) => a.currency !== "CZK");
  if (hasForeign && totalCzk != null) {
    return {
      value: formatCurrency(totalCzk, "CZK"),
      detail: formatMultiCurrency(amounts),
    };
  }
  return { value: formatMultiCurrency(amounts), detail: null };
}

// Filter tabs derive from INVOICE_STATUS so `draft` ("Koncept") flows in
// automatically; the leading "Všechny" tab is the all-statuses filter.
const STATUS_FILTERS = statusOptions(INVOICE_STATUS, {
  value: "",
  label: "Všechny",
});

const PlusIcon = (
  <svg
    width="20"
    height="20"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <line x1="12" y1="5" x2="12" y2="19" />
    <line x1="5" y1="12" x2="19" y2="12" />
  </svg>
);
const UploadIcon = (
  <svg
    width="18"
    height="18"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
    <polyline points="17 8 12 3 7 8" />
    <line x1="12" y1="3" x2="12" y2="15" />
  </svg>
);
const ChevronLeftIcon = (
  <svg
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2.5"
  >
    <polyline points="15 18 9 12 15 6" />
  </svg>
);
const ChevronRightIcon = (
  <svg
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2.5"
  >
    <polyline points="9 18 15 12 9 6" />
  </svg>
);
const ViewIcon = (
  <svg
    width="18"
    height="18"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
    <circle cx="12" cy="12" r="3" />
  </svg>
);
const EditIcon = (
  <svg
    width="18"
    height="18"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
    <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
  </svg>
);
const PdfIcon = (
  <svg
    width="18"
    height="18"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
    <polyline points="14 2 14 8 20 8" />
    <line x1="16" y1="13" x2="8" y2="13" />
    <line x1="16" y1="17" x2="8" y2="17" />
  </svg>
);
const DeleteIcon = (
  <svg
    width="18"
    height="18"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <polyline points="3 6 5 6 21 6" />
    <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
  </svg>
);

export default function Invoices() {
  const alert = useAlert();
  const { hasPermission } = useAuth();

  const [searchParams, setSearchParams] = useSearchParams();
  const activeTab =
    searchParams.get("tab") === "received" ? "received" : "issued";
  const setActiveTab = (tab: string) =>
    setSearchParams({ tab }, { replace: true });
  const [receivedUploadOpen, setReceivedUploadOpen] = useState(false);
  const { sort, order, handleSort } = useTableSort("invoice_number");
  const [search, setSearch] = useState("");
  const [page, setPage] = useState(1);
  const [statusFilter, setStatusFilter] = useState("");

  const now = new Date();
  const [statsMonth, setStatsMonth] = useState(now.getMonth() + 1);
  const [statsYear, setStatsYear] = useState(now.getFullYear());
  const blobUrlRef = useRef<string | null>(null);
  // Track first successful list load so later refetches (filter/status/month/
  // page change) keep the table visible instead of flashing the full skeleton.
  const hasLoadedOnce = useRef(false);

  useEffect(() => {
    return () => {
      if (blobUrlRef.current) {
        URL.revokeObjectURL(blobUrlRef.current);
        blobUrlRef.current = null;
      }
    };
  }, []);

  const isCurrentMonth =
    statsMonth === now.getMonth() + 1 && statsYear === now.getFullYear();
  const monthLabel = `${MONTH_NAMES[statsMonth - 1]} ${statsYear}`;

  const statsQuery = useQuery(invoiceStatsOptions(statsMonth, statsYear));
  const stats = statsQuery.data ?? null;

  const prevMonth = () => {
    if (statsMonth === 1) {
      setStatsMonth(12);
      setStatsYear((y) => y - 1);
    } else {
      setStatsMonth((m) => m - 1);
    }
  };

  const nextMonth = () => {
    if (isCurrentMonth) return;
    if (statsMonth === 12) {
      setStatsMonth(1);
      setStatsYear((y) => y + 1);
    } else {
      setStatsMonth((m) => m + 1);
    }
  };

  const [deleteConfirm, setDeleteConfirm] = useState<{
    show: boolean;
    invoice: Invoice | null;
  }>({ show: false, invoice: null });
  const [deleting, setDeleting] = useState(false);
  const [pdfLoading, setPdfLoading] = useState<number | null>(null);

  const queryClient = useQueryClient();
  const {
    items: invoices,
    pagination,
    isPending: initialLoad,
    isFetching: loading,
  } = usePaginatedQuery<Invoice>(
    invoiceListOptions({
      search,
      sort,
      order,
      page,
      month: statsMonth,
      year: statsYear,
      status: statusFilter || undefined,
    }),
  );

  // Per-currency total over the WHOLE filtered set of the ISSUED list (not one
  // page). Uses the SAME filters as the issued list query so the summary
  // matches what's shown. Separate from the KPI `statsQuery` above.
  const listTotalsQuery = useQuery(
    invoiceTotalsOptions({
      search,
      status: statusFilter || undefined,
      month: statsMonth,
      year: statsYear,
    }),
  );

  // Mark first load done in an effect (not during render) to avoid a
  // render-phase ref mutation.
  useEffect(() => {
    if (!initialLoad) hasLoadedOnce.current = true;
  }, [initialLoad]);

  if (!hasPermission("invoices.view")) return <Forbidden />;

  const handleDelete = async () => {
    if (!deleteConfirm.invoice) return;
    setDeleting(true);
    try {
      const response = await apiFetch(
        `${API_BASE}/invoices/${deleteConfirm.invoice.id}`,
        {
          method: "DELETE",
        },
      );
      const result = await response.json();
      if (result.success) {
        setDeleteConfirm({ show: false, invoice: null });
        alert.success(result.message || "Faktura byla smazána");
        queryClient.invalidateQueries({ queryKey: ["invoices"] });
        queryClient.invalidateQueries({ queryKey: ["orders"] });
        queryClient.invalidateQueries({ queryKey: ["projects"] });
      } else {
        alert.error(result.error || "Nepodařilo se smazat fakturu");
      }
    } catch {
      alert.error("Chyba připojení");
    } finally {
      setDeleting(false);
    }
  };

  const toggleStatus = async (inv: Invoice) => {
    if (inv.status === "paid") return;
    try {
      const res = await apiFetch(`${API_BASE}/invoices/${inv.id}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ status: "paid" }),
      });
      const data = await res.json();
      if (data.success) {
        alert.success("Faktura označena jako zaplacená");
        queryClient.invalidateQueries({ queryKey: ["invoices"] });
        queryClient.invalidateQueries({ queryKey: ["orders"] });
        queryClient.invalidateQueries({ queryKey: ["projects"] });
      } else {
        alert.error(data.error || "Nepodařilo se změnit stav");
      }
    } catch {
      alert.error("Chyba připojení");
    }
  };

  const handlePdf = async (inv: Invoice) => {
    if (pdfLoading) return;
    const newWindow = window.open("", "_blank");
    setPdfLoading(inv.id);
    try {
      const response = await apiFetch(`${API_BASE}/invoices/${inv.id}/file`);
      if (response.status === 401) {
        newWindow?.close();
        return;
      }
      if (!response.ok) {
        newWindow?.close();
        alert.error("PDF soubor nenalezen — otevřete fakturu a uložte ji");
        return;
      }
      const blob = await response.blob();
      if (blobUrlRef.current) {
        URL.revokeObjectURL(blobUrlRef.current);
      }
      blobUrlRef.current = URL.createObjectURL(blob);
      if (newWindow) newWindow.location.href = blobUrlRef.current;
    } catch {
      alert.error("Chyba při generování PDF");
    } finally {
      setPdfLoading(null);
    }
  };

  // Only show the full-page skeleton on the very first load; on subsequent
  // refetches (filter/status/month/page change) keep the table visible (the
  // Card dims via `loading`/isFetching) so it doesn't flash.
  if (initialLoad && !hasLoadedOnce.current) {
    return <LoadingState />;
  }

  const total = pagination?.total ?? invoices.length;
  const subtitle = `${total} ${czechPlural(
    total,
    "faktura",
    "faktury",
    "faktur",
  )}`;

  const statusTabs: TabDef[] = STATUS_FILTERS.map((f) => ({
    value: f.value,
    label: f.label,
  }));

  // KPI cards — stat math preserved verbatim.
  const renderKpi = () => {
    if (statsQuery.isPending && !stats) {
      return <LoadingState />;
    }
    if (!stats) return null;

    const paid = formatCzkWithDetail(stats.paid_month, stats.paid_month_czk);
    const wait = formatCzkWithDetail(stats.awaiting, stats.awaiting_czk);
    const over = formatCzkWithDetail(stats.overdue, stats.overdue_czk);
    const vat = formatCzkWithDetail(stats.vat_month, stats.vat_month_czk);
    const countFooter = (count: number, zero: string) =>
      count > 0
        ? `${count} ${czechPlural(count, "faktura", "faktury", "faktur")}`
        : zero;

    const cards: {
      label: string;
      value: string;
      footer: string;
      color: StatCardColor;
    }[] = [
      {
        label: `Uhrazeno (${MONTH_NAMES[statsMonth - 1]})`,
        value: paid.value,
        footer: [
          paid.detail,
          countFooter(stats.paid_month_count, "žádné úhrady"),
        ]
          .filter(Boolean)
          .join(" · "),
        color: "success",
      },
      {
        label: "Čeká úhrada · celkově",
        value: wait.value,
        footer: [wait.detail, countFooter(stats.awaiting_count, "vše uhrazeno")]
          .filter(Boolean)
          .join(" · "),
        color: "warning",
      },
      {
        label: "Po splatnosti · celkově",
        value: over.value,
        footer: [
          over.detail,
          stats.overdue_count === 0
            ? "vše v pořádku"
            : countFooter(stats.overdue_count, ""),
        ]
          .filter(Boolean)
          .join(" · "),
        color: "error",
      },
      {
        label: `DPH (${MONTH_NAMES[statsMonth - 1]})`,
        value: vat.value,
        footer: vat.detail || "z vydaných faktur",
        color: "info",
      },
    ];

    return (
      <Box
        sx={{
          display: "grid",
          gridTemplateColumns: {
            xs: "1fr",
            sm: "repeat(2, 1fr)",
            lg: "repeat(4, 1fr)",
          },
          gap: 2,
          mb: 3,
        }}
      >
        {cards.map((c) => (
          <StatCard
            key={c.label}
            label={c.label}
            value={c.value}
            footer={c.footer}
            color={c.color}
          />
        ))}
      </Box>
    );
  };

  // Per-row overdue tint (replaces offers-expired-row).
  // Compare as YYYY-MM-DD strings in LOCAL time (lexicographic === chronological)
  // to avoid the UTC-vs-local off-by-one near midnight Prague.
  const rowSx = (inv: Invoice) => {
    const isOverdue =
      inv.status === "overdue" ||
      (inv.status === "issued" &&
        !!inv.due_date &&
        normalizeDateStr(inv.due_date) < todayLocalStr());
    if (isOverdue) {
      return {
        backgroundColor: "rgba(var(--mui-palette-warning-mainChannel) / 0.12)",
        "&:hover": {
          backgroundColor:
            "rgba(var(--mui-palette-warning-mainChannel) / 0.18)",
        },
      };
    }
    return {};
  };

  const columns: DataColumn<Invoice>[] = [
    {
      key: "invoice_number",
      header: "Číslo",
      width: "15%",
      sortKey: "invoice_number",
      mono: true,
      render: (inv) => (
        <Box
          component={RouterLink}
          to={`/invoices/${inv.id}`}
          sx={{
            color: "primary.main",
            textDecoration: "none",
            "&:hover": { textDecoration: "underline" },
          }}
        >
          {documentNumberLabel(inv.invoice_number)}
        </Box>
      ),
    },
    {
      key: "customer_name",
      header: "Zákazník",
      width: "22%",
      render: (inv) => inv.customer_name || "—",
    },
    {
      key: "status",
      header: "Stav",
      width: "13%",
      sortKey: "status",
      render: (inv) =>
        inv.status === "paid" ? (
          <StatusChip
            label={statusLabel(INVOICE_STATUS, inv.status)}
            color={statusColor(INVOICE_STATUS, inv.status)}
          />
        ) : (
          <StatusChip
            label={statusLabel(INVOICE_STATUS, inv.status)}
            color={statusColor(INVOICE_STATUS, inv.status)}
            onClick={() => toggleStatus(inv)}
          />
        ),
    },
    {
      key: "issue_date",
      header: "Vystaveno",
      width: "12%",
      sortKey: "issue_date",
      mono: true,
      render: (inv) => formatDate(inv.issue_date),
    },
    {
      key: "due_date",
      header: "Splatnost",
      width: "12%",
      sortKey: "due_date",
      mono: true,
      render: (inv) => (
        <Box
          component="span"
          sx={
            inv.status === "overdue"
              ? { color: "error.main", fontWeight: 600 }
              : undefined
          }
        >
          {formatDate(inv.due_date)}
        </Box>
      ),
    },
    {
      key: "total",
      header: "Celkem",
      width: "12%",
      align: "right",
      mono: true,
      bold: true,
      render: (inv) => formatCurrency(inv.total, inv.currency),
    },
    {
      key: "actions",
      header: "Akce",
      width: "14%",
      align: "right",
      render: (inv) => (
        <Box sx={{ display: "flex", gap: 0.5, justifyContent: "flex-end" }}>
          <IconButton
            size="small"
            component={RouterLink}
            to={`/invoices/${inv.id}`}
            title={inv.status === "paid" ? "Detail" : "Upravit"}
            aria-label={inv.status === "paid" ? "Detail" : "Upravit"}
          >
            {inv.status === "paid" ? ViewIcon : EditIcon}
          </IconButton>
          {hasPermission("invoices.view") && (
            <IconButton
              size="small"
              onClick={() => handlePdf(inv)}
              title="Zobrazit fakturu"
              aria-label="Zobrazit fakturu"
              disabled={pdfLoading === inv.id}
            >
              {pdfLoading === inv.id ? <CircularProgress size={16} /> : PdfIcon}
            </IconButton>
          )}
          {hasPermission("invoices.delete") && inv.status !== "paid" && (
            <IconButton
              size="small"
              color="error"
              onClick={() => setDeleteConfirm({ show: true, invoice: inv })}
              title="Smazat"
              aria-label="Smazat"
            >
              {DeleteIcon}
            </IconButton>
          )}
        </Box>
      ),
    },
  ];

  return (
    <PageEnter>
      <PageHeader
        title="Faktury"
        subtitle={subtitle}
        actions={
          hasPermission("invoices.create") ? (
            activeTab === "received" ? (
              <Button
                startIcon={UploadIcon}
                onClick={() => setReceivedUploadOpen(true)}
              >
                Nahrát faktury
              </Button>
            ) : (
              <Button
                component={RouterLink}
                to="/invoices/new"
                startIcon={PlusIcon}
              >
                Nová faktura
              </Button>
            )
          ) : undefined
        }
      />

      <Box>
        <Box
          sx={{
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            gap: 1,
            mb: 2,
          }}
        >
          <IconButton
            size="small"
            onClick={prevMonth}
            aria-label="Předchozí měsíc"
          >
            {ChevronLeftIcon}
          </IconButton>
          <Typography
            sx={{ minWidth: 140, textAlign: "center", fontWeight: 600 }}
          >
            {monthLabel}
          </Typography>
          <IconButton
            size="small"
            onClick={nextMonth}
            disabled={isCurrentMonth}
            aria-label="Následující měsíc"
          >
            {ChevronRightIcon}
          </IconButton>
        </Box>

        <Box sx={{ display: "flex", justifyContent: "center", mb: 2.5 }}>
          <Tabs
            value={activeTab}
            onChange={(v) => setActiveTab(v)}
            tabs={[
              { value: "issued", label: "Vydané" },
              { value: "received", label: "Přijaté" },
            ]}
          />
        </Box>
      </Box>

      {activeTab === "received" ? (
        <Suspense fallback={<LoadingState />}>
          <ReceivedInvoices
            statsMonth={statsMonth}
            statsYear={statsYear}
            uploadOpen={receivedUploadOpen}
            setUploadOpen={setReceivedUploadOpen}
          />
        </Suspense>
      ) : (
        <>
          {renderKpi()}

          <Box sx={{ mb: 2.5 }}>
            <Tabs
              value={statusFilter}
              onChange={(v) => {
                setStatusFilter(v);
                setPage(1);
              }}
              tabs={statusTabs}
            />
          </Box>

          <FilterBar>
            <Box sx={{ flex: "1 1 320px" }}>
              <TextField
                value={search}
                onChange={(e) => {
                  setSearch(e.target.value);
                  setPage(1);
                }}
                placeholder="Hledat podle čísla faktury, zákazníka nebo IČ..."
                fullWidth
              />
            </Box>
          </FilterBar>

          <Card sx={{ opacity: loading ? 0.6 : 1, transition: "opacity .2s" }}>
            <DataTable<Invoice>
              columns={columns}
              rows={invoices}
              rowKey={(inv) => inv.id}
              rowSx={rowSx}
              sortBy={sort}
              sortDir={order}
              onSort={handleSort}
              empty={
                search || statusFilter ? (
                  <EmptyState title="Žádné faktury neodpovídají filtru." />
                ) : (
                  <EmptyState
                    title="Zatím nejsou žádné faktury."
                    description={
                      hasPermission("invoices.create")
                        ? "Vytvořte první fakturu tlačítkem výše."
                        : undefined
                    }
                  />
                )
              }
            />
            {(listTotalsQuery.data?.length ?? 0) > 0 && (
              <Box
                sx={{
                  display: "flex",
                  justifyContent: "flex-end",
                  mt: 1.5,
                  px: 1,
                  gap: 1,
                  color: "text.secondary",
                  fontSize: "0.9rem",
                }}
              >
                <span>Celkem:</span>
                <Box
                  component="span"
                  sx={{ fontWeight: 700, color: "text.primary" }}
                >
                  {formatMultiCurrency(listTotalsQuery.data ?? [])}
                </Box>
              </Box>
            )}
            <Pagination
              page={page}
              pageCount={pagination?.total_pages ?? 1}
              onChange={setPage}
            />
          </Card>

          <ConfirmDialog
            isOpen={deleteConfirm.show}
            onClose={() => setDeleteConfirm({ show: false, invoice: null })}
            onConfirm={handleDelete}
            title="Smazat fakturu"
            message={`Opravdu chcete smazat fakturu "${deleteConfirm.invoice?.invoice_number}"? Tato akce je nevratná.`}
            confirmText="Smazat"
            cancelText="Zrušit"
            confirmVariant="danger"
            loading={deleting}
          />
        </>
      )}
    </PageEnter>
  );
}
