import { useSwipeCard } from "@code/ui/hooks/use-swipe-card";
import { cn } from "@code/ui/lib/utils";
import {
  ArrowUp,
  Check,
  ChevronRight,
  MoreHorizontal,
  Plus,
  RotateCcw,
} from "lucide-react";
import type { FormEvent, MouseEvent } from "react";

import { MobileProjectManagerPanel } from "./mobile-project-manager-panel";
import { MobileProjectSelect } from "./mobile-project-select";
import { MobileSettingsPanel } from "./mobile-settings-panel";
import type {
  MobileProjectView,
  MobileWorkspaceView,
  MobileWorkUnitTone,
  MobileWorkUnitView,
} from "./models";

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

const statusClass: Readonly<Record<MobileWorkUnitTone, string>> = {
  blue: "bg-[#d5e1ff] text-[#315dc0]",
  green: "bg-[#d8f1e4] text-[#238050]",
  orange: "bg-[#ffe0d0] text-[#c53c08]",
  purple: "bg-[#e6d6ff] text-[#7137ef]",
};

const dateLabel = new Intl.DateTimeFormat("en", {
  day: "numeric",
  weekday: "short",
})
  .format(new Date())
  .toUpperCase();

interface WorkStackHeaderProps {
  readonly activeCount: number;
  readonly onAddProject: () => void;
  readonly onOpenSettings?: () => void;
  readonly onProjectSelect: (projectId: string) => void;
  readonly projects: readonly MobileProjectView[];
  readonly selectedProjectId?: string;
  readonly userInitials: string;
}

const WorkStackHeader = ({
  activeCount,
  onAddProject,
  onOpenSettings,
  onProjectSelect,
  projects,
  selectedProjectId,
  userInitials,
}: WorkStackHeaderProps) => (
  <header className="flex h-[96px] 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">
      Z
    </div>
    <div className="ml-3">
      <h1 className="text-[20px] leading-6 font-semibold tracking-[-0.03em] text-[#0b0b0a]">
        Zopu
      </h1>
      <MobileProjectSelect
        activeCount={activeCount}
        onAddProject={onAddProject}
        onProjectSelect={onProjectSelect}
        projects={projects}
        selectedProjectId={selectedProjectId}
      />
    </div>
    <button
      aria-label="Open settings"
      className="ml-auto flex size-10 items-center justify-center rounded-full bg-[#f2f3ef] text-black"
      onClick={onOpenSettings}
      type="button"
    >
      <MoreHorizontal className="size-5" />
    </button>
    <button
      aria-label="Open profile"
      className="ml-2 flex size-10 items-center justify-center rounded-full bg-[#0b0b0a] text-[13px] font-semibold text-white"
      onClick={onOpenSettings}
      type="button"
    >
      {userInitials}
    </button>
  </header>
);

interface SwipeWorkCardProps {
  readonly data: MobileWorkspaceView;
  readonly onChecked: (workUnitId: string) => void;
  readonly onOpen: (workUnitId: string) => void;
  readonly onSendBack: (workUnitId: string) => void;
  readonly workUnit: MobileWorkUnitView;
}

