import { cn } from "@code/ui/lib/utils";
import { ArrowUp, GripVertical, LoaderCircle } from "lucide-react";
import type { ComponentProps, ReactNode } from "react";

const MobileViewport = ({ className, ...props }: ComponentProps<"div">) => (
  <div
    data-slot="mobile-viewport"
    className={cn(
      "relative mx-auto h-[100dvh] min-h-0 w-full max-w-[390px] overflow-hidden bg-background text-foreground sm:border-x sm:border-border/70",
      className
    )}
    {...props}
  />
);

const MobileChatMark = ({ className, ...props }: ComponentProps<"span">) => (
  <span
    aria-hidden="true"
    data-slot="mobile-chat-mark"
    className={cn(
      "inline-flex size-6 shrink-0 items-center justify-center rounded-md bg-[#f1f1ef] text-[#171716]",
      className
    )}
    {...props}
  >
    <GripVertical className="size-3.5" strokeWidth={2.2} />
  </span>
);

interface MobileChatHeaderProps extends Omit<
  ComponentProps<"header">,
  "children"
> {
  active?: boolean;
  label?: string;
  statusLabel: string;
}

const MobileChatHeader = ({
  active = false,
  className,
  label = "Zopu",
  statusLabel,
  ...props
}: MobileChatHeaderProps) => (
  <header
    data-slot="mobile-chat-header"
    className={cn(
      "flex h-[78px] shrink-0 items-center border-b border-[#e9e9e7] bg-[#fefefe] px-4",
      className
    )}
    {...props}
  >
    <div className="flex w-full items-center gap-3">
      <MobileChatMark className="size-7 rounded-[7px]" />
      <h1 className="text-[17px] leading-none font-semibold tracking-[-0.015em] text-[#171716]">
        {label}
      </h1>
      <span
        aria-hidden="true"
        className={cn(
          "ml-auto size-1.5 rounded-full bg-[#b9bbb8]",
          active && "bg-[#17c777]"
        )}
      />
      <span className="sr-only" aria-live="polite">
        {statusLabel}
      </span>
    </div>
  </header>
);

interface MobileChatMessageProps extends Omit<
  ComponentProps<"article">,
  "role"
> {
  sender: "assistant" | "user";
}

const MobileChatMessage = ({
  className,
  sender,
  ...props
}: MobileChatMessageProps) => (
  <article
    data-sender={sender}
    data-slot="mobile-chat-message"
    className={cn(
      "flex w-full min-w-0",
      sender === "user" ? "justify-end" : "justify-start",
      className
    )}
    {...props}
  />
);

interface MobileChatBubbleProps extends Omit<ComponentProps<"div">, "role"> {
  sender: "assistant" | "user";
}

const MobileChatBubble = ({
  className,
  sender,
  ...props
}: MobileChatBubbleProps) => (
  <div
    data-sender={sender}
    data-slot="mobile-chat-bubble"
    className={cn(
      "min-w-0 text-[15px] tracking-[-0.012em] wrap-break-word",
      sender === "user"
        ? "max-w-[260px] rounded-[20px] bg-[#0d0d0c] px-[14px] py-[11px] leading-[18px] text-[#fafafa]"
        : "w-full leading-[18px] text-[#232321]",
      className
    )}
    {...props}
  />
);

interface MobileChatAssistantLabelProps extends ComponentProps<"div"> {
  label?: string;
  state?: ReactNode;
}

const MobileChatAssistantLabel = ({
  className,
  label = "Zopu",
  state,
  ...props
}: MobileChatAssistantLabelProps) => (
  <div
    data-slot="mobile-chat-assistant-label"
    className={cn(
      "mb-3 flex items-center gap-2 text-[14px] leading-5 text-[#6f706e]",
      className
    )}
    {...props}
  >
    <MobileChatMark className="size-5 rounded-[5px] [&_svg]:size-3" />
    <span>{label}</span>
    {state}
  </div>
);

interface MobileChatToolCallProps extends ComponentProps<"div"> {
  detail?: ReactNode;
  icon?: ReactNode;
  status: string;
  tone?: "error" | "neutral" | "success";
  toolName: string;
}

const MobileChatToolCall = ({
  children,
  className,
  detail,
  icon,
  status,
  tone = "neutral",
  toolName,
  ...props
}: MobileChatToolCallProps) => {
  let content: ReactNode;
  if (children) {
    content = <div className="mt-2 grid gap-2">{children}</div>;
  } else if (detail) {
    content = (
      <div className="mt-2 flex items-start gap-2">
        <MobileChatMark className="mt-0.5 size-4 rounded-[4px] [&_svg]:size-2.5" />
        <p className="line-clamp-2 min-w-0 text-[11px] leading-[15px] text-[#555653]">
          {detail}
        </p>
      </div>
    );
  }

  return (
    <div
      data-slot="mobile-chat-tool-call"
      className={cn(
        "mb-3 overflow-hidden rounded-[16px] bg-[#f4f4f2] px-3 py-3 text-[#171716]",
        className
      )}
      {...props}
    >
      <div className="flex min-h-5 items-center gap-2">
        <span className="flex size-5 shrink-0 items-center justify-center rounded-[5px] bg-[#e8e8e5] text-[#171716]">
          {icon ?? <GripVertical className="size-3" strokeWidth={2.2} />}
        </span>
        <span className="min-w-0 flex-1 truncate text-[12px] leading-4 font-semibold">
          {toolName}
        </span>
        <span
          className={cn(
            "rounded-full bg-[#e6e7e4] px-2 py-1 text-[9px] leading-none font-medium text-[#454643]",
            tone === "success" && "bg-[#dff5e8] text-[#174b32]",
            tone === "error" && "bg-[#f8dfdc] text-[#7b2821]"
          )}
        >
          {status}
        </span>
      </div>
      {content}
    </div>
  );
};

