"use client";

import { Component, type ReactNode } from "react";
import type { Block, OutgoingInput } from "@/lib/chat/types";
import ContactCard from "./ContactCard";
import EnquiryCreated from "./EnquiryCreated";
import EnquiryDetail from "./EnquiryDetail";
import EnquiryForm from "./EnquiryForm";
import EnquiryList from "./EnquiryList";
import ErrorBlock from "./ErrorBlock";
import LeadCreated from "./LeadCreated";
import LeadForm from "./LeadForm";
import LoginCard from "./LoginCard";
import OrderDetail from "./OrderDetail";
import OrderList from "./OrderList";
import ProductList from "./ProductList";
import QuickReplies from "./QuickReplies";
import TextBlock from "./TextBlock";

/**
 * A block whose payload doesn't match the contract must not take the whole
 * chat down with it — it simply isn't shown.
 */
class BlockBoundary extends Component<{ children: ReactNode }, { failed: boolean }> {
  state = { failed: false };

  static getDerivedStateFromError() {
    return { failed: true };
  }

  render() {
    return this.state.failed ? null : this.props.children;
  }
}

type Props = {
  block: Block;
  /** Stable per block (`<messageId>:<index>`); forms use it to track submission. */
  blockKey: string;
  /** Client time the reply arrived (ms). */
  receivedAt: number;
  /** What the user sent to get this reply. */
  source: OutgoingInput | null;
  /** The form block that sent `source`, if any. */
  sourceFormKey?: string;
};

function renderBlock({ block, blockKey, receivedAt, source, sourceFormKey }: Props): ReactNode {
  switch (block.type) {
    case "text":
      return <TextBlock block={block} />;
    case "quick_replies":
      return <QuickReplies block={block} />;
    case "login_required":
      return <LoginCard block={block} />;
    case "order_list":
      return <OrderList block={block} />;
    case "order_detail":
      return <OrderDetail block={block} />;
    case "enquiry_list":
      return <EnquiryList block={block} />;
    case "enquiry_detail":
      return <EnquiryDetail block={block} receivedAt={receivedAt} />;
    case "enquiry_form":
      return <EnquiryForm block={block} formKey={blockKey} />;
    case "enquiry_created":
      return <EnquiryCreated block={block} />;
    case "product_list":
      return <ProductList block={block} />;
    case "lead_form":
      return <LeadForm block={block} formKey={blockKey} />;
    case "lead_created":
      return <LeadCreated block={block} />;
    case "contact":
      return <ContactCard block={block} />;
    case "error":
      return <ErrorBlock block={block} source={source} sourceFormKey={sourceFormKey} />;
    default:
      // Unknown block types (a newer server) are ignored.
      return null;
  }
}

export default function BlockRenderer(props: Props) {
  if (!props.block || typeof props.block !== "object") return null;
  return <BlockBoundary>{renderBlock(props)}</BlockBoundary>;
}
