'use client';

import { useState } from 'react';
import Link from 'next/link';
import { Clock, Image, AlertCircle, Sparkles, FileText, Save, ChevronDown, ChevronUp, Code } from 'lucide-react';
import { Button } from '@/components/ui/Button';
import type { PlanoConPrompt, ReferenceAsset, PromptComposition } from '@/types/project';

interface PlanoAssetCardProps {
  plano: PlanoConPrompt;
  index: number;
  slug: string;
  capNumero: string;
  fondoImagenUrl?: string;
  onGeneratePrompt: (planoId: string) => Promise<void>;
  onGenerateImage: (planoId: string) => Promise<void>;
  onSaveComposition: (planoId: string, composition: PromptComposition) => Promise<void>;
  generatingPrompt: string | null;
  generatingImage: string | null;
}

const COMPOSITION_FIELDS: { key: keyof PromptComposition; label: string; rows: number }[] = [
  { key: 'tipoPlano', label: 'Tipo de plano', rows: 1 },
  { key: 'camara', label: 'Cámara', rows: 1 },
  { key: 'optica', label: 'Óptica', rows: 1 },
  { key: 'personajes', label: 'Personajes', rows: 2 },
  { key: 'accion', label: 'Acción', rows: 2 },
  { key: 'luz', label: 'Luz', rows: 1 },
  { key: 'estilo', label: 'Estilo', rows: 2 },
  { key: 'custom', label: 'Input personalizado', rows: 2 },
];

/** Ensure a composition field value is a string (handles legacy data with objects/arrays) */
function fieldToString(val: any): string {
  if (typeof val === 'string') return val;
  if (val == null) return '';
  if (Array.isArray(val)) return val.map(v => typeof v === 'object' ? Object.values(v).filter(Boolean).join(', ') : String(v)).join('. ');
  if (typeof val === 'object') return Object.values(val).filter(Boolean).join(', ');
  return String(val);
}

function composePromptLocal(comp: PromptComposition): string {
  const parts = [
    comp.tipoPlano,
    comp.camara,
    comp.optica,
    comp.personajes,
    comp.accion,
    comp.luz,
    comp.estilo,
    comp.custom,
  ].map(fieldToString).filter(Boolean);
  return parts.join('. ') + '.';
}

/** Build the full Gemini instruction text (same logic as generateSceneImage in image-service.ts) */
function buildGeminiInstruction(promptImagen: string, hasRefs: boolean): string {
  if (hasRefs) {
    return `Using the character reference images above as exact visual references (maintain their colors, proportions, features, accessories, and art style), generate the following scene:\n\n${promptImagen}`;
  }
  return promptImagen;
}

/** Build reference labels that match what the server sends to Gemini */
function buildReferenceLabels(refs: ReferenceAsset[], fondoImagenUrl?: string): string[] {
  const labels: string[] = [];

  // Fondo first (matches imagenes/route.ts order)
  if (fondoImagenUrl) {
    labels.push('Background reference for "Fondo". Use this image as inspiration for the background/environment where the action takes place. Match the atmosphere, lighting, and setting shown.');
  }

  // Character refs
  for (const ref of refs) {
    const frontUrl = ref.tposeFrontUrl || (ref as any).tposeUrl;
    if (frontUrl) labels.push(`${ref.nombre} - T-pose front`);
    if (ref.tposeSideUrl) labels.push(`${ref.nombre} - T-pose side`);
    if (ref.tposeBackUrl) labels.push(`${ref.nombre} - T-pose back`);
    if (ref.emotionUrl) labels.push(`${ref.nombre} - ${ref.emocion}`);
  }

  return labels;
}

/** Build a reconstructed JSON preview of the Gemini API request */
function buildGeminiRequestJson(
  promptImagen: string,
  refs: ReferenceAsset[],
  fondoImagenUrl?: string,
): object {
  const refLabels = buildReferenceLabels(refs, fondoImagenUrl);
  const contents: any[] = [];

  for (const label of refLabels) {
    contents.push({ inlineData: { mimeType: 'image/png', data: '<base64>' } });
    contents.push({ text: `[Reference: ${label}]` });
  }

  const instruction = buildGeminiInstruction(promptImagen, refLabels.length > 0);
  contents.push({ text: instruction });

  return {
    model: 'gemini-3-pro-image-preview',
    contents,
    config: {
      responseModalities: ['TEXT', 'IMAGE'],
      imageConfig: { aspectRatio: '16:9' },
    },
  };
}