const SwipeWorkCard = ({
  data,
  onChecked,
  onOpen,
  onSendBack,
  workUnit,
}: SwipeWorkCardProps) => {
  const swipeCard = useSwipeCard({
    itemKey: workUnit.id,
    onSwipe: (direction) => {
      if (direction === "right") {
        onChecked(workUnit.id);
        return;
      }
      onSendBack(workUnit.id);
    },
  });
  const {
    backLabelRef,
    cardRef,
    checkedLabelRef,
    dragged,
    pointerHandlers,
    swipe,
    transitionHandlers,
  } = swipeCard;

  const handleOpen = (event: MouseEvent<HTMLButtonElement>) => {
    if (dragged()) {
      event.preventDefault();
      return;
    }
    onOpen(workUnit.id);
  };

  return (
    <div className="relative h-full touch-pan-y select-none">
      <span
        className="pointer-events-none absolute top-5 left-5 z-10 rounded-full bg-black px-3 py-1.5 text-[11px] font-semibold text-white opacity-0"
        ref={backLabelRef}
      >
        SEND TO BACK
      </span>
      <span
        className="pointer-events-none absolute top-5 right-5 z-10 rounded-full bg-[#c8ff00] px-3 py-1.5 text-[11px] font-semibold text-black opacity-0"
        ref={checkedLabelRef}
      >
        CHECKED
      </span>
      <article
        aria-label={`${workUnit.title}. Swipe right to check, left to send to back.`}
        className={cn(
          "relative h-full overflow-hidden rounded-[30px] p-5 shadow-[0_12px_38px_rgba(43,61,107,0.08)] will-change-transform",
          toneClass[workUnit.tone]
        )}
        ref={cardRef}
        {...transitionHandlers}
      >
        <div className="flex items-center">
          <span
            className={cn(
              "rounded-full px-2.5 py-1.5 text-[10px] font-semibold",
              statusClass[workUnit.tone]
            )}
          >
            {workUnit.statusLabel.toUpperCase()}
          </span>
          <span className="ml-2 text-[10px] opacity-55">{workUnit.code}</span>
          <MoreHorizontal className="ml-auto size-5 opacity-75" />
        </div>
        <button
          className="mt-5 block w-full text-left focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-[#315dc0]"
          onClick={handleOpen}
          onKeyDown={(event) => {
            if (event.key === "ArrowRight") {
              swipe("right");
            }
            if (event.key === "ArrowLeft") {
              swipe("left");
            }
          }}
          type="button"
          {...pointerHandlers}
        >
          <h3 className="line-clamp-2 text-[27px] leading-[30px] font-semibold tracking-[-0.045em]">
            {workUnit.title}
          </h3>
          <p className="mt-2 truncate text-[13px] opacity-60">
            Updated {workUnit.updatedLabel}
          </p>
          <div className="mt-3 border-t border-current/10 pt-3">
            <p className="text-[10px] font-semibold opacity-60">
              CURRENT STATE
            </p>
            <p className="mt-1 line-clamp-2 text-[14px] leading-5 opacity-80">
              {workUnit.summary}
            </p>
          </div>
          <div className="mt-5 h-[7px] rounded-full bg-current/10">
            <div
              className="h-full rounded-full bg-current"
              style={{ width: `${workUnit.progress}%` }}
            />
          </div>
          <div className="mt-2 flex text-[10px] font-semibold">
            <span>{workUnit.progress}% COMPLETE</span>
            <span className="ml-auto font-normal opacity-60">
              {workUnit.canRetry ? "Needs attention" : "On track"}
            </span>
          </div>
        </button>
        <div className="absolute inset-x-5 bottom-5 flex items-center border-t border-current/10 pt-4">
          <button
            aria-label={`Mark ${workUnit.title} checked`}
            className="flex size-10 shrink-0 items-center justify-center rounded-[14px] bg-white text-[#315dc0] active:scale-[0.98]"
            onClick={() => swipe("right")}
            type="button"
          >
            <Check className="size-5" />
          </button>
          <div className="ml-3 min-w-0 flex-1">
            <p className="text-[10px] font-semibold opacity-55">NEXT ACTION</p>
            <p className="truncate text-[14px] font-semibold">
              {workUnit.nextAction}
            </p>
            <p className="text-[10px] opacity-55">
              {data.artifactCount} artifacts available
            </p>
          </div>
          <button
            className="ml-3 flex h-12 shrink-0 items-center gap-1 rounded-[17px] bg-[#c8ff00] px-4 text-[12px] font-semibold text-black active:scale-[0.98]"
            onClick={() => onOpen(workUnit.id)}
            type="button"
          >
            Open unit
            <ChevronRight className="size-4" />
          </button>
        </div>
      </article>
    </div>
  );
};

interface WorkStackComposerProps {
  readonly onChange: (value: string) => void;
  readonly onSubmit: (event: FormEvent<HTMLFormElement>) => void;
  readonly statusMessage?: string;
  readonly value: string;
}

