"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useParams, useSearchParams } from "next/navigation";
import { PageLayout } from "@/components/templates/PageLayout";
import { useCheckoutStore } from "@/features/checkout/stores/checkout.store";
import {
  ClipboardDocumentCheckIcon,
  CheckCircleIcon,
  SparklesIcon,
  WrenchScrewdriverIcon,
  PuzzlePieceIcon,
  BoltIcon,
  ClockIcon,
  Squares2X2Icon,
  ExclamationTriangleIcon,
  CalendarDaysIcon,
  CurrencyYenIcon,
  DocumentTextIcon,
} from "@heroicons/react/24/outline";
import { StatusPill } from "@/components/atoms/status-pill";
import { DetailStatsGrid, type StatGridItem } from "@/components/molecules";
import { SectionCard } from "@/components/molecules/SectionCard";
import { ordersService } from "@/features/orders/api/orders.api";
import { useOrderUpdates } from "@/features/orders/hooks/useOrderUpdates";
import {
  calculateOrderTotals,
  deriveOrderStatusDescriptor,
  getServiceCategory,
} from "@/features/orders/utils/order-presenters";
import {
  buildOrderDisplayItems,
  type OrderDisplayItem,
  type OrderDisplayItemCategory,
  type OrderDisplayItemCharge,
} from "@/features/orders/utils/order-display";
import { OrderServiceIcon } from "@/features/orders/components/OrderServiceIcon";
import { OrderProgressTimeline } from "@/features/orders/components/OrderProgressTimeline";
import { OrderDetailSkeleton } from "@/features/orders/components/OrderDetailSkeleton";
import type { OrderDetails, OrderUpdateEventPayload } from "@customer-portal/domain/orders";
import { Formatting } from "@customer-portal/domain/toolkit";
import { cn, formatIsoDate } from "@/shared/utils";

const CATEGORY_CONFIG: Record<
  OrderDisplayItemCategory,
  {
    icon: typeof SparklesIcon;
    label: string;
  }
> = {
  service: {
    icon: SparklesIcon,
    label: "Service",
  },
  installation: {
    icon: WrenchScrewdriverIcon,
    label: "Installation",
  },
  addon: {
    icon: PuzzlePieceIcon,
    label: "Add-on",
  },
  activation: {
    icon: BoltIcon,
    label: "Activation",
  },
  other: {
    icon: Squares2X2Icon,
    label: "Item",
  },
};

const ITEM_VISUAL_STYLES: Record<
  OrderDisplayItemCategory,
  {
    container: string;
    icon: string;
  }
> = {
  service: {
    container: "bg-card",
    icon: "bg-info-soft text-info",
  },
  installation: {
    container: "bg-card",
    icon: "bg-success-soft text-success",
  },
  addon: {
    container: "bg-card",
    icon: "bg-muted text-foreground/70",
  },
  activation: {
    container: "bg-card",
    icon: "bg-success-soft text-success",
  },
  other: {
    container: "bg-card",
    icon: "bg-muted text-muted-foreground",
  },
};

const getItemVisualStyle = (item: OrderDisplayItem) => {
  return ITEM_VISUAL_STYLES[item.primaryCategory] ?? ITEM_VISUAL_STYLES.other;
};

const describeCharge = (charge: OrderDisplayItemCharge): string => {
  if (typeof charge.suffix === "string" && charge.suffix.trim().length > 0) {
    return charge.suffix.trim();
  }

  if (charge.kind === "one-time") {
    return "one-time";
  }

  if (charge.kind === "monthly") {
    return "/ month";
  }

  return charge.label.toLowerCase();
};

const SERVICE_LABELS: Record<string, string> = {
  internet: "Internet Service",
  sim: "Mobile Service",
  vpn: "VPN Service",
};

function getServiceLabel(serviceCategory: string, orderType?: string) {
  return SERVICE_LABELS[serviceCategory] ?? (orderType ? `${orderType} Service` : "Service");
}

function formatPlacedDate(createdDate?: string, style: "full" | "medium" = "full"): string | null {
  if (!createdDate) return style === "medium" ? "—" : null;
  const formatted = formatIsoDate(createdDate, { dateStyle: style });
  return formatted === "Invalid date" ? (style === "medium" ? "—" : null) : formatted;
}

