import { cn } from "@code/ui/lib/utils";
import {
  ArrowLeft,
  ArrowUp,
  Check,
  ChevronRight,
  ExternalLink,
  FileText,
  ListChecks,
  LoaderCircle,
  Mic,
  MoreHorizontal,
  Paperclip,
  Plus,
  Sparkles,
  X,
} from "lucide-react";
import type { FormEvent, ReactNode } from "react";

import type {
  MobileProjectView,
  MobileWorkspaceView,
  MobileWorkUnitTone,
  MobileWorkUnitView,
} from "./mobile-workspace/models";

export type MobileWorkspaceVariant =
  | "character-pass"
  | "expanded-work-unit"
  | "home-expanded-in-place"
  | "vertical-work-stack"
  | "work-units-home";

export interface MobileWorkspaceRendererProps {
  composerValue: string;
  createIssueBody: string;
  createIssueTitle: string;
  data: MobileWorkspaceView;
  onBack?: () => void;
  onComposerChange: (value: string) => void;
  onComposerSubmit: (event: FormEvent<HTMLFormElement>) => void;
  onCreateBodyChange: (value: string) => void;
  onCreateIssue: (event: FormEvent<HTMLFormElement>) => void;
  onCreateIssueFromSignal?: () => void;
  onCreateTitleChange: (value: string) => void;
  onManageProjects?: () => void;
  onOpenAssistant?: () => void;
  onOpenUnit?: (workUnitId?: string) => void;
  onProjectSelect?: (projectId: string) => void;
  onReviewUnit?: (reviewUrl: string) => void;
  onStartUnit?: (workUnitId: string) => void;
  onViewWork?: () => void;
  pendingAction?: string | null;
  statusMessage?: string;
  variant: MobileWorkspaceVariant;
}

const BrandGlyph = ({ className }: { className?: string }) => (
  <span
    aria-hidden="true"
    className={cn(
      "inline-flex h-[23px] w-[9px] items-center justify-center bg-black text-[4px] leading-none font-bold tracking-[-0.08em] text-white [writing-mode:vertical-rl]",
      className
    )}
  >
    ZOPU
  </span>
);

interface ProductHeaderProps {
  avatar?: boolean;
  letterLogo?: boolean;
  onAssistant?: () => void;
  onManageProjects?: () => void;
  profileInset?: boolean;
  subtitle?: string;
}

const ProductHeader = ({
  avatar = false,
  letterLogo = false,
  onAssistant,
  onManageProjects,
  profileInset = false,
  subtitle = "Workspace is active",
}: ProductHeaderProps) => (
  <header className="flex h-20 shrink-0 items-center bg-white px-4">
    <div className="flex size-10 items-center justify-center rounded-[14px] bg-[#c8ff00] text-[20px] font-bold text-black">
      {letterLogo ? "Z" : <BrandGlyph />}
    </div>
    <div className="ml-3">
      <h1 className="text-[20px] leading-6 font-semibold tracking-[-0.03em] text-[#0b0b0a]">
        Zopu
      </h1>
      <p className="mt-0.5 flex items-center gap-2 text-[13px] leading-4 text-[#7c7772]">
        <span className="size-1.5 rounded-full bg-[#64ad1f]" />
        {subtitle}
      </p>
    </div>
    {avatar ? (
      <button
        aria-label="Open profile"
        className={cn(
          "ml-auto flex size-[42px] items-center justify-center rounded-full bg-[#0b0b0a] text-[13px] font-semibold text-white",
          profileInset && "mr-[31px]"
        )}
        onClick={onManageProjects}
        type="button"
      >
        YM
      </button>
    ) : (
      <>
        <button
          aria-label="Open Zopu assistant"
          className="ml-auto flex size-10 items-center justify-center rounded-full bg-[#f2f3ef]"
          onClick={onAssistant}
          type="button"
        >
          <BrandGlyph className="h-[20px] w-[8px]" />
        </button>
        <button
          aria-label="More options"
          className="ml-2 flex size-10 items-center justify-center rounded-full bg-[#f2f3ef]"
          onClick={onManageProjects}
          type="button"
        >
          <MoreHorizontal className="size-5" />
        </button>
      </>
    )}
  </header>
);

interface ComposerProps {
  contextLabel?: string;
  deviceHomeIndicator?: boolean;
  hint?: string;
  homeIndicator?: boolean;
  onChange: (value: string) => void;
  onSubmit: (event: FormEvent<HTMLFormElement>) => void;
  placeholder: string;
  sendBlue?: boolean;
  statusMessage?: string;
  value: string;
}

const ReferenceComposer = ({
  contextLabel,
  deviceHomeIndicator = false,
  hint,
  homeIndicator = false,
  onChange,
  onSubmit,
  placeholder,
  sendBlue = false,
  statusMessage,
  value,
}: ComposerProps) => (
  <footer
    className={cn(
      "relative shrink-0 border-t border-[#eff0ec] bg-white px-[14px]",
      contextLabel ? "h-[144px] pt-[13px]" : "h-[120px] pt-[14px]",
      !homeIndicator && !contextLabel && "h-[100px]",
      deviceHomeIndicator && "h-[125px]"
    )}
  >
    {contextLabel ? (
      <div className="mb-2 flex h-6 w-fit items-center gap-2 rounded-full bg-[#dbe6ff] px-2.5 text-[10px] font-semibold text-[#315dc0]">
        <span className="size-1.5 rounded-full bg-[#315dc0]" />
        {contextLabel}
        <X className="size-3" />
      </div>
    ) : null}
    <form
      className="flex h-[60px] items-center rounded-[30px] bg-[#f2f3ef] p-2"
      onSubmit={onSubmit}
    >
      <button
        aria-label="Add attachment"
        className="flex size-11 shrink-0 items-center justify-center rounded-full bg-white text-[#5e5a56]"
        type="button"
      >
        <Plus className="size-5" strokeWidth={1.8} />
      </button>
      <label className="ml-2 min-w-0 flex-1">
        <span className="sr-only">{placeholder}</span>
        <textarea
          className="block h-5 w-full resize-none overflow-hidden bg-transparent text-[14px] leading-5 text-[#282622] outline-none placeholder:text-[#b3afab]"
          onChange={(event) => onChange(event.target.value)}
          placeholder={placeholder}
          rows={1}
          value={value}
        />
        {hint || statusMessage ? (
          <span className="block truncate text-[10px] leading-4 text-[#c0bcb7]">
            {statusMessage ?? hint}
          </span>
        ) : null}
      </label>
      <button
        aria-label="Send"
        className={cn(
          "ml-2 flex size-11 shrink-0 items-center justify-center rounded-full text-white",
          sendBlue ? "bg-[#315dc0]" : "bg-black",
          !value.trim() && "opacity-100"
        )}
        type="submit"
      >
        <ArrowUp className="size-5" strokeWidth={2.2} />
      </button>
    </form>
    {homeIndicator ? (
      <span className="absolute bottom-[13px] left-1/2 h-[5px] w-[120px] -translate-x-1/2 rounded-full bg-black" />
    ) : null}
  </footer>
);