const WorkStackComposer = ({
  onChange,
  onSubmit,
  statusMessage,
  value,
}: WorkStackComposerProps) => (
  <footer className="relative h-[112px] shrink-0 border-t border-[#eff0ec] bg-white px-[14px] pt-[14px]">
    <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">Ask Zopu or create new work</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="Ask Zopu or create new work..."
          rows={1}
          value={value}
        />
        <span className="block truncate text-[10px] leading-4 text-[#c0bcb7]">
          {statusMessage ?? "Use @ to reference a work unit"}
        </span>
      </label>
      <button
        aria-label="Send"
        className="ml-2 flex size-11 shrink-0 items-center justify-center rounded-full bg-black text-white active:scale-[0.98]"
        type="submit"
      >
        <ArrowUp className="size-5" strokeWidth={2.2} />
      </button>
    </form>
    <span className="absolute bottom-[10px] left-1/2 h-[5px] w-[120px] -translate-x-1/2 rounded-full bg-black" />
  </footer>
);

export interface MobileWorkStackScreenProps {
  readonly checkedCount: number;
  readonly composerValue: string;
  readonly data: MobileWorkspaceView;
  readonly modelId: string;
  readonly modelLabel: string;
  readonly onAddProject: () => void;
  readonly onComposerChange: (value: string) => void;
  readonly onComposerSubmit: (event: FormEvent<HTMLFormElement>) => void;
  readonly onOpenUnit: (workUnitId: string) => void;
  readonly onProjectSelect: (projectId: string) => void;
  readonly onProjectManagerClose: () => void;
  readonly onRepositoryChange: (value: string) => void;
  readonly onRepositoryConnect: (event: FormEvent<HTMLFormElement>) => void;
  readonly onRestoreChecked: () => void;
  readonly onSettingsClose: () => void;
  readonly onSettingsOpen: () => void;
  readonly onSignOut?: () => void;
  readonly onWorkUnitChecked: (workUnitId: string) => void;
  readonly onWorkUnitSentBack: (workUnitId: string) => void;
  readonly pendingAction?: string | null;
  readonly projectManagerOpen: boolean;
  readonly repositoryValue: string;
  readonly settingsOpen: boolean;
  readonly statusMessage?: string;
  readonly userEmail?: string;
  readonly userInitials: string;
  readonly userName?: string;
  readonly workUnits: readonly MobileWorkUnitView[];
}

