import type { LucideIcon } from "lucide-react";
import {
  Building2,
  Download,
  Eye,
  FileCheck,
  FileText,
  Globe,
  Hash,
  Mail,
  MapPin,
  Phone,
  ShieldCheck,
  User,
} from "lucide-react";
import {
  ActionIcon,
  Badge,
  Divider,
  Group,
  Loader,
  Stack,
  Text,
  ThemeIcon,
  Tooltip,
} from "@mantine/core";
import { useQuery } from "@tanstack/react-query";
import type { Freight } from "@edr/types";
import { clearanceWorkflowFileLabel } from "@edr/types";

import { SectionCard } from "@/components/bookings/detail/SectionCard";
import { detailStyles } from "@/components/bookings/detail/booking-detail.styles";
import { customersService } from "@/services/customers.service";

type ContractFile = NonNullable<Freight.IContract["files"]>[number];

// ── shared bits ──────────────────────────────────────────────────────────────

interface InfoRowProps {
  icon: LucideIcon;
  label: string;
  value?: string | null;
}

function InfoRow({ icon: Icon, label, value }: InfoRowProps) {
  return (
    <Group justify="space-between" wrap="nowrap" py={6} gap="md">
      <Group gap="xs" wrap="nowrap">
        <Icon size={15} color="var(--mantine-color-gray-5)" />
        <Text size="sm" c="dimmed">
          {label}
        </Text>
      </Group>
      <Text size="sm" fw={600} ta="right" style={{ minWidth: 0 }} truncate>
        {value || "—"}
      </Text>
    </Group>
  );
}

function InfoRows({ rows }: { rows: InfoRowProps[] }) {
  const visible = rows.filter((r) => r.value);
  if (visible.length === 0) {
    return (
      <Text size="sm" c="dimmed">
        No details available.
      </Text>
    );
  }
  return (
    <Stack gap={0}>
      {visible.map((row, i) => (
        <div key={row.label}>
          {i > 0 && <Divider color="var(--mantine-color-gray-2)" />}
          <InfoRow {...row} />
        </div>
      ))}
    </Stack>
  );
}

// ── Customer tab ─────────────────────────────────────────────────────────────

/**
 * Customer info for the contract. The contract detail payload only carries a
 * `companyId`, so we fetch the full company record to surface contact + manager
 * details (mirrors the booking-request customer card).
 */
export function ContractCustomerCard({
  contract,
}: {
  contract: Freight.IContract;
}) {
  const companyId = contract.companyId ?? undefined;

  const { data: company, isLoading } = useQuery({
    queryKey: ["companies", "byId", companyId],
    queryFn: () => customersService.getById(companyId!),
    enabled: Boolean(companyId) && !contract.isGovernment,
  });

  // Government contracts carry an institution name instead of a company.
  if (contract.isGovernment) {
    return (
      <SectionCard icon={Building2} title="Customer" accent="blue">
        <InfoRows
          rows={[
            {
              icon: Building2,
              label: "Government",
              value: contract.governmentInstitution ?? "Government",
            },
          ]}
        />
      </SectionCard>
    );
  }

  if (isLoading) {
    return (
      <SectionCard icon={Building2} title="Customer" accent="blue">
        <Group gap="sm" py="sm">
          <Loader size="sm" color="gray" />
          <Text size="sm" c="dimmed">
            Loading customer…
          </Text>
        </Group>
      </SectionCard>
    );
  }

  if (!company) {
    return (
      <SectionCard icon={Building2} title="Customer" accent="blue">
        <Text size="sm" c="dimmed">
          No customer linked to this contract.
        </Text>
      </SectionCard>
    );
  }

  return (
    <Stack gap="lg">
      <SectionCard
        icon={Building2}
        title="Customer"
        subtitle={company.name}
        accent="blue"
      >
        <InfoRows
          rows={[
            { icon: FileCheck, label: "TIN", value: company.tin },
            { icon: Hash, label: "VAT number", value: company.vatNumber },
            { icon: ShieldCheck, label: "FAN number", value: company.fanNumber },
            { icon: Globe, label: "Country", value: company.country },
            { icon: Mail, label: "Email", value: company.email },
            { icon: Phone, label: "Phone", value: company.phone },
            { icon: MapPin, label: "Address", value: company.address },
            { icon: Globe, label: "Website", value: company.website },
          ]}
        />
      </SectionCard>

      <SectionCard icon={User} title="Contact person" accent="teal">
        <InfoRows
          rows={[
            { icon: User, label: "Name", value: company.contactPersonName },
            { icon: Phone, label: "Phone", value: company.contactPersonPhone },
          ]}
        />
      </SectionCard>

      <SectionCard icon={User} title="General manager" accent="grape">
        <InfoRows
          rows={[
            { icon: User, label: "Name", value: company.generalManagerName },
            { icon: Mail, label: "Email", value: company.generalManagerEmail },
            { icon: Phone, label: "Phone", value: company.generalManagerPhone },
          ]}
        />
      </SectionCard>
    </Stack>
  );
}