interface CreateWorkFormProps {
  readonly body: string;
  readonly onBodyChange: (value: string) => void;
  readonly onSubmit: (event: FormEvent<HTMLFormElement>) => void;
  readonly onTitleChange: (value: string) => void;
  readonly pending: boolean;
  readonly title: string;
}

const CreateWorkForm = ({
  body,
  onBodyChange,
  onSubmit,
  onTitleChange,
  pending,
  title,
}: CreateWorkFormProps) => (
  <form className="mt-4 rounded-[22px] bg-white p-3" onSubmit={onSubmit}>
    <div className="flex items-center">
      <p className="text-[10px] font-semibold uppercase text-[#807b76]">
        Create project work
      </p>
      {pending ? (
        <LoaderCircle className="ml-auto size-3 animate-spin" />
      ) : null}
    </div>
    <input
      aria-label="Work title"
      className="mt-2 h-9 w-full rounded-[12px] bg-[#f2f3ef] px-3 text-[13px] outline-none placeholder:text-[#b3afab]"
      disabled={pending}
      onChange={(event) => onTitleChange(event.target.value)}
      placeholder="Outcome or issue title"
      required
      value={title}
    />
    <textarea
      aria-label="Work description"
      className="mt-2 min-h-16 w-full resize-none rounded-[12px] bg-[#f2f3ef] px-3 py-2 text-[12px] leading-4 outline-none placeholder:text-[#b3afab]"
      disabled={pending}
      onChange={(event) => onBodyChange(event.target.value)}
      placeholder="Describe the desired result or constraints"
      required
      value={body}
    />
    <button
      className="mt-2 h-9 w-full rounded-[12px] bg-black text-[12px] font-semibold text-white disabled:opacity-50"
      disabled={pending || !title.trim() || !body.trim()}
      type="submit"
    >
      {pending ? "Creating…" : "Create work"}
    </button>
  </form>
);

const ProjectSwitcher = ({
  data,
  onManageProjects,
  onProjectSelect,
}: {
  readonly data: MobileWorkspaceView;
  readonly onManageProjects?: () => void;
  readonly onProjectSelect?: (projectId: string) => void;
}) => (
  <div className="flex items-center gap-2 border-b border-[#eff0ec] bg-white px-4 py-2">
    <label className="sr-only" htmlFor="mobile-project-selector">
      Active project
    </label>
    <select
      className="min-w-0 flex-1 bg-transparent text-[12px] font-semibold outline-none"
      id="mobile-project-selector"
      onChange={(event) => onProjectSelect?.(event.target.value)}
      value={data.selectedProjectId ?? ""}
    >
      {data.projects.length === 0 ? (
        <option value="">No connected projects</option>
      ) : (
        data.projects.map((project: MobileProjectView) => (
          <option key={project.id} value={project.id}>
            {project.name} {project.connected ? "" : "(not connected)"}
          </option>
        ))
      )}
    </select>
    <button
      aria-label="Manage projects"
      className="flex size-8 items-center justify-center rounded-full bg-[#f2f3ef]"
      onClick={onManageProjects}
      type="button"
    >
      <MoreHorizontal className="size-4" />
    </button>
  </div>
);

const WorkUnitActions = ({
  onReview,
  onStart,
  pending,
  workUnit,
}: {
  readonly onReview?: (reviewUrl: string) => void;
  readonly onStart?: (workUnitId: string) => void;
  readonly pending: boolean;
  readonly workUnit?: MobileWorkUnitView;
}) => {
  if (!workUnit) {
    return null;
  }
  return (
    <div className="mt-3 flex gap-2">
      {workUnit.canStart || workUnit.canRetry ? (
        <button
          className="flex h-9 flex-1 items-center justify-center gap-2 rounded-[12px] bg-black text-[12px] font-semibold text-white disabled:opacity-50"
          disabled={pending}
          onClick={() => onStart?.(workUnit.id)}
          type="button"
        >
          {pending ? <LoaderCircle className="size-3 animate-spin" /> : null}
          {workUnit.canRetry ? "Retry work" : "Start work"}
        </button>
      ) : null}
      {workUnit.reviewUrl ? (
        <button
          className="flex h-9 flex-1 items-center justify-center gap-2 rounded-[12px] bg-[#c8ff00] text-[12px] font-semibold text-black"
          onClick={() => onReview?.(workUnit.reviewUrl as string)}
          type="button"
        >
          <ExternalLink className="size-3.5" />
          Review PR
          {workUnit.pullRequestNumber ? ` #${workUnit.pullRequestNumber}` : ""}
        </button>
      ) : null}
    </div>
  );
};

const workUnitToneClass: Record<MobileWorkUnitTone, string> = {
  blue: "bg-[#e8efff] text-[#14265f]",
  green: "bg-[#e8f7ef] text-[#105c35]",
  orange: "bg-[#fff0e8] text-[#8a2e13]",
  purple: "bg-[#f1e8ff] text-[#3e0b74]",
};

const workUnitStatusClass: Record<MobileWorkUnitTone, string> = {
  blue: "text-[#315dc0]",
  green: "text-[#238050]",
  orange: "text-[#c53c08]",
  purple: "text-[#7137ef]",
};