function useOrderDetailData(orderId: string | undefined) {
  const [data, setData] = useState<OrderDetails | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const activeControllerRef = useRef<AbortController | null>(null);
  const isMountedRef = useRef(true);

  const fetchOrder = useCallback(async (): Promise<void> => {
    if (!orderId) return;

    if (activeControllerRef.current) activeControllerRef.current.abort();
    const controller = new AbortController();
    activeControllerRef.current = controller;

    try {
      setIsLoading(true);
      const order = await ordersService.getOrderById(orderId, { signal: controller.signal });
      if (!isMountedRef.current || controller.signal.aborted) return;
      setData(order ?? null);
      setError(null);
    } catch (e) {
      if (!isMountedRef.current || controller.signal.aborted) return;
      setError(e instanceof Error ? e.message : "Failed to load order");
    } finally {
      if (activeControllerRef.current === controller) activeControllerRef.current = null;
      if (isMountedRef.current) setIsLoading(false);
    }
  }, [orderId]);

  useEffect(() => {
    isMountedRef.current = true;
    void fetchOrder();
    return () => {
      isMountedRef.current = false;
      if (activeControllerRef.current) {
        activeControllerRef.current.abort();
        activeControllerRef.current = null;
      }
    };
  }, [fetchOrder]);

  return { data, error, isLoading, fetchOrder };
}

function NewOrderBanner() {
  return (
    <div className="mb-6 rounded-2xl border border-success/25 bg-success-soft px-5 py-4 shadow-[var(--cp-shadow-1)]">
      <div className="flex items-start gap-3">
        <CheckCircleIcon className="h-6 w-6 text-success" />
        <div className="space-y-3">
          <div>
            <h3 className="text-lg font-semibold text-foreground">Order submitted</h3>
            <p className="text-sm text-muted-foreground">
              We&apos;ve received your order and started the review process. Status updates will
              appear here automatically.
            </p>
          </div>
          <ul className="list-disc space-y-1 pl-5 text-sm text-muted-foreground">
            <li>We&apos;ll confirm everything within 1 business day.</li>
            <li>You&apos;ll get an email as soon as the order is approved.</li>
            <li>Installation scheduling happens right after approval.</li>
          </ul>
        </div>
      </div>
    </div>
  );
}

function buildStatsGridItems(
  statusDescriptor: ReturnType<typeof deriveOrderStatusDescriptor> | null,
  statusPillVariant: string,
  totals: { monthlyTotal: number; oneTimeTotal: number },
  placedDateShort: string | null
): StatGridItem[] {
  return [
    {
      icon: <DocumentTextIcon className="h-5 w-5" />,
      label: "Order Status",
      value: statusDescriptor ? (
        <StatusPill
          label={statusDescriptor.label}
          variant={statusPillVariant as "success" | "info" | "warning" | "neutral"}
        />
      ) : (
        "—"
      ),
    },
    {
      icon: <CurrencyYenIcon className="h-5 w-5" />,
      label: "Monthly",
      value: totals.monthlyTotal > 0 ? Formatting.formatCurrency(totals.monthlyTotal) : "—",
    },
    {
      icon: <CurrencyYenIcon className="h-5 w-5" />,
      label: "One-Time",
      value: totals.oneTimeTotal > 0 ? Formatting.formatCurrency(totals.oneTimeTotal) : "—",
    },
    {
      icon: <CalendarDaysIcon className="h-5 w-5" />,
      label: "Order Date",
      value: placedDateShort ?? "—",
    },
  ];
}