export const MobileWorkStackScreen = ({
  checkedCount,
  composerValue,
  data,
  modelId,
  modelLabel,
  onAddProject,
  onComposerChange,
  onComposerSubmit,
  onOpenUnit,
  onProjectManagerClose,
  onProjectSelect,
  onRepositoryChange,
  onRepositoryConnect,
  onRestoreChecked,
  onSettingsClose,
  onSettingsOpen,
  onSignOut,
  onWorkUnitChecked,
  onWorkUnitSentBack,
  pendingAction,
  projectManagerOpen,
  repositoryValue,
  settingsOpen,
  statusMessage,
  userEmail,
  userInitials,
  userName,
  workUnits,
}: MobileWorkStackScreenProps) => {
  const [currentWorkUnit, ...queuedWorkUnits] = workUnits;
  const previewWorkUnits = queuedWorkUnits.slice(0, 2).toReversed();
  const attentionLabel =
    data.needsAttentionCount === 1
      ? "1 item needs attention."
      : `${data.needsAttentionCount} items need attention.`;

  return (
    <div className="relative mx-auto flex h-[100dvh] max-h-[858px] min-h-[700px] w-full max-w-[390px] flex-col overflow-hidden bg-white text-[#0b0b0a]">
      <WorkStackHeader
        activeCount={data.activeCount}
        onAddProject={onAddProject}
        onOpenSettings={onSettingsOpen}
        onProjectSelect={onProjectSelect}
        projects={data.projects}
        selectedProjectId={data.selectedProjectId}
        userInitials={userInitials}
      />
      <main className="relative min-h-0 flex-1 overflow-hidden bg-[#f7f8f5] px-5 pt-[26px]">
        <div className="flex items-center">
          <h2 className="text-[31px] leading-9 font-semibold tracking-[-0.055em]">
            Daily focus
          </h2>
          <span className="ml-auto rounded-full bg-white px-3 py-1.5 text-[11px] font-semibold text-[#5f5b57]">
            {dateLabel}
          </span>
        </div>
        <p className="mt-1 text-[14px] leading-5 text-[#807b76]">
          {data.needsAttentionCount > 0
            ? `One priority is moving. ${attentionLabel}`
            : "Your active work is moving."}
        </p>
        <section
          aria-label="Active work stack"
          className="absolute inset-x-5 top-[154px] bottom-11"
        >
          {previewWorkUnits.map((workUnit, reverseIndex) => {
            const depth = previewWorkUnits.length - reverseIndex;
            return (
              <button
                aria-label={`Open ${workUnit.title}`}
                className={cn(
                  "absolute inset-x-5 h-[112px] rounded-[28px] px-4 pt-4 text-left focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-black",
                  toneClass[workUnit.tone]
                )}
                key={workUnit.id}
                onClick={() => onOpenUnit(workUnit.id)}
                style={{
                  top: `${(depth - 1) * 36}px`,
                  transform: `scale(${1 - depth * 0.025})`,
                }}
                type="button"
              >
                <span
                  className={cn(
                    "rounded-full px-2.5 py-1.5 text-[10px] font-semibold",
                    statusClass[workUnit.tone]
                  )}
                >
                  {workUnit.statusLabel.toUpperCase()}
                </span>
                <span className="ml-2 text-[10px] opacity-55">
                  {workUnit.code}
                </span>
              </button>
            );
          })}
          {currentWorkUnit ? (
            <div
              className="absolute inset-x-0 bottom-0 h-[calc(100%-58px)]"
              key={currentWorkUnit.id}
            >
              <SwipeWorkCard
                data={data}
                onChecked={onWorkUnitChecked}
                onOpen={onOpenUnit}
                onSendBack={onWorkUnitSentBack}
                workUnit={currentWorkUnit}
              />
            </div>
          ) : (
            <div className="absolute inset-x-0 top-16 rounded-[30px] bg-white px-6 py-12 text-center">
              <Check className="mx-auto size-8 text-[#64ad1f]" />
              <h3 className="mt-3 text-[20px] font-semibold">
                Daily focus cleared
              </h3>
              <p className="mt-1 text-[13px] text-[#807b76]">
                {checkedCount} work units checked for now.
              </p>
              <button
                className="mt-5 inline-flex h-10 items-center gap-2 rounded-[14px] bg-black px-4 text-[12px] font-semibold text-white"
                onClick={onRestoreChecked}
                type="button"
              >
                <RotateCcw className="size-4" />
                Restore stack
              </button>
            </div>
          )}
        </section>
        {workUnits.length > 0 ? (
          <div className="absolute inset-x-0 bottom-4 flex justify-center gap-2">
            {workUnits.slice(0, 4).map((workUnit, index) => (
              <span
                className={cn(
                  "h-1.5 rounded-full bg-[#d7d6d4]",
                  index === 0 ? "w-6 bg-black" : "w-1.5"
                )}
                key={workUnit.id}
              />
            ))}
          </div>
        ) : null}
      </main>
      <WorkStackComposer
        onChange={onComposerChange}
        onSubmit={onComposerSubmit}
        statusMessage={statusMessage}
        value={composerValue}
      />
      {projectManagerOpen ? (
        <MobileProjectManagerPanel
          data={data}
          onClose={onProjectManagerClose}
          onProjectSelect={onProjectSelect}
          onRepositoryChange={onRepositoryChange}
          onRepositoryConnect={onRepositoryConnect}
          pendingAction={pendingAction}
          repositoryValue={repositoryValue}
          statusMessage={statusMessage}
        />
      ) : null}
      {settingsOpen ? (
        <MobileSettingsPanel
          modelId={modelId}
          modelLabel={modelLabel}
          onClose={onSettingsClose}
          onSignOut={onSignOut}
          userEmail={userEmail}
          userName={userName}
        />
      ) : null}
    </div>
  );
};
