import { Box, Group, Paper, Text, Tooltip } from "@mantine/core";
import { AlertTriangle, FileText } from "lucide-react";
import type { LucideIcon } from "lucide-react";
import type { ReactNode } from "react";
import type { Freight } from "@edr/types";

import { fetchViewableFile } from "@/services/files.service";

// Brand palette (mirrors the booking form's shared constants).
export const INK = "#10202F";
export const MUTED = "#6B7C8E";
export const GREEN = "#0EA371";
export const GREEN_DARK = "#0A6F4D";
export const BORDER = "#E6ECF2";

// Accent hues used for the thin status rail on each KPI card.
const ACCENT: Record<string, string> = {
  "edr-green": "#0EA371",
  "edr-accent": "#F2A516",
  violet: "#6A40B8",
  orange: "#C77F09",
};

/**
 * A clean KPI card for the contracts list + detail header strips. No filled
 * background, no icon tile — just a thin colored accent rail, the value, and a
 * muted label. The icon is a small ghost glyph in the corner.
 */
export function StatCard({
  label,
  value,
  hint,
  icon: Icon,
  color = "edr-green",
}: {
  label: string;
  value: ReactNode;
  hint?: string;
  icon: LucideIcon;
  color?: string;
}) {
  const accent = ACCENT[color] ?? GREEN;
  return (
    <Paper
      withBorder
      radius="lg"
      p="lg"
      style={{
        borderColor: BORDER,
        flex: 1,
        minWidth: 180,
        position: "relative",
        overflow: "hidden",
        // Soft accent-tinted wash instead of a hard left rail.
        background: `linear-gradient(135deg, ${accent}0F 0%, ${accent}05 28%, #FFFFFF 70%)`,
      }}
    >
      {Icon && (
        <Icon
          size={18}
          style={{
            position: "absolute",
            top: 16,
            right: 16,
            color: accent,
            opacity: 0.45,
          }}
        />
      )}
      <Text
        fz={11}
        fw={700}
        tt="uppercase"
        c="dimmed"
        style={{ letterSpacing: "0.06em" }}
      >
        {label}
      </Text>
      <Text
        fz={30}
        fw={800}
        lh={1.1}
        mt={6}
        style={{ color: INK, letterSpacing: "-0.02em" }}
      >
        {value}
      </Text>
      {hint && (
        <Text fz={12} c="dimmed" mt={2} truncate>
          {hint}
        </Text>
      )}
    </Paper>
  );
}

// Tone presets so every status maps to a consistent badge palette.
const TONE = {
  neutral: { color: "#6B7C8E", bg: "#EEF2F6" },
  info: { color: "#2E5B96", bg: "#EAF1FB" },
  warning: { color: "#9A6700", bg: "#FFF6E5" },
  success: { color: "#0A6F4D", bg: "#E7F6EE" },
  danger: { color: "#B42318", bg: "#FEECEB" },
} as const;

/**
 * Visual config covering ALL contract statuses (`CONTRACT_STATUSES` in
 * `@edr/types`) plus the Path B clearance + renewal + booking statuses reused by
 * badges on the contract detail page.
 */
export const CONTRACT_STATUS_CONFIG: Record<
  string,
  { label: string; color: string; bg: string }