const EmptyWorkState = ({
  isLoading,
  onManageProjects,
}: {
  isLoading: boolean;
  onManageProjects?: () => void;
}) => (
  <article className="mt-3 grid h-[190px] place-items-center rounded-[27px] bg-white p-6 text-center">
    <div>
      <p className="text-[15px] font-semibold">
        {isLoading ? "Loading your work…" : "No work units yet"}
      </p>
      <p className="mt-1 text-[12px] leading-4 text-[#807b76]">
        {isLoading
          ? "Zopu is syncing projects, signals, and activity."
          : "Import a project and create an issue to start the flow."}
      </p>
      <button
        className={cn(
          "mt-4 rounded-[14px] bg-[#c8ff00] px-4 py-2 text-[12px] font-semibold",
          isLoading && "invisible"
        )}
        disabled={isLoading}
        onClick={onManageProjects}
        type="button"
      >
        Manage projects
      </button>
    </div>
  </article>
);

const WorkFeedScreen = ({
  createIssueBody,
  createIssueTitle,
  data,
  onChange,
  onCreateBodyChange,
  onCreateIssue,
  onCreateTitleChange,
  onManageProjects,
  onOpenAssistant,
  onOpen,
  onProjectSelect,
  onReviewUnit,
  onStartUnit,
  onSubmit,
  onViewWork,
  pendingAction,
  statusMessage,
  value,
}: ComposerProps & {
  createIssueBody: string;
  createIssueTitle: string;
  data: MobileWorkspaceView;
  onCreateBodyChange: (value: string) => void;
  onCreateIssue: (event: FormEvent<HTMLFormElement>) => void;
  onCreateTitleChange: (value: string) => void;
  onManageProjects?: () => void;
  onOpen?: (workUnitId?: string) => void;
  onOpenAssistant?: () => void;
  onProjectSelect?: (projectId: string) => void;
  onReviewUnit?: (reviewUrl: string) => void;
  onStartUnit?: (workUnitId: string) => void;
  pendingAction?: string | null;
  onViewWork?: () => void;
}) => {
  const primaryWorkUnit = data.selectedWorkUnit;
  const secondaryWorkUnits = data.workUnits
    .filter((workUnit) => workUnit.id !== primaryWorkUnit?.id)
    .slice(0, 2);

  return (
    <div className="mx-auto flex h-[min(100dvh,844px)] w-full max-w-[390px] flex-col overflow-hidden bg-white text-[#0b0b0a]">
      <ProductHeader
        onAssistant={onOpenAssistant}
        onManageProjects={onManageProjects}
        subtitle={`${data.activeCount} active work units`}
      />
      <ProjectSwitcher
        data={data}
        onManageProjects={onManageProjects}
        onProjectSelect={onProjectSelect}
      />
      <main className="min-h-0 flex-1 bg-[#f7f8f5] px-4 pt-4">
        <h2 className="text-[29px] leading-9 font-semibold tracking-[-0.05em]">
          Good morning.
        </h2>
        <p className="text-[14px] leading-5 text-[#807b76]">
          {data.projectName
            ? `${data.projectName} is moving. ${data.needsAttentionCount} things need you.`
            : "Connect a project to put work in motion."}
        </p>
        <div className="mt-2 grid h-[55px] grid-cols-3 gap-2">
          <div className="rounded-[18px] bg-white px-2.5 py-2">
            <p className="text-[9px] font-semibold text-[#aaa6a1]">ACTIVE</p>
            <p className="text-[17px] leading-5 font-semibold">
              {data.activeCount} units
            </p>
          </div>
          <div className="rounded-[18px] bg-[#fff0e8] px-2.5 py-2 text-[#9a3215]">
            <p className="text-[9px] font-semibold">NEEDS YOU</p>
            <p className="text-[17px] leading-5 font-semibold">
              {data.needsAttentionCount} blockers
            </p>
          </div>
          <div className="rounded-[18px] bg-[#e8f7ef] px-2.5 py-2 text-[#23633d]">
            <p className="text-[9px] font-semibold">SHIPPED</p>
            <p className="text-[17px] leading-5 font-semibold">
              {data.shippedCount} total
            </p>
          </div>
        </div>
        <div className="mt-[18px] flex items-center">
          <h3 className="text-[14px] font-semibold">Now</h3>
          <button
            className="ml-auto text-[12px] text-[#807b76]"
            onClick={onViewWork}
            type="button"
          >
            View all {data.totalCount}
          </button>
        </div>
        {primaryWorkUnit ? (
          <article
            className={cn(
              "mt-3 h-[190px] rounded-[27px] p-[14px]",
              workUnitToneClass[primaryWorkUnit.tone]
            )}
          >
            <div className="flex items-center">
              <span className="flex size-[26px] items-center justify-center rounded-[9px] bg-white text-[#315dc0]">
                ↗
              </span>
              <div className="ml-2">
                <p
                  className={cn(
                    "text-[10px] font-semibold uppercase",
                    workUnitStatusClass[primaryWorkUnit.tone]
                  )}
                >
                  {primaryWorkUnit.statusLabel} · {primaryWorkUnit.progress}%
                </p>
                <p className="text-[10px] text-[#60718e]">
                  Updated {primaryWorkUnit.updatedLabel}
                </p>
              </div>
              <ChevronRight className="ml-auto size-4 text-[#315dc0]" />
            </div>
            <h3 className="mt-3 text-[20px] leading-6 font-semibold tracking-[-0.035em]">
              {primaryWorkUnit.title}
            </h3>
            <p className="mt-1 overflow-hidden text-[13px] leading-5 whitespace-nowrap text-[#526482]">
              {data.latestSignal?.summary ?? primaryWorkUnit.summary}
            </p>
            <div className="mt-3 h-[7px] rounded-full bg-[#315dc0]/15">
              <div
                className="h-full rounded-full bg-[#315dc0]"
                style={{ width: `${primaryWorkUnit.progress}%` }}
              />
            </div>
            <div className="mt-[10px] flex h-[42px] gap-2">
              <div className="min-w-0 flex-1 rounded-[14px] bg-white px-2 py-1.5">
                <p className="text-[9px] font-semibold text-[#8a97b5]">
                  NEXT ACTION
                </p>
                <p className="truncate text-[12px] font-semibold">
                  {primaryWorkUnit.nextAction}
                </p>
              </div>
              <button
                className="rounded-[14px] bg-[#c8ff00] px-4 text-[12px] font-semibold text-black"
                onClick={() => onOpen?.(primaryWorkUnit.id)}
                type="button"
              >
                Open unit →
              </button>
            </div>
            <WorkUnitActions
              onReview={onReviewUnit}
              onStart={onStartUnit}
              pending={pendingAction === `issue:${primaryWorkUnit.id}`}
              workUnit={primaryWorkUnit}
            />
          </article>
        ) : (
          <EmptyWorkState
            isLoading={data.isLoading}
            onManageProjects={onManageProjects}
          />
        )}
        <CreateWorkForm
          body={createIssueBody}
          onBodyChange={onCreateBodyChange}
          onSubmit={onCreateIssue}
          onTitleChange={onCreateTitleChange}
          pending={pendingAction === "issue"}
          title={createIssueTitle}
        />
        {secondaryWorkUnits[0] ? (
          <article
            className={cn(
              "mt-[14px] h-[116px] rounded-[25px] p-[14px]",
              workUnitToneClass[secondaryWorkUnits[0].tone]
            )}
          >
            <div className="flex items-center text-[10px] font-semibold text-[#c53c08]">
              <span className="mr-2 size-2 rounded-full bg-[#ff7620]" />
              {secondaryWorkUnits[0].statusLabel.toUpperCase()}
              <ChevronRight className="ml-auto size-4" />
            </div>
            <h3 className="mt-[13px] text-[18px] leading-5 font-semibold">
              {secondaryWorkUnits[0].title}
            </h3>
            <div className="mt-2 flex items-center">
              <div>
                <p className="max-w-[240px] truncate text-[12px]">
                  {secondaryWorkUnits[0].summary}
                </p>
                <p className="text-[10px] text-[#b3aaa5]">
                  Updated {secondaryWorkUnits[0].updatedLabel}
                </p>
              </div>
              <button
                className="ml-auto rounded-[13px] bg-white px-5 py-2 text-[11px] font-semibold"
                onClick={() => onOpen?.(secondaryWorkUnits[0]?.id)}
                type="button"
              >
                Open
              </button>
            </div>
          </article>
        ) : null}
        <div className="mt-[14px] grid h-[94px] grid-cols-2 gap-[10px]">
          {secondaryWorkUnits.slice(1).map((workUnit) => (
            <article
              className={cn(
                "rounded-[24px] p-3",
                workUnitToneClass[workUnit.tone]
              )}
              key={workUnit.id}
            >
              <div
                className={cn(
                  "flex text-[10px] font-semibold uppercase",
                  workUnitStatusClass[workUnit.tone]
                )}
              >
                {workUnit.statusLabel}
                <span className="ml-auto font-normal">
                  {workUnit.progress}%
                </span>
              </div>
              <h3 className="mt-3 text-[15px] font-semibold">
                {workUnit.title}
              </h3>
              <p className="mt-1 truncate text-[11px] opacity-65">
                {workUnit.summary}
              </p>
            </article>
          ))}
        </div>
      </main>
      <footer className="h-[100px] shrink-0 border-t border-[#eff0ec] bg-white px-3 pt-[10px]">
        <div className="mb-[7px] flex h-5 w-fit items-center gap-2 rounded-full bg-[#f1f2ef] px-2 text-[10px] font-semibold text-[#5f5b57]">
          <span className="size-1.5 rounded-full bg-[#c8ff00]" />
          GLOBAL MODE
        </div>
        <form
          className="flex h-[52px] items-center rounded-[26px] bg-[#f2f3ef] p-2"
          onSubmit={onSubmit}
        >
          <button
            aria-label="Add attachment"
            className="flex size-9 items-center justify-center rounded-full bg-white"
            type="button"
          >
            <Plus className="size-5" />
          </button>
          <input
            className="min-w-0 flex-1 bg-transparent px-2 text-[14px] outline-none placeholder:text-[#b3afab]"
            onChange={(event) => onChange(event.target.value)}
            placeholder="Ask anything or create new work..."
            value={value}
          />
          <button
            aria-label="Send"
            className="flex size-9 items-center justify-center rounded-full bg-black text-white"
            type="submit"
          >
            <ArrowUp className="size-5" />
          </button>
        </form>
        {statusMessage ? (
          <span className="sr-only">{statusMessage}</span>
        ) : null}
      </footer>
    </div>
  );
};