function OrderItemRow({ item }: { item: OrderDisplayItem }) {
  const categoryConfig = CATEGORY_CONFIG[item.primaryCategory] ?? CATEGORY_CONFIG.other;
  const Icon = categoryConfig.icon;
  const style = getItemVisualStyle(item);

  return (
    <div
      className={cn(
        "flex flex-col gap-3 px-4 py-4 sm:flex-row sm:items-center sm:justify-between",
        style.container,
        "border-0 rounded-none"
      )}
    >
      <div className="flex flex-1 items-start gap-3">
        <div
          className={cn(
            "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg",
            style.icon
          )}
        >
          <Icon className="h-4 w-4" />
        </div>
        <div className="flex flex-1 items-baseline justify-between gap-4 sm:items-center">
          <div className="min-w-0 flex-1">
            <h4 className="font-semibold leading-snug text-foreground">{item.name}</h4>
            <p className="mt-0.5 text-xs font-semibold text-muted-foreground">
              {categoryConfig.label}
            </p>
          </div>
          <div className="flex flex-col items-end gap-0.5 text-right">
            {item.charges.map((charge, index) => {
              const descriptor = describeCharge(charge);
              return charge.amount > 0 ? (
                <div key={`${item.id}-charge-${index}`} className="whitespace-nowrap text-lg">
                  <span className="font-bold text-foreground">
                    {Formatting.formatCurrency(charge.amount)}
                  </span>
                  <span className="ml-2 text-xs font-medium text-muted-foreground">
                    {descriptor}
                  </span>
                </div>
              ) : (
                <div
                  key={`${item.id}-charge-${index}`}
                  className="text-xs font-medium text-muted-foreground"
                >
                  Included {descriptor}
                </div>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
}

function OrderItemsList({ items }: { items: OrderDisplayItem[] }) {
  if (items.length === 0) {
    return (
      <div className="rounded-xl border border-dashed border-border bg-muted px-4 py-8 text-center text-sm text-muted-foreground">
        No items found on this order.
      </div>
    );
  }
  return (
    <div className="rounded-xl border border-border overflow-hidden divide-y divide-border">
      {items.map(item => (
        <OrderItemRow key={item.id} item={item} />
      ))}
    </div>
  );
}

function OrderDetailHeader({
  serviceIcon,
  serviceLabel,
  placedDate,
  totals,
}: {
  serviceIcon: React.ReactNode;
  serviceLabel: string;
  placedDate: string | null;
  totals: { monthlyTotal: number; oneTimeTotal: number };
}) {
  return (
    <div className="border-b border-border bg-card px-6 py-6 sm:px-8">
      <div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
        <div className="flex flex-col gap-1">
          <div className="flex items-center gap-3">
            <div className="flex h-11 w-11 items-center justify-center rounded-xl bg-muted text-muted-foreground">
              {serviceIcon}
            </div>
            <div>
              <h2 className="text-2xl font-bold text-foreground">{serviceLabel}</h2>
              {placedDate && <p className="text-sm text-muted-foreground">{placedDate}</p>}
            </div>
          </div>
        </div>
        <div className="flex items-start gap-6 sm:gap-8">
          {totals.monthlyTotal > 0 && (
            <div className="text-right">
              <p className="mb-1 text-xs font-medium uppercase tracking-wider text-muted-foreground">
                Monthly
              </p>
              <p className="text-3xl font-bold text-foreground">
                {Formatting.formatCurrency(totals.monthlyTotal)}
              </p>
            </div>
          )}
          {totals.oneTimeTotal > 0 && (
            <div className="text-right">
              <p className="mb-1 text-xs font-medium uppercase tracking-wider text-muted-foreground">
                One-Time
              </p>
              <p className="text-3xl font-bold text-foreground">
                {Formatting.formatCurrency(totals.oneTimeTotal)}
              </p>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function NextStepsNotice({ nextAction }: { nextAction: string }) {
  return (
    <div className="border-l-4 border-info bg-info-soft px-4 py-3">
      <div className="flex items-start gap-3">
        <ClockIcon className="h-5 w-5 flex-shrink-0 text-info" />
        <div>
          <p className="text-sm font-semibold text-foreground">Next Steps</p>
          <p className="mt-1 text-sm text-muted-foreground">{nextAction}</p>
        </div>
      </div>
    </div>
  );
}

function FeeNotice() {
  return (
    <div className="border-l-4 border-warning bg-warning-soft px-4 py-3">
      <div className="flex items-start gap-3">
        <ExclamationTriangleIcon className="h-5 w-5 flex-shrink-0 text-warning" />
        <div>
          <p className="text-sm font-semibold text-foreground">Installation Fee Notice</p>
          <p className="mt-1 text-sm text-muted-foreground">
            Standard installation is included. Additional charges may apply for weekend scheduling,
            express service, or specialized equipment installation. Any extra fees will be discussed
            and approved by you before work begins.
          </p>
        </div>
      </div>
    </div>
  );
}

function useDerivedOrderData(data: OrderDetails | null) {
  const statusDescriptor = data
    ? deriveOrderStatusDescriptor({
        status: data.status,
        activationStatus: data.activationStatus ?? "",
        scheduledAt: data.activationScheduledAt ?? "",
      })
    : null;
  const statusPillVariant = statusDescriptor?.tone ?? "neutral";
  const serviceCategory = getServiceCategory(data?.orderType);
  const displayItems = useMemo<OrderDisplayItem[]>(
    () => buildOrderDisplayItems(data?.itemsSummary),
    [data?.itemsSummary]
  );
  const totals = useMemo(
    () =>
      calculateOrderTotals(
        data?.itemsSummary?.map(i => ({ totalPrice: i.totalPrice, billingCycle: i.billingCycle })),
        data?.totalAmount
      ),
    [data?.itemsSummary, data?.totalAmount]
  );
  const placedDate = useMemo(
    () => formatPlacedDate(data?.createdDate, "full"),
    [data?.createdDate]
  );
  const placedDateShort = useMemo(
    () => formatPlacedDate(data?.createdDate, "medium"),
    [data?.createdDate]
  );
  const serviceLabel = useMemo(
    () => getServiceLabel(serviceCategory, data?.orderType),
    [data?.orderType, serviceCategory]
  );
  const showFeeNotice = displayItems.some(
    item => item.categories.includes("installation") || item.categories.includes("activation")
  );
  const orderNumber = data?.orderNumber || (data ? String(data.id).slice(-8) : "");

  return {
    statusDescriptor,
    statusPillVariant,
    serviceCategory,
    displayItems,
    totals,
    placedDate,
    placedDateShort,
    serviceLabel,
    showFeeNotice,
    orderNumber,
  };
}

function OrderDetailLoadedContent({
  derived,
}: {
  derived: ReturnType<typeof useDerivedOrderData>;
}) {
  const {
    statusDescriptor,
    statusPillVariant,
    serviceCategory,
    displayItems,
    totals,
    placedDate,
    placedDateShort,
    serviceLabel,
    showFeeNotice,
  } = derived;
  const serviceIcon = <OrderServiceIcon category={serviceCategory} className="h-6 w-6" />;

  return (
    <div className="space-y-6">
      <DetailStatsGrid
        items={buildStatsGridItems(statusDescriptor, statusPillVariant, totals, placedDateShort)}
      />

      <SectionCard icon={<ClockIcon className="h-5 w-5" />} title="Order Progress" tone="info">
        {statusDescriptor && (
          <OrderProgressTimeline
            serviceCategory={serviceCategory}
            currentState={statusDescriptor.state}
          />
        )}
      </SectionCard>

      <div className="rounded-xl border border-border bg-card text-card-foreground shadow-[var(--cp-shadow-1)]">
        <OrderDetailHeader
          serviceIcon={serviceIcon}
          serviceLabel={serviceLabel}
          placedDate={placedDate}
          totals={totals}
        />
        <div className="px-6 py-6 sm:px-8">
          <div className="flex flex-col gap-6">
            <div>
              <h3
                className="mb-2 text-xs font-semibold uppercase tracking-widest text-muted-foreground"
                style={{ letterSpacing: "0.1em" }}
              >
                Order Details
              </h3>
              <div className="space-y-4">
                <OrderItemsList items={displayItems} />
              </div>
            </div>
            {statusDescriptor?.nextAction && (
              <NextStepsNotice nextAction={statusDescriptor.nextAction} />
            )}
            {showFeeNotice && <FeeNotice />}
          </div>
        </div>
      </div>
    </div>
  );
}

export function OrderDetailContainer() {
  const params = useParams<{ id: string }>();
  const searchParams = useSearchParams();
  const isNewOrder = searchParams.get("status") === "success";
  const clearCheckout = useCheckoutStore(state => state.clear);
  const { data, error, isLoading, fetchOrder } = useOrderDetailData(params.id);
  const derived = useDerivedOrderData(data);

  useEffect(() => {
    if (isNewOrder && data?.createdDate) {
      const orderAge = Date.now() - new Date(data.createdDate).getTime();
      if (orderAge < 5 * 60 * 1000) clearCheckout();
    }
  }, [isNewOrder, data?.createdDate, clearCheckout]);

  const handleOrderUpdate = useCallback(
    (event: OrderUpdateEventPayload) => {
      if (params.id && event.orderId === params.id) void fetchOrder();
    },
    [fetchOrder, params.id]
  );
  useOrderUpdates(params.id, handleOrderUpdate);

  const pageTitle = data ? `${data.orderType} Service Order` : "Order Details";

  return (
    <PageLayout
      icon={<ClipboardDocumentCheckIcon />}
      title={pageTitle}
      backLink={{ label: "Back to Orders", href: "/account/orders" }}
    >
      {error && <div className="mb-4 text-sm text-danger">{error}</div>}
      {isNewOrder && <NewOrderBanner />}
      {isLoading || !data ? (
        <OrderDetailSkeleton />
      ) : (
        <OrderDetailLoadedContent derived={derived} />
      )}
    </PageLayout>
  );
}

export default OrderDetailContainer;