> = {
  // ── Contract lifecycle ──
  DRAFT: { label: "Draft", ...TONE.neutral },
  SUBMITTED: { label: "Submitted", ...TONE.info },
  PRICE_CHANGED_PENDING_CONFIRM: { label: "Confirm New Price", ...TONE.warning },
  CHANGES_REQUESTED: { label: "Changes Requested", ...TONE.warning },
  PENDING_APPROVAL: { label: "Pending Approval", ...TONE.warning },
  APPROVED: { label: "Approved", ...TONE.info },
  APPROVED_PENDING_SIGNATURE: { label: "Awaiting Signature", ...TONE.warning },
  CONTRACT_READY: { label: "Ready to Sign", ...TONE.info },
  SIGNED_CUSTOMER: { label: "Signed — Awaiting Staff", ...TONE.info },
  FULLY_EXECUTED: { label: "Fully Executed", ...TONE.success },
  CONTRACT_ACTIVE: { label: "Active", ...TONE.success },
  // ── Path B pre-booking clearance (contract-level) ──
  AWAITING_CLEARANCE_DOCUMENTS: {
    label: "Upload Clearance Docs",
    ...TONE.warning,
  },
  CLEARANCE_UNDER_REVIEW: { label: "Clearance Under Review", ...TONE.info },
  CLEARANCE_READY_FOR_BOOKING: { label: "Cleared — Awaiting Booking", ...TONE.success },
  ACTIVE_SHIPMENT_IN_PROGRESS: { label: "Shipment In Progress", ...TONE.info },
  // ── Terminal ──
  CONTRACT_CLOSED: { label: "Closed", ...TONE.neutral },
  EXPIRED: { label: "Expired", ...TONE.danger },
  REJECTED: { label: "Rejected", ...TONE.danger },
  CANCELLED: { label: "Cancelled", ...TONE.danger },
  // ── Renewal branch ──
  RENEWAL_DRAFT: { label: "Renewal Draft", ...TONE.neutral },
  RENEWAL_SUBMITTED: { label: "Renewal Submitted", ...TONE.info },
  RENEWAL_PENDING_APPROVAL: { label: "Renewal Pending Approval", ...TONE.warning },
  AMENDMENTS_PROPOSED: { label: "Amendments Proposed", ...TONE.warning },
  ARCHIVED: { label: "Archived", ...TONE.neutral },
  // ── Booking statuses reused by the contract's booking list badges ──
  PENDING: { label: "Pending", ...TONE.warning },
  AWAITING_DOCUMENTS: { label: "Awaiting Documents", ...TONE.warning },
  DOCUMENTS_UNDER_REVIEW: { label: "Documents Under Review", ...TONE.info },
  CLEARANCE_READY: { label: "Clearance Ready", ...TONE.success },
  OPERATION_REQUEST_PENDING: { label: "Operation Review", ...TONE.warning },
  OPERATION_REQUESTED: { label: "Operation Requested", ...TONE.info },
  OPERATION_CHANGES_REQUESTED: { label: "Changes Requested", ...TONE.warning },
  OPERATION_PRICE_PENDING_CONFIRM: { label: "Confirm New Price", ...TONE.warning },
  ROAD_DISPATCH_PENDING: { label: "Awaiting Dispatch", ...TONE.warning },
  READY_FOR_ASSIGNMENT: { label: "Assigning Wagon", ...TONE.info },
  WAGON_ASSIGNED: { label: "Wagon Assigned", ...TONE.success },
  SELECTED_FOR_BATCH: { label: "Awaiting Payment", ...TONE.warning },
  PNR_GENERATED: { label: "Payment Reference Ready", ...TONE.warning },
  PAYMENT_VERIFICATION_IN_PROGRESS: { label: "Verifying Payment", ...TONE.warning },
  INVOICED: { label: "Invoiced", ...TONE.info },
  PAID: { label: "Paid", ...TONE.success },
  PENDING_CONSOLIDATION: { label: "Consolidating", ...TONE.info },
  CONSOLIDATED: { label: "Consolidated", ...TONE.success },
  TRUCK_ASSIGNED: { label: "Truck Assigned", ...TONE.success },
  IN_TRANSIT: { label: "In Transit", ...TONE.info },
  ARRIVED: { label: "Arrived", ...TONE.success },
  DELIVERED: { label: "Delivered", ...TONE.success },
  COMPLETED: { label: "Completed", ...TONE.success },
};

export function ContractStatusBadge({ status }: { status: string }) {
  const cfg =
    CONTRACT_STATUS_CONFIG[status] ?? {
      // Readable title-case fallback so an unmapped status never leaks the raw
      // SCREAMING_SNAKE enum to the customer.
      label: status
        .replace(/_/g, " ")
        .toLowerCase()
        .replace(/\b\w/g, (m) => m.toUpperCase()),
      color: MUTED,
      bg: "#EEF2F6",
    };
  return (
    <Group
      gap={6}
      align="center"
      wrap="nowrap"
      style={{
        display: "inline-flex",
        borderRadius: 999,
        backgroundColor: cfg.bg,
        padding: "4px 10px",
      }}
    >
      <Box
        style={{
          width: 6,
          height: 6,
          borderRadius: "50%",
          backgroundColor: cfg.color,
          flexShrink: 0,
        }}
      />
      <Text fz={11.5} fw={700} style={{ color: cfg.color, whiteSpace: "nowrap" }}>
        {cfg.label}
      </Text>
    </Group>
  );
}

/**
 * How close to its validity end a contract has to be before the customer is
 * warned. The API notifies at the same distance (contract-expiry.service), so
 * the inbox message and the list badge agree.
 */
export const EXPIRY_NOTICE_DAYS = 10;

/** Whole days until a date (0 = today, negative = already past). Null if unset. */
export function daysUntil(dateIso?: string | null): number | null {
  if (!dateIso) return null;
  const end = new Date(dateIso).getTime();
  if (Number.isNaN(end)) return null;
  return Math.ceil((end - Date.now()) / 86_400_000);
}

/** Contracts that are already over — no point warning about their expiry. */
const CLOSED_CONTRACT_STATUSES = [
  "REJECTED",
  "CANCELLED",
  "CONTRACT_CLOSED",
  "ARCHIVED",
  "EXPIRED",
];