const DeviceFrame402 = ({ children }: { children: ReactNode }) => (
  <div className="mx-auto h-[min(100dvh,855px)] w-full max-w-[402px] overflow-hidden bg-black p-[5px] pb-0">
    <div className="flex h-full min-h-0 flex-col overflow-hidden bg-white">
      {children}
    </div>
  </div>
);

const getExpandedTitle = (
  workUnit: MobileWorkUnitView | undefined,
  isLoading: boolean
) => {
  if (workUnit) {
    return workUnit.title;
  }
  return isLoading ? "Loading work…" : "No work selected";
};

const getUpdatedLabel = (
  workUnit: MobileWorkUnitView | undefined,
  compact: boolean
) => {
  if (!workUnit) {
    return "Waiting for project data";
  }
  return compact ? workUnit.updatedLabel : `Updated ${workUnit.updatedLabel}`;
};

const getExpandedLayout = (
  compact: boolean,
  workUnit: MobileWorkUnitView | undefined
) => ({
  articleHeight: compact ? "h-[500px]" : "h-[610px]",
  articleTone: workUnit
    ? workUnitToneClass[workUnit.tone]
    : "bg-[#e8efff] text-[#14265f]",
  milestoneSpacing: compact ? "mt-5" : "mt-[35px]",
  summarySpacing: compact ? "mt-3" : "mt-[43px]",
  titleSize: compact
    ? "mt-4 text-[27px] leading-[30px]"
    : "mt-5 text-[29px] leading-[31px]",
});