// ── Documents tab ────────────────────────────────────────────────────────────

function formatBytes(bytes?: number | null): string {
  if (!bytes || bytes <= 0) return "—";
  const units = ["B", "KB", "MB", "GB"];
  let value = bytes;
  let unit = 0;
  while (value >= 1024 && unit < units.length - 1) {
    value /= 1024;
    unit += 1;
  }
  return `${value.toFixed(value >= 10 || unit === 0 ? 0 : 1)} ${units[unit]}`;
}

/** Human label for a file's `code` (e.g. "business_license" → "Business license"). */
function codeLabel(code?: string | null): string | null {
  if (!code) return null;
  return (
    clearanceWorkflowFileLabel(code) ??
    code.replace(/[_-]+/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
  );
}

export interface ContractDocumentsCardProps {
  files: ContractFile[];
  /** Card heading. Defaults to "Documents". */
  title?: string;
  /** Message shown when there are no files. */
  emptyText?: string;
  /** Open the file inline in a viewer modal. */
  onView?: (file: ContractFile) => void;
  /** Download the file to disk. */
  onDownload?: (file: ContractFile) => void;
}

/** Rich list of the contract's attached documents: type, size, view + download. */
export function ContractDocumentsCard({
  files,
  title = "Documents",
  emptyText = "No documents attached to this contract.",
  onView,
  onDownload,
}: ContractDocumentsCardProps) {
  return (
    <SectionCard
      icon={FileText}
      title={title}
      accent="indigo"
      extra={
        <Badge color="gray" variant="light" radius="sm">
          {files.length}
        </Badge>
      }
    >
      {files.length === 0 ? (
        <Text size="sm" c="dimmed">
          {emptyText}
        </Text>
      ) : (
        <Stack gap="xs">
          {files.map((file) => {
            const label = codeLabel(file.code);
            return (
              <Group
                key={file.id}
                justify="space-between"
                wrap="nowrap"
                p="xs"
                style={detailStyles.fileRow}
                onMouseEnter={(e) => {
                  e.currentTarget.style.background =
                    "var(--mantine-color-gray-0)";
                  e.currentTarget.style.borderColor =
                    "var(--freight-brand-border)";
                }}
                onMouseLeave={(e) => {
                  e.currentTarget.style.background = "transparent";
                  e.currentTarget.style.borderColor =
                    "var(--mantine-color-gray-2)";
                }}
              >
                <Group gap="sm" wrap="nowrap" style={{ minWidth: 0 }}>
                  <ThemeIcon size={36} radius="md" variant="light" color="indigo">
                    <FileText size={17} />
                  </ThemeIcon>
                  <Stack gap={2} style={{ minWidth: 0 }}>
                    <Text size="sm" fw={500} truncate>
                      {file.name}
                    </Text>
                    <Group gap={6} wrap="nowrap">
                      {label ? (
                        <Badge
                          variant="light"
                          color="gray"
                          radius="sm"
                          size="xs"
                          tt="none"
                        >
                          {label}
                        </Badge>
                      ) : null}
                      <Text size="xs" c="dimmed">
                        {formatBytes(file.size)}
                      </Text>
                    </Group>
                  </Stack>
                </Group>
                <Group gap={4} wrap="nowrap">
                  {onView ? (
                    <Tooltip label="View" withArrow>
                      <ActionIcon
                        variant="subtle"
                        color="indigo"
                        radius="md"
                        onClick={() => onView(file)}
                        aria-label={`View ${file.name}`}
                      >
                        <Eye size={16} />
                      </ActionIcon>
                    </Tooltip>
                  ) : null}
                  {onDownload ? (
                    <Tooltip label="Download" withArrow>
                      <ActionIcon
                        variant="subtle"
                        color="gray"
                        radius="md"
                        onClick={() => onDownload(file)}
                        aria-label={`Download ${file.name}`}
                      >
                        <Download size={16} />
                      </ActionIcon>
                    </Tooltip>
                  ) : null}
                </Group>
              </Group>
            );
          })}
        </Stack>
      )}
    </SectionCard>
  );
}