/**
 * Days left on a live contract, but only inside the notice window — null when
 * the contract is closed, has no validity date, has already lapsed, or is still
 * further out than {@link EXPIRY_NOTICE_DAYS}.
 */
export function expiryNoticeDays(
  contract: Pick<Freight.IContract, "status" | "contractValidUntil">,
): number | null {
  if (CLOSED_CONTRACT_STATUSES.includes(contract.status)) return null;
  const days = daysUntil(contract.contractValidUntil);
  if (days == null || days < 0 || days > EXPIRY_NOTICE_DAYS) return null;
  return days;
}

/** "Expires today" / "5 days left" — the wording shared by list and banner. */
export function expiryNoticeLabel(days: number): string {
  if (days === 0) return "Expires today";
  return `${days} day${days === 1 ? "" : "s"} left`;
}

/**
 * Amber countdown pill shown on a contract that is about to lapse. Renders
 * nothing outside the notice window, so callers can drop it in unconditionally.
 */
export function ContractExpiryBadge({
  contract,
}: {
  contract: Pick<Freight.IContract, "status" | "contractValidUntil">;
}) {
  const days = expiryNoticeDays(contract);
  if (days == null) return null;
  return (
    <Tooltip
      withArrow
      label="This contract stops accepting bookings when its validity ends. Contact EDR to renew it."
    >
      <Group
        gap={5}
        align="center"
        wrap="nowrap"
        mt={4}
        style={{
          display: "inline-flex",
          borderRadius: 999,
          backgroundColor: "#FEF6E7",
          border: "1px solid #F5D9A3",
          padding: "2px 8px",
        }}
      >
        <AlertTriangle size={12} color="#9A6700" />
        <Text fz={11} fw={700} style={{ color: "#9A6700", whiteSpace: "nowrap" }}>
          {expiryNoticeLabel(days)}
        </Text>
      </Group>
    </Tooltip>
  );
}

/** A labelled value used across the contract detail summary cards. */
export function MetaItem({
  label,
  value,
  icon,
}: {
  label: string;
  value: ReactNode;
  icon?: ReactNode;
}) {
  return (
    <div>
      <Text fz={12} fw={600} c="dimmed" mb={4} style={{ letterSpacing: 0.2 }}>
        {label}
      </Text>
      <Group gap={6} wrap="nowrap" align="center">
        {icon}
        <Text fz={14} fw={600} style={{ color: INK }}>
          {value}
        </Text>
      </Group>
    </div>
  );
}

/** Format a contracted/remaining quantity with its unit. */
export function formatQuantity(
  qty: number,
  unit?: string | null,
  isContainerLine?: boolean,
): string {
  const rounded = Number.isInteger(qty) ? qty : Number(qty.toFixed(2));
  if (isContainerLine) return `${rounded} containers`;
  if (unit === "PER_ITEM") return `${rounded} items`;
  return `${rounded} tons`;
}

/** The generated contract PDF (file with code "contract"), if present. */
export function contractPdfFile(
  contract: Pick<Freight.IContract, "files">,
): NonNullable<Freight.IContract["files"]>[number] | undefined {
  return (contract.files ?? []).find((f) => f.code === "contract");
}

/**
 * Icon button that opens the generated contract PDF in a new tab. Renders
 * nothing when the contract has not been generated yet, so it's safe to drop
 * into any contract row (list table, home recents, etc).
 */
export function ContractDocButton({
  contract,
  onClick,
}: {
  contract: Pick<Freight.IContract, "files">;
  /** Stop row-click propagation when the button lives inside a clickable row. */
  onClick?: (e: React.MouseEvent) => void;
}) {
  const file = contractPdfFile(contract);
  if (!file) return null;
  return (
    <Tooltip label="Contract document" withArrow>
      <Box
        component="button"
        type="button"
        onClick={(e: React.MouseEvent) => {
          onClick?.(e);
          void fetchViewableFile(file.id, file.name).then((f) =>
            window.open(f.url, "_blank"),
          );
        }}
        aria-label="Open contract document"
        style={{
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          width: 34,
          height: 34,
          padding: 0,
          cursor: "pointer",
          borderRadius: 8,
          border: `1px solid ${BORDER}`,
          background: "#FFFFFF",
          color: GREEN_DARK,
          flexShrink: 0,
          transition: "border-color 120ms ease, background-color 120ms ease",
        }}
        onMouseEnter={(e) => {
          e.currentTarget.style.borderColor = GREEN;
          e.currentTarget.style.backgroundColor = "#F0FAF5";
        }}
        onMouseLeave={(e) => {
          e.currentTarget.style.borderColor = BORDER;
          e.currentTarget.style.backgroundColor = "#FFFFFF";
        }}
      >
        <FileText size={16} />
      </Box>
    </Tooltip>
  );
}