const ExpandedWorkUnitActivity = ({
  compact,
  data,
  workUnit,
}: {
  compact: boolean;
  data: MobileWorkspaceView;
  workUnit?: MobileWorkUnitView;
}) => {
  if (compact) {
    return (
      <div className="mt-[14px] flex items-center gap-3">
        <span className="flex size-[30px] items-center justify-center rounded-[10px] bg-white text-[#315dc0]">
          Z
        </span>
        <div>
          <p className="text-[11px] font-semibold text-[#33405c]">
            {workUnit?.title ?? "Project workspace ready"}
          </p>
          <p className="text-[10px] text-[#6e83b4]">
            Zopu · {workUnit?.updatedLabel ?? "now"}
          </p>
        </div>
      </div>
    );
  }

  return (
    <>
      <div className="mt-[14px] flex text-[10px] font-semibold text-[#6e83b4]">
        RECENT ACTIVITY
        <span className="ml-auto font-normal text-[#315dc0]">View all</span>
      </div>
      <div className="mt-3 grid gap-3">
        <div className="flex items-center gap-3">
          <span className="flex size-7 items-center justify-center rounded-[9px] bg-white text-[#315dc0]">
            Z
          </span>
          <div>
            <p className="text-[11px] font-semibold text-[#33405c]">
              {data.latestSignal?.title ?? "Zopu updated the project signal"}
            </p>
            <p className="text-[10px] text-[#6e83b4]">
              {workUnit?.updatedLabel ?? "Recently"}
            </p>
          </div>
        </div>
        <div className="flex items-center gap-3">
          <span className="flex size-7 items-center justify-center rounded-[9px] bg-white text-[#315dc0]">
            ↗
          </span>
          <div>
            <p className="text-[11px] font-semibold text-[#33405c]">
              {data.artifactCount} project artifacts available
            </p>
            <p className="text-[10px] text-[#6e83b4]">
              Synced from {data.projectName ?? data.organizationLabel}
            </p>
          </div>
        </div>
      </div>
    </>
  );
};

const ExpandedWorkUnitContent = ({
  compact = false,
  data,
  onReview,
  onStart,
  pendingAction,
}: {
  compact?: boolean;
  data: MobileWorkspaceView;
  onReview?: (reviewUrl: string) => void;
  onStart?: (workUnitId: string) => void;
  pendingAction?: string | null;
}) => {
  const workUnit = data.selectedWorkUnit;
  const title = getExpandedTitle(workUnit, data.isLoading);
  const summary =
    data.latestSignal?.summary ??
    workUnit?.summary ??
    "Create an issue in the project workspace to begin.";
  const nextAction =
    data.latestSignal?.desiredOutcome ??
    workUnit?.nextAction ??
    "Manage project work";
  const progress = workUnit?.progress ?? 0;
  const layout = getExpandedLayout(compact, workUnit);
  const milestoneNote = data.latestSignal
    ? `Signal: ${data.latestSignal.title}`
    : "Ready for your review";

  return (
    <article
      className={cn(
        "rounded-[30px] p-5",
        layout.articleTone,
        layout.articleHeight
      )}
    >
      <div className="flex items-center">
        <span className="rounded-full bg-[#d6e2ff] px-2 py-1 text-[10px] font-semibold text-[#315dc0]">
          {workUnit?.statusLabel.toUpperCase() ?? "WORKSPACE"}
        </span>
        <span className="ml-auto text-[11px] text-[#6e83b4]">{progress}%</span>
      </div>
      <h1 className={cn("font-semibold tracking-[-0.045em]", layout.titleSize)}>
        {title}
      </h1>
      <p
        className={cn(
          "text-[14px] leading-5 text-[#60718e]",
          layout.summarySpacing
        )}
      >
        {summary}
      </p>
      <div className="mt-[14px] h-[7px] rounded-full bg-[#315dc0]/15">
        <div
          className="h-full rounded-full bg-[#315dc0]"
          style={{ width: `${progress}%` }}
        />
      </div>
      <div className="mt-1.5 flex text-[10px] font-semibold text-[#315dc0]">
        {workUnit?.statusLabel.toUpperCase() ?? "READY"}
        <span className="ml-auto font-normal text-[#6e83b4]">
          {getUpdatedLabel(workUnit, compact)}
        </span>
      </div>
      <div className="mt-[18px] border-t border-[#315dc0]/15 pt-[14px]">
        <p className="text-[10px] font-semibold text-[#6e83b4]">
          CURRENT STATE
        </p>
        <p className="mt-1 text-[14px] leading-5 text-[#33405c]">{summary}</p>
      </div>
      <section
        className={cn(
          "flex items-center rounded-[19px] bg-white p-3",
          layout.milestoneSpacing
        )}
      >
        <span className="flex size-10 shrink-0 items-center justify-center rounded-[13px] bg-[#c8ff00] text-black">
          <Check className="size-5" />
        </span>
        <div className="ml-3 min-w-0">
          <p className="text-[10px] font-semibold text-[#6e83b4]">
            NEXT MILESTONE
          </p>
          <p className="truncate text-[14px] font-semibold">{nextAction}</p>
          <p className="text-[10px] text-[#6e83b4]">{milestoneNote}</p>
        </div>
      </section>
      <div className="mt-[14px] grid h-[78px] grid-cols-2 gap-[10px]">
        <div className="rounded-[19px] bg-[#dce6fc] p-3">
          <p className="text-[10px] font-semibold text-[#6e83b4]">ARTIFACTS</p>
          <strong className="mt-1 block text-xl">{data.artifactCount}</strong>
          <span className="text-[10px] text-[#60718e]">Project context</span>
        </div>
        <div className="rounded-[19px] bg-[#dce6fc] p-3">
          <p className="text-[10px] font-semibold text-[#6e83b4]">ACTIVITY</p>
          <strong className="mt-1 block text-xl">{data.activityCount}</strong>
          <span className="text-[10px] text-[#60718e]">Issues and signals</span>
        </div>
      </div>
      <ExpandedWorkUnitActivity
        compact={compact}
        data={data}
        workUnit={workUnit}
      />
      <WorkUnitActions
        onReview={onReview}
        onStart={onStart}
        pending={pendingAction === `issue:${workUnit?.id}`}
        workUnit={workUnit}
      />
    </article>
  );
};

