"use client";

import {
  ArrowUp,
  Bot,
  Check,
  ChevronDown,
  ChevronUp,
  Globe2,
  Image as ImageIcon,
  ImagePlus,
  Library,
  Paperclip,
  Plus,
  Sparkles,
  Square,
  Video,
  X
} from "lucide-react";
import { forwardRef, type ReactNode, useMemo, useRef, useState } from "react";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Switch } from "@/components/ui/switch";
import { useI18n } from "@/i18n/i18n";
import { PromptComposer, type PromptComposerHandle, type UploadedReferenceImage, type CanvasAnnotation, type AnnotationPreviewRequest } from "@/ui/components/PromptComposer";

export type ComposerMode = "agent" | "image";
export type ComposerImageQuality = "auto" | "high" | "medium" | "low";
export type ComposerImageRatio = "1:1" | "3:2" | "2:3" | "4:3" | "3:4" | "9:16" | "1:1-2k" | "16:9-2k" | "9:16-2k" | "16:9-4k" | "9:16-4k" | "auto";

export type ComposerImageSettings = {
  quality: ComposerImageQuality;
  ratio: ComposerImageRatio;
  width: number;
  height: number;
  count: number;
};

export type CanvasComposerModel = {
  id: string;
  label: string;
  description?: string;
  duration?: string;
  credits: number;
};

export type CanvasAgentComposerVariant = "panel" | "floating";

export type CanvasAgentComposerProps = {
  text: string;
  mode: ComposerMode;
  models: CanvasComposerModel[];
  selectedModel: CanvasComposerModel;
  settings: ComposerImageSettings;
  webSearchEnabled: boolean;
  generating: boolean;
  variant?: CanvasAgentComposerVariant;
  references?: UploadedReferenceImage[];
  annotations?: CanvasAnnotation[];
  previewSlot?: ReactNode;
  onTextChange: (text: string) => void;
  onModeChange: (mode: ComposerMode) => void;
  onSettingsChange: (settings: ComposerImageSettings) => void;
  onModelChange: (modelId: string) => void;
  onWebSearchChange: (enabled: boolean) => void;
  onUploadFile: (file: File | null) => void | Promise<void>;
  onReferencesChange: (references: UploadedReferenceImage[]) => void;
  onReferenceRemoved: (reference: UploadedReferenceImage) => void;
  onAnnotationsChange?: (annotations: CanvasAnnotation[]) => void;
  onAnnotationPreviewChange?: (preview: AnnotationPreviewRequest | null) => void;
  onSubmit: () => void;
  onStop?: () => void;
};

const qualityOptions: Array<{ id: ComposerImageQuality; labelKey: string }> = [
  { id: "auto", labelKey: "qualityAuto" },
  { id: "high", labelKey: "qualityHigh" },
  { id: "medium", labelKey: "qualityMedium" },
  { id: "low", labelKey: "qualityLow" }
];

export const composerRatioOptions: Array<{ id: ComposerImageRatio; label: string; width: number; height: number }> = [
  { id: "1:1", label: "1:1", width: 1024, height: 1024 },
  { id: "3:2", label: "3:2", width: 1536, height: 1024 },
  { id: "2:3", label: "2:3", width: 1024, height: 1536 },
  { id: "4:3", label: "4:3", width: 1365, height: 1024 },
  { id: "3:4", label: "3:4", width: 1024, height: 1365 },
  { id: "9:16", label: "9:16", width: 1024, height: 1820 },
  { id: "1:1-2k", label: "1:1(2k)", width: 2048, height: 2048 },
  { id: "16:9-2k", label: "16:9(2k)", width: 2048, height: 1152 },
  { id: "9:16-2k", label: "9:16(2k)", width: 1152, height: 2048 },
  { id: "16:9-4k", label: "16:9(4k)", width: 4096, height: 2304 },
  { id: "9:16-4k", label: "9:16(4k)", width: 2304, height: 4096 },
  { id: "auto", label: "auto", width: 1024, height: 1024 }
];