export function PlanoAssetCard({
  plano, index, slug, capNumero, fondoImagenUrl,
  onGeneratePrompt, onGenerateImage, onSaveComposition,
  generatingPrompt, generatingImage,
}: PlanoAssetCardProps) {
  const refs = plano.referenceAssets || [];
  const hasPrompt = !!plano.promptImagen;
  const hasImage = !!plano.imagenUrl;
  const hasComposition = !!plano.promptComposition;
  const isGeneratingPrompt = generatingPrompt === plano.id;
  const isGeneratingImage = generatingImage === plano.id;
  const isBusy = !!generatingPrompt || !!generatingImage;
  const missingRefs = refs.filter(r => !r.tposeFrontUrl && !(r as any).tposeUrl);

  const [expanded, setExpanded] = useState(false);
  const [editComp, setEditComp] = useState<PromptComposition | null>(null);
  const [saving, setSaving] = useState(false);
  const [showJson, setShowJson] = useState(false);

  const isEditing = editComp !== null;
  const currentComp = editComp || plano.promptComposition;
  const isDirty = isEditing && JSON.stringify(editComp) !== JSON.stringify(plano.promptComposition);

  const handleStartEdit = () => {
    if (plano.promptComposition) {
      const c = plano.promptComposition;
      setEditComp({
        personajes: fieldToString(c.personajes),
        accion: fieldToString(c.accion),
        luz: fieldToString(c.luz),
        camara: fieldToString(c.camara),
        optica: fieldToString(c.optica),
        tipoPlano: fieldToString(c.tipoPlano),
        estilo: fieldToString(c.estilo),
        custom: fieldToString(c.custom),
      });
    } else {
      setEditComp({
        personajes: '', accion: '', luz: '', camara: '', optica: '',
        tipoPlano: '', estilo: '', custom: '',
      });
    }
    setExpanded(true);
  };

  const handleFieldChange = (key: keyof PromptComposition, value: string) => {
    if (!editComp) return;
    setEditComp({ ...editComp, [key]: value });
  };

  const handleSave = async () => {
    if (!editComp) return;
    setSaving(true);
    try {
      await onSaveComposition(plano.id, editComp);
      setEditComp(null);
    } finally {
      setSaving(false);
    }
  };

  const handleCancelEdit = () => {
    setEditComp(null);
  };

  return (
    <div className={`bg-white border rounded-lg overflow-hidden transition-colors ${hasPrompt ? 'border-stone-200 hover:border-stone-300' : 'border-dashed border-stone-300'}`}>
      {/* Header */}
      <div className="px-4 py-2.5 bg-stone-50/80 border-b border-stone-100 flex items-center justify-between">
        <div className="flex items-center gap-2.5">
          <span className="flex-shrink-0 w-6 h-6 bg-indigo-50 text-indigo-600 rounded text-[11px] font-semibold flex items-center justify-center">
            {index + 1}
          </span>
          <span className="text-xs font-medium text-stone-700">{plano.numeroPlano}</span>
          <span className="text-xs text-stone-400">{plano.segmentoGuion}</span>
        </div>
        <div className="flex items-center gap-2">
          <div className="flex items-center gap-1 text-xs text-stone-400">
            <Clock className="w-3 h-3" />
            {plano.tiempoSegundos}s
          </div>
          {hasPrompt && !hasImage && (
            <span className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-50 text-indigo-600">
              Prompt listo
            </span>
          )}
          {hasImage && (
            <span className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium bg-emerald-100 text-emerald-700">
              Imagen generada
            </span>
          )}
        </div>
      </div>

      {!hasPrompt ? (
        /* Empty state: no prompt yet */
        <div className="px-4 py-4 flex items-center justify-between">
          <div>
            <p className="text-sm text-stone-600">{plano.accionDescripcion}</p>
            <p className="text-xs text-stone-400 mt-1">Sin prompt de imagen</p>
          </div>
          <Button
            size="sm"
            variant="outline"
            onClick={() => onGeneratePrompt(plano.id)}
            loading={isGeneratingPrompt}
            disabled={isBusy}
          >
            <FileText className="w-3.5 h-3.5" />
            Generar prompt
          </Button>
        </div>
      ) : (
        <>
          {/* Reference images row */}
          {(refs.length > 0 || fondoImagenUrl) && (
            <div className="px-4 py-3 border-b border-stone-100">
              <span className="text-[10px] font-medium text-stone-400 uppercase tracking-wide">Referencias</span>
              <div className="mt-2 flex flex-wrap gap-3">
                {/* Fondo thumbnail */}
                {fondoImagenUrl && (
                  <div className="text-center">
                    <img
                      src={fondoImagenUrl}
                      alt="Fondo"
                      className="w-20 h-12 rounded border border-indigo-200 object-cover bg-stone-50"
                    />
                    <span className="text-[10px] text-indigo-500 mt-0.5 block font-medium">Fondo</span>
                  </div>
                )}
                {/* Character refs */}
                {refs.map((ref) => (
                  <ReferenceGroup key={ref.personajeId} ref_={ref} />
                ))}
              </div>
            </div>
          )}

          {/* Composition toggle + prompt final */}
          <div className="px-4 py-3 border-b border-stone-100">
            <div className="flex items-center justify-between mb-2">
              <button
                onClick={() => setExpanded(!expanded)}
                className="flex items-center gap-1.5 text-[10px] font-medium text-stone-400 uppercase tracking-wide hover:text-stone-600 transition-colors"
              >
                {expanded ? <ChevronUp className="w-3 h-3" /> : <ChevronDown className="w-3 h-3" />}
                Composición
              </button>
              <div className="flex items-center gap-1.5">
                {!isEditing && hasComposition && (
                  <button
                    onClick={handleStartEdit}
                    className="text-[10px] font-medium text-indigo-500 hover:text-indigo-700 transition-colors"
                  >
                    Editar
                  </button>
                )}
                {isEditing && (
                  <>
                    <button
                      onClick={handleCancelEdit}
                      className="text-[10px] font-medium text-stone-400 hover:text-stone-600 transition-colors"
                    >
                      Cancelar
                    </button>
                    <Button
                      size="sm"
                      variant="primary"
                      onClick={handleSave}
                      loading={saving}
                      disabled={!isDirty}
                    >
                      <Save className="w-3 h-3" />
                      Guardar
                    </Button>
                  </>
                )}
              </div>
            </div>

            {/* Expanded: sub-field editors */}
            {expanded && currentComp && (
              <div className="space-y-2 mb-3">
                {COMPOSITION_FIELDS.map(({ key, label, rows }) => (
                  <div key={key}>
                    <label className="text-[10px] font-medium text-stone-500 block mb-0.5">{label}</label>
                    {isEditing ? (
                      <textarea
                        value={fieldToString(editComp![key])}
                        onChange={(e) => handleFieldChange(key, e.target.value)}
                        rows={rows}
                        className="w-full px-2 py-1.5 text-xs border border-stone-200 rounded bg-white text-stone-700 focus:outline-none focus:ring-1 focus:ring-indigo-400 focus:border-indigo-400 resize-y font-mono transition-colors"
                      />
                    ) : (
                      <p className="text-xs text-stone-600 bg-stone-50 rounded px-2 py-1.5 font-mono min-h-[28px]">
                        {fieldToString(currentComp[key]) || <span className="text-stone-300 italic">vacío</span>}
                      </p>
                    )}
                  </div>
                ))}
              </div>
            )}

            {/* Final composed prompt (always visible) */}
            <div>
              <span className="text-[10px] font-medium text-stone-400 uppercase tracking-wide">Prompt final</span>
              <p className="mt-1 text-xs text-stone-600 leading-relaxed bg-stone-50 rounded p-2.5 font-mono">
                {isEditing && editComp ? composePromptLocal(editComp) : plano.promptImagen}
              </p>
            </div>

            {/* Full Gemini instruction (with reference wrapper) */}
            {(() => {
              const currentPrompt = isEditing && editComp ? composePromptLocal(editComp) : plano.promptImagen;
              const hasRefs = refs.length > 0 || !!fondoImagenUrl;
              const fullInstruction = buildGeminiInstruction(currentPrompt || '', hasRefs);
              return hasRefs ? (
                <div className="mt-2">
                  <span className="text-[10px] font-medium text-stone-400 uppercase tracking-wide">Instrucción enviada a Gemini</span>
                  <p className="mt-1 text-[11px] text-stone-500 leading-relaxed bg-amber-50/60 border border-amber-100 rounded p-2.5 font-mono whitespace-pre-wrap">
                    {fullInstruction}
                  </p>
                </div>
              ) : null;
            })()}

            {/* JSON request preview button */}
            <div className="mt-2 flex items-center gap-2">
              <button
                onClick={() => setShowJson(!showJson)}
                className="flex items-center gap-1 text-[10px] font-medium text-stone-400 hover:text-indigo-500 transition-colors"
              >
                <Code className="w-3 h-3" />
                {showJson ? 'Ocultar JSON' : 'JSON Nano Banana Pro'}
              </button>
            </div>
            {showJson && (
              <div className="mt-1.5">
                <pre className="text-[10px] text-stone-500 leading-relaxed bg-stone-900 text-stone-300 rounded p-3 font-mono overflow-x-auto max-h-80 overflow-y-auto">
                  {JSON.stringify(
                    buildGeminiRequestJson(
                      isEditing && editComp ? composePromptLocal(editComp) : (plano.promptImagen || ''),
                      refs,
                      fondoImagenUrl
                    ),
                    null,
                    2
                  )}
                </pre>
              </div>
            )}
          </div>

          {/* Result / Generate image */}
          <div className="px-4 py-3">
            {hasImage ? (
              <div>
                <div className="flex items-center justify-between mb-2">
                  <span className="text-[10px] font-medium text-stone-400 uppercase tracking-wide">Resultado</span>
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={() => onGenerateImage(plano.id)}
                    loading={isGeneratingImage}
                    disabled={isBusy}
                  >
                    <Sparkles className="w-3 h-3" />
                    Regenerar imagen
                  </Button>
                </div>
                <img
                  src={`${plano.imagenUrl}?v=${Date.now()}`}
                  alt={`Plano ${plano.numeroPlano}`}
                  className="w-full rounded-lg border border-stone-200 object-cover"
                  style={{ aspectRatio: '16/9' }}
                />
              </div>
            ) : (
              <div className="flex items-center justify-between">
                <div className="flex items-center gap-2 text-stone-400">
                  <Image className="w-4 h-4" />
                  <span className="text-xs">Sin imagen generada</span>
                </div>
                <Button
                  size="sm"
                  onClick={() => onGenerateImage(plano.id)}
                  loading={isGeneratingImage}
                  disabled={isBusy}
                >
                  <Sparkles className="w-3.5 h-3.5" />
                  Generar imagen
                </Button>
              </div>
            )}
          </div>

          {/* Missing refs warning */}
          {missingRefs.length > 0 && (
            <div className="px-4 py-2 bg-amber-50 border-t border-amber-100 flex items-center gap-2">
              <AlertCircle className="w-3.5 h-3.5 text-amber-500 flex-shrink-0" />
              <span className="text-xs text-amber-700">
                Sin T-pose: {missingRefs.map(r => r.nombre).join(', ')}
              </span>
              <Link
                href={`/project/${slug}?step=personajes`}
                className="ml-auto text-xs font-medium text-amber-600 hover:text-amber-800 transition-colors"
              >
                Generar assets
              </Link>
            </div>
          )}
        </>
      )}
    </div>
  );
}