const WorkUnitScreen = ({
  createIssueBody,
  createIssueTitle,
  data,
  onBack,
  onChange,
  onCreateBodyChange,
  onCreateIssue,
  onCreateTitleChange,
  onManageProjects,
  onSubmit,
  onProjectSelect,
  onReviewUnit,
  onStartUnit,
  pendingAction,
  statusMessage,
  value,
}: ComposerProps & {
  createIssueBody: string;
  createIssueTitle: string;
  data: MobileWorkspaceView;
  onCreateBodyChange: (value: string) => void;
  onCreateIssue: (event: FormEvent<HTMLFormElement>) => void;
  onCreateTitleChange: (value: string) => void;
  onBack?: () => void;
  onManageProjects?: () => void;
  onProjectSelect?: (projectId: string) => void;
  onReviewUnit?: (reviewUrl: string) => void;
  onStartUnit?: (workUnitId: string) => void;
  pendingAction?: string | null;
}) => (
  <DeviceFrame402>
    <header className="flex h-20 shrink-0 items-center bg-white px-4">
      <button
        aria-label="Back to work units"
        className="flex size-10 items-center justify-center rounded-full bg-[#fbfcf9]"
        onClick={onBack}
        type="button"
      >
        <ArrowLeft className="size-5" />
      </button>
      <div className="min-w-0 flex-1 text-center">
        <p className="text-[16px] font-semibold">Work unit</p>
        <p className="text-[11px] text-[#807b76]">
          {data.selectedWorkUnit
            ? `${data.selectedWorkUnit.code} · ${data.selectedWorkUnit.statusLabel}`
            : data.organizationLabel}
        </p>
      </div>
      <button
        aria-label="More work unit actions"
        className="flex size-10 items-center justify-center rounded-full bg-[#fbfcf9]"
        onClick={onManageProjects}
        type="button"
      >
        <MoreHorizontal className="size-5" />
      </button>
    </header>
    <ProjectSwitcher
      data={data}
      onManageProjects={onManageProjects}
      onProjectSelect={onProjectSelect}
    />
    <main className="min-h-0 flex-1 bg-[#f7f8f5] px-[17px] pt-4">
      <ExpandedWorkUnitContent
        data={data}
        onReview={onReviewUnit}
        onStart={onStartUnit}
        pendingAction={pendingAction}
      />
    </main>
    <CreateWorkForm
      body={createIssueBody}
      onBodyChange={onCreateBodyChange}
      onSubmit={onCreateIssue}
      onTitleChange={onCreateTitleChange}
      pending={pendingAction === "issue"}
      title={createIssueTitle}
    />
    <ReferenceComposer
      contextLabel={
        data.selectedWorkUnit?.title.toUpperCase() ?? "PROJECT WORK"
      }
      hint="Zopu can use your project signals"
      onChange={onChange}
      onSubmit={onSubmit}
      placeholder="Ask about this work unit..."
      sendBlue
      statusMessage={statusMessage}
      value={value}
    />
  </DeviceFrame402>
);

const VerticalStack = ({
  data,
  onChange,
  onManageProjects,
  onOpen,
  onProjectSelect,
  onSubmit,
  statusMessage,
  value,
}: ComposerProps & {
  data: MobileWorkspaceView;
  onManageProjects?: () => void;
  onOpen?: (workUnitId?: string) => void;
  onProjectSelect?: (projectId: string) => void;
}) => {
  const { selectedWorkUnit } = data;
  const secondaryWorkUnits = data.workUnits
    .filter((workUnit) => workUnit.id !== selectedWorkUnit?.id)
    .slice(0, 3);
  const previewLayout = [
    "inset-x-[13px] top-0",
    "inset-x-[7px] top-[70px]",
    "inset-x-1 top-[142px]",
  ] as const;

  return (
    <DeviceFrame402>
      <ProductHeader
        avatar
        letterLogo
        onManageProjects={onManageProjects}
        profileInset
        subtitle={`${data.activeCount} active work units`}
      />
      <ProjectSwitcher
        data={data}
        onManageProjects={onManageProjects}
        onProjectSelect={onProjectSelect}
      />
      <main className="relative min-h-0 flex-1 bg-[#f7f8f5] px-5 pt-8">
        <div className="flex items-center">
          <h2 className="text-[29px] leading-9 font-semibold tracking-[-0.05em]">
            Work in motion
          </h2>
          <span className="ml-auto max-w-28 truncate rounded-full bg-white px-3 py-1.5 text-[11px] font-semibold text-[#5f5b57]">
            {data.projectName ?? data.organizationLabel}
          </span>
        </div>
        <p className="mt-1 text-[14px] leading-5 text-[#807b76]">
          Scroll vertically. Tap a card to expand it in place.
        </p>
        <div className="mt-[34px] flex text-[12px]">
          <span className="font-semibold">ACTIVE WORK</span>
          <span className="ml-auto text-[#807b76]">
            {data.totalCount} units
          </span>
        </div>
        <section className="absolute inset-x-5 top-[142px] h-[500px]">
          {secondaryWorkUnits.map((workUnit, index) => (
            <article
              className={cn(
                "absolute h-[150px] rounded-[28px] p-5",
                previewLayout[index],
                workUnitToneClass[workUnit.tone]
              )}
              key={workUnit.id}
            >
              <span
                className={cn(
                  "text-[10px] font-semibold uppercase",
                  workUnitStatusClass[workUnit.tone]
                )}
              >
                {workUnit.statusLabel}
              </span>
              <span className="float-right text-[10px] opacity-60">
                {workUnit.code}
              </span>
              <strong className="mt-4 block truncate text-[22px]">
                {workUnit.title}
              </strong>
            </article>
          ))}
          {selectedWorkUnit ? (
            <article
              className={cn(
                "absolute inset-x-px top-[218px] h-[285px] rounded-[30px] p-5",
                workUnitToneClass[selectedWorkUnit.tone]
              )}
            >
              <div className="flex items-center">
                <span className="rounded-full bg-[#d6e2ff] px-2 py-1 text-[10px] font-semibold text-[#315dc0]">
                  {selectedWorkUnit.statusLabel.toUpperCase()}
                </span>
                <span className="ml-auto text-[10px] text-[#6e83b4]">
                  {selectedWorkUnit.code}
                </span>
              </div>
              <h3 className="mt-4 truncate text-[24px] leading-[27px] font-semibold tracking-[-0.04em]">
                {selectedWorkUnit.title}
              </h3>
              <p className="mt-2 truncate text-[13px] text-[#60718e]">
                {data.latestSignal?.summary ?? selectedWorkUnit.summary}
              </p>
              <div className="mt-4 h-[7px] rounded-full bg-[#315dc0]/15">
                <div
                  className="h-full rounded-full bg-[#315dc0]"
                  style={{ width: `${selectedWorkUnit.progress}%` }}
                />
              </div>
              <div className="mt-2 flex text-[10px] font-semibold text-[#315dc0]">
                {selectedWorkUnit.progress}% COMPLETE
                <span className="ml-auto font-normal text-[#6e83b4]">
                  {selectedWorkUnit.updatedLabel}
                </span>
              </div>
              <button
                className="mt-5 flex w-full items-center border-t border-[#315dc0]/15 pt-4 text-left"
                onClick={() => onOpen?.(selectedWorkUnit.id)}
                type="button"
              >
                <span className="flex size-10 items-center justify-center rounded-[14px] bg-white text-[#315dc0]">
                  ↗
                </span>
                <span className="ml-3 min-w-0">
                  <span className="block text-[10px] font-semibold text-[#6e83b4]">
                    NEXT MILESTONE
                  </span>
                  <span className="block truncate text-[14px] font-semibold">
                    {selectedWorkUnit.nextAction}
                  </span>
                  <span className="block text-[10px] text-[#6e83b4]">
                    {data.artifactCount} artifacts · {data.activityCount} events
                  </span>
                </span>
              </button>
            </article>
          ) : (
            <EmptyWorkState
              isLoading={data.isLoading}
              onManageProjects={onManageProjects}
            />
          )}
        </section>
      </main>
      <ReferenceComposer
        deviceHomeIndicator
        hint="Use @ to reference a work unit"
        homeIndicator
        onChange={onChange}
        onSubmit={onSubmit}
        placeholder="Ask Zopu or create new work..."
        statusMessage={statusMessage}
        value={value}
      />
    </DeviceFrame402>
  );
};