export const defaultComposerImageSettings: ComposerImageSettings = {
  quality: "auto",
  ratio: "1:1",
  width: 1024,
  height: 1024,
  count: 1
};

export function composerImageSize(settings: ComposerImageSettings) {
  return `${Math.max(1, Math.round(settings.width))}x${Math.max(1, Math.round(settings.height))}`;
}

export function composerSettingsSummary(settings: ComposerImageSettings) {
  const ratioLabel = composerRatioOptions.find((option) => option.id === settings.ratio)?.label ?? settings.ratio;
  return `${qualityLabel(settings.quality)} · ${ratioLabel} · ${settings.count} img`;
}

function qualityLabel(quality: ComposerImageQuality) {
  if (quality === "high") return "高";
  if (quality === "medium") return "中";
  if (quality === "low") return "低";
  return "自动";
}

function hasComposerPromptText(value: string) {
  return value.replace(/\u00a0/g, " ").trim().length > 0;
}

export const CanvasAgentComposer = forwardRef<PromptComposerHandle, CanvasAgentComposerProps>(function CanvasAgentComposer(
  {
    text,
    mode,
    models,
    selectedModel,
    settings,
    webSearchEnabled,
    generating,
    variant = "panel",
    references,
    annotations,
    previewSlot,
    onTextChange,
    onModeChange,
    onSettingsChange,
    onModelChange,
    onWebSearchChange,
    onUploadFile,
    onReferencesChange,
    onReferenceRemoved,
    onAnnotationsChange,
    onAnnotationPreviewChange,
    onSubmit,
    onStop
  },
  ref
) {
  const { t } = useI18n();
  const fileInputRef = useRef<HTMLInputElement | null>(null);
  const [assetMenuOpen, setAssetMenuOpen] = useState(false);
  const [modeMenuOpen, setModeMenuOpen] = useState(false);
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [modelOpen, setModelOpen] = useState(false);
  const [upgradeVisible, setUpgradeVisible] = useState(true);
  const sendCost = useMemo(() => Math.max(1, selectedModel.credits * Math.max(1, settings.count)), [selectedModel.credits, settings.count]);
  const modeLabel = mode === "image" ? t("imageMode") : t("agentShort");
  const ModeIcon = mode === "image" ? ImagePlus : Bot;
  const canSubmit = hasComposerPromptText(text);

  const patchSettings = (patch: Partial<ComposerImageSettings>) => {
    onSettingsChange({ ...settings, ...patch });
  };

  const selectRatio = (ratio: ComposerImageRatio) => {
    const nextRatio = composerRatioOptions.find((option) => option.id === ratio) ?? composerRatioOptions[0];
    patchSettings({ ratio, width: nextRatio.width, height: nextRatio.height });
  };

  const composerCard = (
    <div id={variant === "panel" ? "agent-chat-footer" : undefined} className={`assistant-composer ${mode === "image" ? "image-mode" : "agent-mode-active"} ${variant === "floating" ? "floating-composer" : ""}`}>
      {mode === "image"}
      <PromptComposer
        ref={ref}
        text={text}
        placeholder={t("canvasPromptPlaceholder")}
        ariaLabel={t("canvasPromptPlaceholder")}
        className="compact"
        references={references}
        annotations={annotations}
        removeLabel={t("removeReference")}
        onTextChange={onTextChange}
        onReferencesChange={onReferencesChange}
        onReferenceRemoved={onReferenceRemoved}
        onAnnotationsChange={onAnnotationsChange}
        onAnnotationPreviewChange={onAnnotationPreviewChange}
        onPasteFile={onUploadFile}
        onSubmit={onSubmit}
      />
      {previewSlot}
      <div className="assistant-composer-toolbar">
        <input
          ref={fileInputRef}
          type="file"
          accept="image/*"
          hidden
          onChange={(event) => {
            const file = event.target.files?.[0] ?? null;
            event.currentTarget.value = "";
            void onUploadFile(file);
            setAssetMenuOpen(false);
          }}
        />
        <DropdownMenu open={assetMenuOpen} onOpenChange={setAssetMenuOpen}>
          <DropdownMenuTrigger asChild>
            <button className="composer-icon-button plus-button" type="button" aria-label={t("addAsset")}>
              <Plus size={21} />
            </button>
          </DropdownMenuTrigger>
          <DropdownMenuContent className="composer-menu-popover composer-asset-popover" align="start" side="top" sideOffset={10}>
            <DropdownMenuItem onSelect={() => fileInputRef.current?.click()}>
              <Paperclip size={18} />
              <span>{t("uploadFile")}</span>
            </DropdownMenuItem>
            <DropdownMenuItem disabled>
              <Library size={18} />
              <span>{t("chooseFromLibrary")}</span>
            </DropdownMenuItem>
            <DropdownMenuItem
              className="composer-switch-row"
              onSelect={(event) => {
                event.preventDefault();
                onWebSearchChange(!webSearchEnabled);
              }}
            >
              <Globe2 size={18} />
              <span>{t("webSearch")}</span>
              <Switch className="composer-web-switch" checked={webSearchEnabled} onClick={(event) => event.stopPropagation()} onCheckedChange={onWebSearchChange} />
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>

        <DropdownMenu open={modeMenuOpen} onOpenChange={setModeMenuOpen}>
          <DropdownMenuTrigger asChild>
            <button className={`composer-mode-button ${modeMenuOpen ? "open" : ""}`} type="button" aria-label={t("agentMode")}>
              <ModeIcon size={18} />
              <span>{modeLabel}</span>
              {modeMenuOpen ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
            </button>
          </DropdownMenuTrigger>
          <DropdownMenuContent className="composer-menu-popover composer-mode-popover" align="start" side="top" sideOffset={10}>
            <DropdownMenuItem
              onSelect={() => {
                onModeChange("agent");
                setModeMenuOpen(false);
              }}
            >
              <Bot size={18} />
              <span>{t("agentShort")}</span>
              {mode === "agent" && <Check size={16} />}
            </DropdownMenuItem>
            <DropdownMenuItem
              onSelect={() => {
                onModeChange("image");
                setModeMenuOpen(false);
              }}
            >
              <ImagePlus size={18} />
              <span>{t("imageMode")}</span>
              {mode === "image" && <Check size={16} />}
            </DropdownMenuItem>
            <DropdownMenuItem disabled>
              <Video size={18} />
              <span>{t("modelVideoTab")}</span>
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>

        {mode === "image" && (
          <Popover open={settingsOpen} onOpenChange={setSettingsOpen}>
            <PopoverTrigger asChild>
              <button className="composer-settings-chip" type="button" aria-label={t("imageSettings")}>
                {composerSettingsSummary(settings)}
                {settingsOpen ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
              </button>
            </PopoverTrigger>
            <PopoverContent className="composer-settings-popover" align="end" sideOffset={12}>
              <ComposerSettingsPanel settings={settings} onPatch={patchSettings} onSelectRatio={selectRatio} />
            </PopoverContent>
          </Popover>
        )}

        <div className="composer-spacer" />
        <DropdownMenu open={modelOpen} onOpenChange={setModelOpen}>
          <DropdownMenuTrigger asChild>
            <button className="composer-model-button" type="button" aria-label={t("modelSelection")}>
              <Sparkles size={18} />
            </button>
          </DropdownMenuTrigger>
          <DropdownMenuContent className="composer-model-popover" align="end" side="top" sideOffset={12}>
            {models.map((model) => (
              <DropdownMenuItem
                key={model.id}
                onSelect={() => {
                  onModelChange(model.id);
                  setModelOpen(false);
                }}
              >
                <Sparkles size={17} />
                <span>{model.label}</span>
                <small>⚡{model.credits}</small>
                {model.id === selectedModel.id && <Check size={16} />}
              </DropdownMenuItem>
            ))}
          </DropdownMenuContent>
        </DropdownMenu>
        <button
          className={`send-button small ${generating ? "is-stopping" : ""} ${mode === "image" ? "with-cost" : ""}`}
          type="button"
          onClick={generating ? onStop : onSubmit}
          disabled={!generating && !canSubmit}
          aria-label={generating ? t("stopGeneration") : t("send")}
        >
          {generating ? (
            <Square size={15} fill="currentColor" />
          ) : mode === "image" ? (
            <span>⚡{sendCost}</span>
          ) : (
            <ArrowUp size={21} />
          )}
        </button>
      </div>
    </div>
  );

  if (variant === "floating") return composerCard;

  return (
    <div className={`assistant-composer-stack ${upgradeVisible ? "has-upgrade" : ""}`}>
      {upgradeVisible && (
        <div id="agent-chat-banner" className="composer-upgrade">
          <div className="composer-upgrade-row">
            <span className="composer-upgrade-icon" aria-hidden="true">
              <Sparkles size={16} />
            </span>
            <span className="composer-upgrade-copy">{t("unlockModels")}</span>
            <button type="button" aria-label={t("close")} onClick={() => setUpgradeVisible(false)}>
              <X size={16} />
            </button>
          </div>
        </div>
      )}
      {composerCard}
    </div>
  );
});

export function ComposerSettingsPanel({
  settings,
  onPatch,
  onSelectRatio
}: {
  settings: ComposerImageSettings;
  onPatch: (patch: Partial<ComposerImageSettings>) => void;
  onSelectRatio: (ratio: ComposerImageRatio) => void;
}) {
  const { t } = useI18n();

  return (
    <div className="composer-settings-panel">
      <section>
        <h4>{t("quality")}</h4>
        <div className="composer-quality-control">
          {qualityOptions.map((option) => (
            <button key={option.id} type="button" className={settings.quality === option.id ? "selected" : ""} onClick={() => onPatch({ quality: option.id })}>
              {t(option.labelKey)}
            </button>
          ))}
        </div>
      </section>
      <section>
        <h4>{t("imageSizeLabel")}</h4>
        <div className="composer-dimensions">
          <label>
            <span>W</span>
            <input value={settings.width} inputMode="numeric" onChange={(event) => onPatch({ width: Number(event.target.value) || 1024, ratio: "auto" })} />
          </label>
          <i aria-hidden="true">⌁</i>
          <label>
            <span>H</span>
            <input value={settings.height} inputMode="numeric" onChange={(event) => onPatch({ height: Number(event.target.value) || 1024, ratio: "auto" })} />
          </label>
        </div>
        <div className="composer-ratio-grid">
          {composerRatioOptions.map((option) => (
            <button key={option.id} type="button" className={settings.ratio === option.id ? "selected" : ""} onClick={() => onSelectRatio(option.id)}>
              <RatioGlyph ratio={option.id} />
              <span>{option.label}</span>
            </button>
          ))}
        </div>
      </section>
      <section>
        <h4>Image</h4>
        <div className="composer-count-grid">
          {Array.from({ length: 10 }, (_, index) => index + 1).map((count) => (
            <button key={count} type="button" className={settings.count === count ? "selected" : ""} onClick={() => onPatch({ count })}>
              {count} img
            </button>
          ))}
        </div>
      </section>
    </div>
  );
}

function RatioGlyph({ ratio }: { ratio: ComposerImageRatio }) {
  const portrait = ratio.startsWith("2:3") || ratio.startsWith("3:4") || ratio.startsWith("9:16");
  const wide = ratio.startsWith("3:2") || ratio.startsWith("4:3") || ratio.startsWith("16:9");
  return <i className={`ratio-glyph ${portrait ? "portrait" : wide ? "wide" : ""}`} aria-hidden="true" />;
}
