"use client";

import { useCallback, useMemo, useState } from "react";
import {
  DEFAULT_MULTI_ANGLE_SETTINGS,
  MULTI_ANGLE_PRESET_SETTINGS,
  MultiAngleEditor,
  type MultiAnglePresetId,
  type MultiAngleSettings,
} from "@/components/MultiAngleEditor";
import { useI18n } from "@/i18n";
import { useModelStore } from "@/store/modelStore";
import { useWorkflowStore } from "@/store/workflowStore";
import type { GenerateResponse, SelectedModel, WorkflowNode } from "@/types";
import { buildGenerateHeaders } from "@/store/utils/buildApiHeaders";
import { executePopiartTask } from "@/store/execution/popiartTaskClient";
import { createDerivedImageNode } from "@/utils/derivedImageNodes";
import { toSelectedModel } from "@/utils/selectedModel";

interface NodeMultiAnglePanelProps {
  node: WorkflowNode;
  imageSource: string;
  onClose: () => void;
}

type GeneratedImageResult = {
  image: string;
  previewImage?: string;
};

function normalizeGeneratedImage(value: unknown): GeneratedImageResult | null {
  if (typeof value === "string" && value.length > 0) {
    return { image: value };
  }
  if (!value || typeof value !== "object") return null;

  const record = value as { url?: unknown; previewImg?: unknown };
  if (typeof record.url !== "string" || record.url.length === 0) return null;

  return {
    image: record.url,
    previewImage: typeof record.previewImg === "string" ? record.previewImg : undefined,
  };
}

function readFirstGeneratedImage(result: GenerateResponse): GeneratedImageResult | null {
  if (Array.isArray(result.images) && result.images.length > 0) {
    return normalizeGeneratedImage(result.images[0]);
  }
  return normalizeGeneratedImage(result.image);
}

export function NodeMultiAnglePanel({ node, imageSource, onClose }: NodeMultiAnglePanelProps) {
  const { t } = useI18n();
  const addNode = useWorkflowStore((state) => state.addNode);
  const onConnect = useWorkflowStore((state) => state.onConnect);
  const providerSettings = useWorkflowStore((state) => state.providerSettings);
  const selectSingleNode = useWorkflowStore((state) => state.selectSingleNode);
  const multiAngleModel = useModelStore((state) => state.byKind.multiAngle[0] ?? null);
  const [settings, setSettings] = useState<MultiAngleSettings>({ ...DEFAULT_MULTI_ANGLE_SETTINGS });
  const [isGenerating, setIsGenerating] = useState(false);
  const selectedModel = useMemo(
    () => multiAngleModel ? toSelectedModel(multiAngleModel) : null,
    [multiAngleModel]
  );
  const canGenerate = Boolean(selectedModel) && !isGenerating;

  const updateSettings = useCallback((patch: Partial<MultiAngleSettings>) => {
    setSettings((current) => ({
      ...current,
      ...patch,
      preset: patch.preset ?? "custom",
    }));
  }, []);

  const selectPreset = useCallback((preset: MultiAnglePresetId) => {
    setSettings({ ...MULTI_ANGLE_PRESET_SETTINGS[preset] });
  }, []);

  const togglePrompt = useCallback((enabled: boolean) => {
    setSettings((current) => ({
      ...current,
      includePrompt: enabled,
    }));
  }, []);

  const resetSettings = useCallback(() => {
    setSettings((current) => ({
      ...DEFAULT_MULTI_ANGLE_SETTINGS,
      includePrompt: current.includePrompt,
      promptText: current.promptText,
    }));
  }, []);

  const handleGenerate = useCallback(async () => {
    if (!selectedModel || isGenerating) return;
    setIsGenerating(true);
    try {
      const currentWidth = typeof node.width === "number"
        ? node.width
        : typeof node.style?.width === "number"
          ? node.style.width
          : 300;
      const result = await executePopiartTask(
        {
          images: [imageSource],
          prompt: "multi-angle image generation",
          selectedModel,
          parameters: {
            batchSize: 1,
            horizontal_angle: settings.horizontal,
            vertical_angle: settings.vertical,
            zoom: settings.zoom,
          },
          mediaType: "image",
        },
        {
          headers: buildGenerateHeaders("popiserver", providerSettings),
        }
      );
      const generatedImage = readFirstGeneratedImage(result);
      if (!generatedImage) {
        throw new Error(result.error || "Generation failed");
      }

      createDerivedImageNode({
        sourceNodeId: node.id,
        position: {
          x: node.position.x + currentWidth + 220,
          y: node.position.y,
        },
        image: generatedImage.image,
        previewImage: generatedImage.previewImage,
        filename: `multi-angle-${Date.now()}.png`,
        dimensions: null,
        label: t("imageInput.multiAngle"),
        operation: "multiAngle",
        addNode,
        onConnect,
        selectSingleNode,
      });
      onClose();
    } finally {
      setIsGenerating(false);
    }
  }, [
    addNode,
    imageSource,
    isGenerating,
    node,
    onClose,
    onConnect,
    providerSettings,
    selectSingleNode,
    selectedModel,
    settings,
    t,
  ]);

  return (
    <section
      data-testid="node-inline-multi-angle-panel"
      data-composer-popup-root="true"
      className="nodrag nopan nowheel pointer-events-auto flex h-[340px] w-[600px] flex-col overflow-hidden rounded-xl border border-[var(--border-subtle)] bg-[var(--surface-2)] text-[var(--text-primary)] shadow-[var(--shadow-panel)] backdrop-blur"
      onPointerDown={(event) => event.stopPropagation()}
    >
      <div className="min-h-0 flex-1 overflow-hidden">
        <MultiAngleEditor
          previewImage={imageSource}
          settings={settings}
          onChange={updateSettings}
          onSelectPreset={selectPreset}
          onTogglePrompt={togglePrompt}
          onReset={resetSettings}
          compact
          hidePromptControl
          actions={
            <>
              <button
                type="button"
                onClick={onClose}
                className="rounded-lg border border-[var(--border-subtle)] bg-[var(--surface-2)] px-4 py-2 text-sm text-[var(--text-secondary)] transition-colors hover:border-[var(--border-strong)] hover:bg-[var(--surface-hover)] hover:text-[var(--text-primary)]"
              >
                {t("common.cancel")}
              </button>
              <button
                type="button"
                aria-label={t("multiAngle.generate")}
                disabled={!canGenerate}
                onClick={() => void handleGenerate()}
                className="rounded-lg bg-[var(--accent)] px-4 py-2 text-sm font-medium text-[var(--text-on-overlay)] transition-colors hover:bg-[var(--accent-hover)] disabled:cursor-not-allowed disabled:bg-[var(--surface-active)] disabled:text-[var(--text-disabled)]"
              >
                {t("multiAngle.generate")}
              </button>
            </>
          }
        />
      </div>
    </section>
  );
}