interface MobileChatToolResultProps extends ComponentProps<"div"> {
  icon?: ReactNode;
  source?: string;
  title: string;
}

const MobileChatToolResult = ({
  className,
  icon,
  source,
  title,
  ...props
}: MobileChatToolResultProps) => (
  <div
    data-slot="mobile-chat-tool-result"
    className={cn("flex min-w-0 items-start gap-2", className)}
    {...props}
  >
    <span className="mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-[4px] bg-[#e8e8e5] text-[#171716]">
      {icon ?? <GripVertical className="size-2.5" strokeWidth={2.2} />}
    </span>
    <span className="min-w-0">
      <span className="block truncate text-[11px] leading-[14px] font-medium text-[#292a28]">
        {title}
      </span>
      {source ? (
        <span className="block truncate text-[9px] leading-[12px] text-[#9a9b98]">
          {source}
        </span>
      ) : null}
    </span>
  </div>
);

interface MobileChatComposerDockProps extends ComponentProps<"div"> {
  errorMessage?: string;
  statusMessage?: ReactNode;
}

const MobileChatComposerDock = ({
  children,
  className,
  errorMessage,
  statusMessage,
  ...props
}: MobileChatComposerDockProps) => {
  const message = errorMessage ?? statusMessage;

  return (
    <div
      data-slot="mobile-chat-composer-dock"
      className={cn(
        "shrink-0 border-t border-[#e8e8e6] bg-[#fefefe] pb-[env(safe-area-inset-bottom)]",
        className
      )}
      {...props}
    >
      {message ? (
        <div
          id={errorMessage ? "composer-error" : undefined}
          className={cn(
            "px-3 pt-2 text-center text-[10px] leading-4 text-[#777875]",
            errorMessage && "text-destructive"
          )}
        >
          {message}
        </div>
      ) : null}
      {children}
    </div>
  );
};

interface MobileChatComposerProps extends Omit<
  ComponentProps<"form">,
  "children"
> {
  busy?: boolean;
  canSend: boolean;
  errorMessage?: string;
  statusMessage?: ReactNode;
  textareaProps: ComponentProps<"textarea">;
}

const MobileChatComposer = ({
  busy = false,
  canSend,
  className,
  errorMessage,
  statusMessage,
  textareaProps,
  ...props
}: MobileChatComposerProps) => {
  const { className: textareaClassName, ...inputProps } = textareaProps;

  return (
    <MobileChatComposerDock
      errorMessage={errorMessage}
      statusMessage={statusMessage}
    >
      <form
        aria-label="Send a message"
        className={cn("w-full px-3 pt-[11px] pb-3", className)}
        {...props}
      >
        <div className="flex items-end gap-2.5">
          <textarea
            aria-label="Message Zopu"
            placeholder="Message Zopu..."
            rows={1}
            className={cn(
              "min-h-10 max-h-28 flex-1 resize-none rounded-[20px] border-0 bg-[#f4f4f2] px-4 py-[10px] text-[15px] leading-5 text-[#232321] outline-none placeholder:text-center placeholder:text-[#b6b7b4] focus-visible:ring-2 focus-visible:ring-[#171716]/15 disabled:cursor-not-allowed disabled:opacity-60",
              textareaClassName
            )}
            {...inputProps}
          />
          <button
            aria-label="Send message"
            className="inline-flex size-10 shrink-0 items-center justify-center rounded-full bg-[#0d0d0c] text-[#fafafa] transition-transform active:scale-[0.96] disabled:bg-[#dededb] disabled:text-[#9b9c99]"
            disabled={!canSend}
            type="submit"
          >
            {busy ? (
              <LoaderCircle className="size-[18px] animate-spin" />
            ) : (
              <ArrowUp className="size-[18px]" strokeWidth={2.2} />
            )}
          </button>
        </div>
      </form>
    </MobileChatComposerDock>
  );
};

export {
  MobileChatAssistantLabel,
  MobileChatBubble,
  MobileChatComposer,
  MobileChatComposerDock,
  MobileChatHeader,
  MobileChatMark,
  MobileChatMessage,
  MobileChatToolResult,
  MobileChatToolCall,
  MobileViewport,
};
export type {
  MobileChatAssistantLabelProps,
  MobileChatBubbleProps,
  MobileChatComposerProps,
  MobileChatComposerDockProps,
  MobileChatHeaderProps,
  MobileChatMessageProps,
  MobileChatToolCallProps,
  MobileChatToolResultProps,
};