const HomeExpanded = ({
  data,
  onChange,
  onManageProjects,
  onOpen,
  onProjectSelect,
  onSubmit,
  statusMessage,
  value,
}: ComposerProps & {
  data: MobileWorkspaceView;
  onManageProjects?: () => void;
  onOpen?: (workUnitId?: string) => void;
  onProjectSelect?: (projectId: string) => void;
}) => (
  <DeviceFrame402>
    <ProductHeader
      avatar
      letterLogo
      onManageProjects={onManageProjects}
      profileInset
      subtitle={`${data.activeCount} active work units`}
    />
    <ProjectSwitcher
      data={data}
      onManageProjects={onManageProjects}
      onProjectSelect={onProjectSelect}
    />
    <main className="relative min-h-0 flex-1 bg-[#f7f8f5] px-5 pt-[27px]">
      <div className="flex items-center">
        <h2 className="text-[29px] leading-9 font-semibold tracking-[-0.05em]">
          Work in motion
        </h2>
        <span className="ml-auto rounded-full bg-white px-3 py-1.5 text-[11px] font-semibold text-[#5f5b57]">
          MON 20
        </span>
      </div>
      <p className="mt-1 text-[14px] leading-5 text-[#807b76]">
        One work unit is expanded in the stack.
      </p>
      <div className="absolute inset-x-[31px] top-[97px] h-24 rounded-[28px] bg-[#f1e8ff] px-4 pt-4 text-[10px] font-semibold text-[#7137ef]">
        RESEARCHING
      </div>
      <div className="absolute inset-x-[26px] top-[117px] h-24 rounded-[28px] bg-[#fff0e8] px-4 pt-4 text-[10px] font-semibold text-[#c53c08]">
        BLOCKED
      </div>
      <div className="absolute inset-x-[17px] top-[139px]">
        <ExpandedWorkUnitContent compact data={data} />
        <button
          aria-label={`Open ${data.selectedWorkUnit?.title ?? "selected work unit"}`}
          className="absolute inset-0 rounded-[30px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#315dc0]"
          onClick={() => onOpen?.(data.selectedWorkUnit?.id)}
          type="button"
        />
      </div>
    </main>
    <ReferenceComposer
      contextLabel={
        data.selectedWorkUnit?.title.toUpperCase() ?? "PROJECT WORK"
      }
      hint="Zopu can use your project signals"
      onChange={onChange}
      onSubmit={onSubmit}
      placeholder="Ask about this work unit..."
      sendBlue
      statusMessage={statusMessage}
      value={value}
    />
  </DeviceFrame402>
);

const assistantStatusDotClass: Record<
  MobileWorkspaceView["assistant"]["statusTone"],
  string
> = {
  amber: "bg-[#e3a127]",
  green: "bg-[#18c973]",
  red: "bg-[#e04b3f]",
};