function ReferenceGroup({ ref_ }: { ref_: ReferenceAsset }) {
  const tposes = [
    { url: ref_.tposeFrontUrl || (ref_ as any).tposeUrl, label: 'Front' },
    { url: ref_.tposeSideUrl, label: 'Side' },
    { url: ref_.tposeBackUrl, label: 'Back' },
  ].filter(t => t.url);

  return (
    <div className="flex items-center gap-1.5">
      {/* T-poses */}
      {tposes.length > 0 ? (
        tposes.map(({ url, label }) => (
          <div key={label} className="text-center">
            <img
              src={url}
              alt={`${ref_.nombre} ${label}`}
              className="w-12 h-12 rounded border border-stone-200 object-cover bg-stone-50"
            />
            <span className="text-[9px] text-stone-400 mt-0.5 block">{label}</span>
          </div>
        ))
      ) : (
        <div className="text-center">
          <div className="w-12 h-12 rounded border border-dashed border-stone-300 bg-stone-50 flex items-center justify-center">
            <span className="text-[9px] text-stone-400">Sin T</span>
          </div>
        </div>
      )}

      {/* Emotion */}
      <div className="text-center">
        {ref_.emotionUrl ? (
          <img
            src={ref_.emotionUrl}
            alt={`${ref_.nombre} ${ref_.emocion}`}
            className="w-12 h-12 rounded border border-stone-200 object-cover bg-stone-50"
          />
        ) : (
          <div className="w-12 h-12 rounded border border-dashed border-stone-300 bg-stone-50 flex items-center justify-center">
            <span className="text-[9px] text-stone-400">Sin em.</span>
          </div>
        )}
        <span className="text-[9px] text-stone-400 mt-0.5 block">{ref_.emocion}</span>
      </div>

      {/* Name */}
      <span className="text-[10px] font-medium text-stone-600 self-start mt-1 ml-0.5">{ref_.nombre}</span>
    </div>
  );
}