const CharacterChat = ({
  data,
  onChange,
  onCreateIssueFromSignal,
  onSubmit,
  statusMessage,
  value,
}: ComposerProps & {
  data: MobileWorkspaceView;
  onCreateIssueFromSignal?: () => void;
}) => (
  <div className="mx-auto h-[min(100dvh,858px)] w-full max-w-[390px] overflow-hidden bg-black">
    <main className="relative h-full overflow-hidden rounded-[30px] bg-white px-4 text-[#11110f]">
      <header className="absolute inset-x-4 top-8 flex items-center">
        <span className="flex size-9 items-center justify-center rounded-[13px] bg-[#c8ff00]">
          <Sparkles className="size-5" />
        </span>
        <div className="ml-3">
          <h1 className="text-[18px] leading-5 font-semibold">Zopu</h1>
          <p className="mt-0.5 flex items-center gap-2 text-[12px] text-[#55524f]">
            <span
              className={cn(
                "size-1.5 rounded-full",
                assistantStatusDotClass[data.assistant.statusTone]
              )}
            />
            {data.assistant.statusLabel}
          </p>
        </div>
        <MoreHorizontal className="ml-auto size-5" />
      </header>
      <section className="absolute inset-x-4 top-[106px] bottom-[105px] overflow-y-auto pb-6">
        {data.assistant.messages.length === 0 ? (
          <>
            <div className="w-fit rounded-full bg-[#f4f4f2] px-2.5 py-1.5 text-[10px] text-[#aaa7a3]">
              TODAY
            </div>
            <div className="mt-10 flex items-center gap-2 text-[14px] text-[#55524f]">
              <span className="flex size-6 items-center justify-center rounded-[8px] bg-[#f4f4f2]">
                <Sparkles className="size-4" />
              </span>
              <strong>Zopu</strong>
              <span className="text-[#b5b2ae]">• a fresh start</span>
            </div>
            <p className="mt-3 text-[17px] leading-5">
              Good morning. What are we making clearer today?
            </p>
            <div className="mt-4 flex gap-7 text-[12px] font-semibold text-[#55524f]">
              <button
                className="flex items-center gap-2"
                onClick={() => onChange("Summarize my latest project signals")}
                type="button"
              >
                <FileText className="size-4" />
                Summarize
              </button>
              <button
                className="flex items-center gap-2"
                onClick={() => onChange("Plan the next steps for my project")}
                type="button"
              >
                <ListChecks className="size-4" />
                Plan
              </button>
              <button
                className="flex items-center gap-2"
                onClick={() => onChange("Explore risks in my active work")}
                type="button"
              >
                ◉ Explore
              </button>
            </div>
            {data.latestSignal ? (
              <section className="mt-12 rounded-[22px] bg-[#f4f4f2] p-[14px]">
                <div className="flex items-center">
                  <span className="flex size-8 items-center justify-center rounded-[10px] bg-[#c8ff00]">
                    ↗
                  </span>
                  <div className="ml-3 min-w-0">
                    <h2 className="truncate text-[15px] leading-4 font-semibold">
                      {data.latestSignal.title}
                    </h2>
                    <p className="text-[10px] text-[#b5b2ae]">
                      Latest project signal
                    </p>
                  </div>
                  <ChevronRight className="ml-auto size-4" />
                </div>
                <p className="mt-3 text-[13px] leading-[18px]">
                  {data.latestSignal.summary}
                </p>
                <button
                  className="mt-3 h-8 rounded-[11px] bg-black px-3 text-[11px] font-semibold text-white"
                  onClick={onCreateIssueFromSignal}
                  type="button"
                >
                  Create work from signal
                </button>
              </section>
            ) : null}
          </>
        ) : (
          <div className="grid gap-5">
            {data.assistant.messages.map((message) =>
              message.role === "user" ? (
                <div
                  className="ml-auto max-w-[86%] rounded-[22px] bg-[#0c0c0b] px-4 py-3 text-[16px] leading-6 whitespace-pre-wrap text-white"
                  key={message.id}
                >
                  {message.text}
                </div>
              ) : (
                <div key={message.id}>
                  <div className="flex items-center gap-2">
                    <span className="flex size-7 items-center justify-center rounded-[9px] bg-[#c8ff00]">
                      <Sparkles className="size-4" />
                    </span>
                    <strong className="text-[14px]">Zopu</strong>
                    <span className="rounded-full bg-[#f1f1ef] px-2 py-1 text-[9px] text-[#aaa7a3]">
                      THINKING PARTNER
                    </span>
                  </div>
                  <p className="mt-3 text-[16px] leading-[21px] whitespace-pre-wrap">
                    {message.text}
                  </p>
                </div>
              )
            )}
            {data.assistant.isBusy ? (
              <p className="text-[13px] text-[#807b76]">Zopu is thinking…</p>
            ) : null}
          </div>
        )}
      </section>
      <form
        className="absolute inset-x-3 bottom-[34px] flex h-[53px] items-center rounded-[27px] bg-[#f4f4f2] p-2"
        onSubmit={onSubmit}
      >
        <button
          aria-label="Attach file"
          className="flex size-10 items-center justify-center rounded-full bg-white"
          type="button"
        >
          <Paperclip className="size-5" />
        </button>
        <input
          className="min-w-0 flex-1 bg-transparent px-2 text-[14px] outline-none placeholder:text-[#b5b2ae]"
          onChange={(event) => onChange(event.target.value)}
          placeholder="Ask anything..."
          value={value}
        />
        <button
          aria-label="Record voice message"
          className="flex size-10 items-center justify-center rounded-full bg-white"
          type="button"
        >
          <Mic className="size-5" />
        </button>
        <button
          aria-label="Send"
          className="ml-1 flex size-10 items-center justify-center rounded-full bg-black text-white"
          type="submit"
        >
          <ArrowUp className="size-5" />
        </button>
      </form>
      <p className="absolute inset-x-0 bottom-[13px] text-center text-[9px] text-[#b5b2ae]">
        {statusMessage ?? "Press Enter to send · Shift + Enter for a new line"}
      </p>
    </main>
  </div>
);

export const MobileWorkspaceScreenRenderer = ({
  composerValue,
  createIssueBody,
  createIssueTitle,
  data,
  onBack,
  onComposerChange,
  onComposerSubmit,
  onCreateBodyChange,
  onCreateIssue,
  onCreateIssueFromSignal,
  onCreateTitleChange,
  onManageProjects,
  onOpenAssistant,
  onOpenUnit,
  onProjectSelect,
  onReviewUnit,
  onStartUnit,
  onViewWork,
  pendingAction,
  statusMessage,
  variant,
}: MobileWorkspaceRendererProps) => {
  const composerProps = {
    onChange: onComposerChange,
    onSubmit: onComposerSubmit,
    placeholder: "",
    statusMessage,
    value: composerValue,
  };

  if (variant === "character-pass") {
    return (
      <CharacterChat
        {...composerProps}
        data={data}
        onCreateIssueFromSignal={onCreateIssueFromSignal}
      />
    );
  }
  if (variant === "expanded-work-unit") {
    return (
      <WorkUnitScreen
        {...composerProps}
        data={data}
        onBack={onBack}
        createIssueBody={createIssueBody}
        createIssueTitle={createIssueTitle}
        onCreateBodyChange={onCreateBodyChange}
        onCreateIssue={onCreateIssue}
        onCreateTitleChange={onCreateTitleChange}
        onManageProjects={onManageProjects}
        onProjectSelect={onProjectSelect}
        onReviewUnit={onReviewUnit}
        onStartUnit={onStartUnit}
        pendingAction={pendingAction}
      />
    );
  }
  if (variant === "home-expanded-in-place") {
    return (
      <HomeExpanded
        {...composerProps}
        data={data}
        onManageProjects={onManageProjects}
        onOpen={onOpenUnit}
        onProjectSelect={onProjectSelect}
      />
    );
  }
  if (variant === "vertical-work-stack") {
    return (
      <VerticalStack
        {...composerProps}
        data={data}
        onManageProjects={onManageProjects}
        onOpen={onOpenUnit}
        onProjectSelect={onProjectSelect}
      />
    );
  }
  if (variant === "work-units-home") {
    return (
      <WorkFeedScreen
        {...composerProps}
        data={data}
        onManageProjects={onManageProjects}
        onOpen={onOpenUnit}
        onOpenAssistant={onOpenAssistant}
        onProjectSelect={onProjectSelect}
        onReviewUnit={onReviewUnit}
        onStartUnit={onStartUnit}
        createIssueBody={createIssueBody}
        createIssueTitle={createIssueTitle}
        onCreateBodyChange={onCreateBodyChange}
        onCreateIssue={onCreateIssue}
        onCreateTitleChange={onCreateTitleChange}
        pendingAction={pendingAction}
        onViewWork={onViewWork}
      />
    );
  }
  variant satisfies never;
  return null;
};
