import React, { useEffect, useMemo, useRef, useState } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Label } from '@/components/ui/label';
import { Checkbox } from '@/components/ui/checkbox';
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
import { uploadEventFile } from '@/shared/api/fileService';
import { getEventMedia } from '@/features/event/api/getEventMedia';
import { generateSocialMediaPosts, publishSocialMediaPost } from '@/features/photopost/api/socialPostService';
import { speechToText } from '@/shared/api/toolService';
import { Loader2, Check, X } from 'lucide-react';

interface PhotoPostWizardProps {
  eventId: string | number;
  onComplete: () => void;
  images?: { url: string; id: string }[];
  participants?: { id: string; name: string; avatar?: string }[];
  onFetchEventImages?: (eventId: string | number) => Promise<{ id: string; url: string }[]>;
  onUploadEventFile?: (file: File, eventId?: string) => Promise<{ success: boolean; url?: string; fileUrl?: string; id?: string; message?: string }>;
  onGenerateSocialPosts?: (payload: any) => Promise<any>;
  onPublishSocialPost?: (args: { postId: string; posts: any; images: any; scheduledTime: string }) => Promise<any>;
  onSpeechToText?: (file: File) => Promise<{ success: boolean; transcription?: string; message: string }>;
}

type Step = 'media' | 'loading' | 'review';

const defaultChannels = ['LinkedIn', 'Twitter', 'Facebook', 'Instagram'];

const MicIcon: React.FC<{ className?: string }> = ({ className = 'w-5 h-5 sm:w-6 sm:h-6' }) => (
  <svg className={className} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="currentColor" strokeWidth={1.8} strokeLinecap="round" strokeLinejoin="round">
    <path d="M12 1.75a3.25 3.25 0 013.25 3.25v6a3.25 3.25 0 11-6.5 0v-6A3.25 3.25 0 0112 1.75z" />
    <path d="M5.75 11.75a6.25 6.25 0 0012.5 0" />
    <path d="M12 18v4" />
    <path d="M8 22h8" />
  </svg>
);

const PhotoPostWizard: React.FC<PhotoPostWizardProps> = ({ eventId, onComplete, images = [], participants = [], onFetchEventImages, onUploadEventFile, onGenerateSocialPosts, onPublishSocialPost, onSpeechToText }) => {
  const [step, setStep] = useState<Step>('media');
  const [eventImages, setEventImages] = useState<{ id: string; url: string }[]>(images);
  const [localImages, setLocalImages] = useState(images);
  const [selectedImageIds, setSelectedImageIds] = useState<string[]>([]);
  const [description, setDescription] = useState('');
  const [selectedParticipants, setSelectedParticipants] = useState<string[]>([]);
  const [selectedChannels, setSelectedChannels] = useState<string[]>(defaultChannels);
  const [loading, setLoading] = useState(false);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [scheduledTime, setScheduledTime] = useState('');
  const [aiPosts, setAiPosts] = useState<Record<string, Record<string, string>> | null>(null);
  const [editedPosts, setEditedPosts] = useState<Record<string, Record<string, string>>>({});
  const [activeLang, setActiveLang] = useState<'de' | 'en' | 'es'>('de');
  const [postId, setPostId] = useState<string>('');
  const languages = [
    { code: 'de', label: 'Deutsch' },
    { code: 'en', label: 'Englisch' },
    { code: 'es', label: 'Spanisch' },
  ];

  // voice recording
  const [recording, setRecording] = useState(false);
  const [audioBlob, setAudioBlob] = useState<Blob | null>(null);
  const [isProcessing, setIsProcessing] = useState(false);
  const mediaRecorderRef = useRef<MediaRecorder | null>(null);
  const audioChunks = useRef<Blob[]>([]);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [previewImage, setPreviewImage] = useState<string | null>(null);

  const handleImageClick = (e: React.MouseEvent, url: string) => {
    e.stopPropagation();
    setPreviewImage(url);
  };

  const handleSelectImage = (id: string, e: React.MouseEvent) => {
    e.stopPropagation();
    setSelectedImageIds((prev) => (prev.includes(id) ? prev.filter((i) => i !== id) : [...prev, id]));
  };

  const canContinueFromMedia = selectedImageIds.length > 0 && description.trim().length > 0;

  const selectedImages = useMemo(() => [...eventImages, ...localImages].filter((img) => selectedImageIds.includes(img.id)), [eventImages, localImages, selectedImageIds]);

  const toggleArrayValue = (arr: string[], value: string) => (arr.includes(value) ? arr.filter((v) => v !== value) : [...arr, value]);

  // fetch event images on mount
  useEffect(() => {
    const fetchEventImages = async () => {
      try {
        const imgs = onFetchEventImages
          ? await onFetchEventImages(eventId)
          : await getEventMedia(eventId as any);
        if (imgs) {
          const normalized = Array.isArray(imgs)
            ? imgs.map((item: any, idx: number) =>
                typeof item === 'string'
                  ? { id: `remote-${idx}`, url: item }
                  : { id: item.id?.toString() || `remote-${idx}`, url: item.url || item.file_url }
              )
            : imgs;
          setEventImages(normalized);
        }
      } catch (err) {
        console.error('Fehler beim Laden der Event Bilder', err);
      }
    };
    fetchEventImages();
  }, [eventId, onFetchEventImages]);

  useEffect(() => {
    if (!images) return;
    setLocalImages((prev) => {
      const map = new Map<string, { id: string; url: string }>();
      for (const it of prev) map.set(it.id, it);
      for (const it of images) map.set(it.id, it);
      const merged = Array.from(map.values());
      if (
        merged.length === prev.length &&
        merged.every((item, idx) => item.id === prev[idx].id && item.url === prev[idx].url)
      ) {
        return prev;
      }
      return merged;
    });
  }, [images]);

  // recording handlers
  const handleStartRecording = async () => {
    setAudioBlob(null);
    setIsProcessing(false);
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      const mediaRecorder = new MediaRecorder(stream);
      mediaRecorderRef.current = mediaRecorder;
      audioChunks.current = [];
      mediaRecorder.ondataavailable = (event) => { if (event.data.size > 0) audioChunks.current.push(event.data); };
      mediaRecorder.onstop = async () => {
        setIsProcessing(true);
        const blob = new Blob(audioChunks.current, { type: 'audio/webm' });
        setAudioBlob(blob);
        try {
          const file = new File([blob], `voice_${Date.now()}.webm`, { type: 'audio/webm' });
          const sttResult = onSpeechToText ? await onSpeechToText(file) : await speechToText(file);
          if (sttResult.success && sttResult.transcription) {
            setDescription((prev) => (prev ? `${prev} ${sttResult.transcription}` : sttResult.transcription));
          }
        } catch (error) {
          console.error('Error converting speech to text:', error);
        } finally {
          setIsProcessing(false);
        }
      };
      mediaRecorder.start();
      setRecording(true);
    } catch (e) {
      console.error('Error accessing microphone:', e);
      alert('Konnte nicht auf das Mikrofon zugreifen.');
    }
  };

  const handleStopRecording = () => {
    if (mediaRecorderRef.current && recording) {
      mediaRecorderRef.current.stop();
      setRecording(false);
    }
  };

  useEffect(() => {
    return () => {
      if (audioBlob) {
        const url = URL.createObjectURL(audioBlob);
        URL.revokeObjectURL(url);
      }
    };
  }, [audioBlob]);

  const handleUploadClick = () => fileInputRef.current?.click();
  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files[0]) {
      const file = e.target.files[0];
      if (!file.type.startsWith('image/')) { alert('Nur Bilddateien erlaubt.'); return; }
      if (file.size === 0) { alert('Datei ist leer (0 Bytes).'); return; }
      const result = onUploadEventFile
        ? await onUploadEventFile(file, String(eventId))
        : await uploadEventFile(file, String(eventId));
      if (result.success && (result.url || result.fileUrl)) {
        const imgUrl = result.url || result.fileUrl;
        const uploaded = { id: result.id || `up-${Date.now()}`, url: imgUrl } as { id: string; url: string };
        setLocalImages((prev) => [...prev, uploaded]);
        setSelectedImageIds((prev) => [...prev, uploaded.id]);
      }
    }
    e.target.value = '';
  };


  const handleGenerate = async () => {
    setLoading(true);
    setAiPosts(null);
    try {
      const payload: any = {
        eventId,
        images: selectedImageIds
          .map((id) => [...eventImages, ...localImages].find((img) => img.id === id)?.id)
          .filter(Boolean),
        description,
        participants: selectedParticipants
          .map((id) => participants.find((p) => p.id === id)?.name)
          .filter(Boolean),
        channels: defaultChannels,
      };
      const response = onGenerateSocialPosts
        ? await onGenerateSocialPosts(payload)
        : await generateSocialMediaPosts(payload);
      const obj = Array.isArray(response) ? response[0] : response;
      const src = obj?.output ? obj.output : obj;
      const result: Record<string, Record<string, string>> = { de: {}, en: {}, es: {} };
      for (const channel of defaultChannels) {
        const key = channel.toLowerCase();
        const arr = src?.[key];
        if (Array.isArray(arr) && arr[0]?.text && arr[0].text[0]) {
          result.de[key] = arr[0].text[0].de || '';
          result.en[key] = arr[0].text[0].en || '';
          result.es[key] = arr[0].text[0].es || '';
        } else {
          result.de[key] = '';
          result.en[key] = '';
          result.es[key] = '';
        }
      }
      setPostId(obj?.id || obj?.postId || obj?.data?.id || obj?.data?.postId || '');
      setAiPosts(result);
      setEditedPosts(result);
      setStep('review');
    } catch (err) {
      console.error('Error generating posts', err);
      setStep('media');
    } finally {
      setLoading(false);
    }
  };

  const handleImmediatePost = async () => {
    if (isSubmitting) return;
    setIsSubmitting(true);
    try {
      if (!postId) { return; }
      const result = onPublishSocialPost
        ? await onPublishSocialPost({ postId, posts: editedPosts, images: selectedImageIds, scheduledTime: new Date().toISOString() })
        : await publishSocialMediaPost({ postId, posts: editedPosts, images: selectedImageIds, scheduledTime: new Date().toISOString() });
      if (result?.status === 'sucess') {
        onComplete();
      }
    } finally {
      setIsSubmitting(false);
    }
  };

  const handleScheduledPost = async () => {
    if (isSubmitting) return;
    setIsSubmitting(true);
    try {
      if (!scheduledTime) { return; }
      if (!postId) { return; }
      const result = onPublishSocialPost
        ? await onPublishSocialPost({ postId, posts: editedPosts, images: selectedImageIds, scheduledTime })
        : await publishSocialMediaPost({ postId, posts: editedPosts, images: selectedImageIds, scheduledTime });
      if (result?.status === 'sucess') {
        onComplete();
      }
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <>
    <Card className="w-full max-w-4xl mx-auto">
      <CardHeader>
        <CardTitle>Quick Post für Event #{String(eventId)}</CardTitle>
      </CardHeader>
      <CardContent>
        {step === 'media' && (
          <div className="space-y-4">
            <div className="flex justify-between items-center mb-2">
              <div className="font-semibold">Bilder aus diesem Event</div>
              {[...eventImages, ...localImages].length > 0 && (
                <span className="text-sm text-muted-foreground">{selectedImageIds.length} {selectedImageIds.length === 1 ? 'Bild' : 'Bilder'} ausgewählt</span>
              )}
            </div>
            <div className="grid grid-cols-4 sm:grid-cols-6 gap-2 mb-3">
              {eventImages.length > 0 ? (
                eventImages.map((img) => {
                  const isSelected = selectedImageIds.includes(img.id);
                  return (
                    <div
                      key={img.id}
                      onClick={(e) => handleImageClick(e, img.url)}
                      className={`relative group rounded-md overflow-hidden border-2 cursor-pointer transition-all ${
                        isSelected ? 'border-primary ring-2 ring-primary' : 'border-transparent hover:border-muted-foreground/30'
                      } aspect-square`}
                    >
                      <img src={img.url} alt="Event" className="absolute inset-0 w-full h-full object-cover" />
                      <div
                        onClick={(e) => handleSelectImage(img.id, e)}
                        className={`absolute top-1 right-1 w-5 h-5 rounded flex items-center justify-center transition-colors ${
                          isSelected ? 'bg-primary text-primary-foreground' : 'bg-background/90 text-foreground/50 hover:bg-background/80 hover:text-foreground/70'
                        }`}
                      >
                        {isSelected && <Check className="h-3.5 w-3.5" />}
                      </div>
                    </div>
                  );
                })
              ) : (
                <div className="col-span-full text-center py-4 text-sm text-muted-foreground">Keine Bilder in diesem Event vorhanden.</div>
              )}
            </div>
            <div className="font-semibold mb-1">Bilder aus dieser Session</div>
            <div className="flex flex-wrap gap-2 mb-2 items-center">
              <Button type="button" variant="outline" size="sm" onClick={handleUploadClick} className="h-16 w-16 flex items-center justify-center p-0 text-xl" title="Bild hochladen">＋</Button>
              <input type="file" accept="image/*" ref={fileInputRef} style={{ display: 'none' }} onChange={handleFileChange} />
              {localImages.length === 0 && (
                <span className="text-xs text-muted-foreground">Keine Bilder in dieser Session.</span>
              )}
              <div className="grid grid-cols-4 sm:grid-cols-6 gap-2 flex-1 min-w-full">
                {localImages.map((img) => {
                  const isSelected = selectedImageIds.includes(img.id);
                  return (
                    <div
                      key={img.id}
                      onClick={(e) => handleImageClick(e, img.url)}
                      className={`relative group rounded-md overflow-hidden border-2 cursor-pointer transition-all ${
                        isSelected ? 'border-primary ring-2 ring-primary' : 'border-transparent hover:border-muted-foreground/30'
                      } aspect-square`}
                    >
                      <img src={img.url} alt="Session" className="absolute inset-0 w-full h-full object-cover" />
                      <div
                        onClick={(e) => handleSelectImage(img.id, e)}
                        className={`absolute top-1 right-1 w-5 h-5 rounded flex items-center justify-center transition-colors ${
                          isSelected ? 'bg-primary text-primary-foreground' : 'bg-background/90 text-foreground/50 hover:bg-background/80 hover:text-foreground/70'
                        }`}
                      >
                        {isSelected && <Check className="h-3.5 w-3.5" />}
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
            <div className="font-semibold mb-1 mt-2">Wer ist dabei?</div>
            <div className="flex flex-wrap gap-2 mb-2">
              {participants.map((p) => (
                <label key={p.id} className="flex items-center gap-2 cursor-pointer">
                  <Checkbox checked={selectedParticipants.includes(p.id)} onCheckedChange={() => setSelectedParticipants((prev) => prev.includes(p.id) ? prev.filter((i) => i !== p.id) : [...prev, p.id])} />
                  <Avatar className="w-6 h-6">{p.avatar ? <AvatarImage src={p.avatar} alt={p.name} /> : <AvatarFallback>{p.name[0]}</AvatarFallback>}</Avatar>
                  <span className="text-xs">{p.name}</span>
                </label>
              ))}
            </div>
            <div className="font-semibold mb-1 mt-2">Situation beschreiben</div>
            <div className="relative mb-2">
              <Textarea value={description} onChange={(e) => setDescription(e.target.value)} rows={3} placeholder="Was passiert auf dem Foto? Wer ist zu sehen?" disabled={isProcessing} className={`pr-10 ${isProcessing ? 'opacity-60 cursor-not-allowed' : ''}`} />
              <button type="button" onClick={recording ? handleStopRecording : handleStartRecording} disabled={isProcessing} className={`absolute bottom-2 right-2 focus:outline-none ${isProcessing ? 'cursor-wait' : 'cursor-pointer'}`} title={recording ? 'Aufnahme stoppen' : 'Aufnahme starten'}>
                {isProcessing ? (
                  <svg className="animate-spin h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle><path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
                ) : recording ? (
                  <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 text-red-600" viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="6" width="12" height="12" rx="2" /></svg>
                ) : (
                  <MicIcon />
                )}
              </button>
            </div>
            <div className="flex justify-end">
              <Button onClick={async () => { setStep('loading'); await handleGenerate(); }} disabled={!canContinueFromMedia || loading}>
                Vorschläge generieren
              </Button>
            </div>
          </div>
        )}

        {step === 'loading' && (
          <div className="flex flex-col items-center justify-center py-12">
            <Loader2 className="h-8 w-8 animate-spin text-primary mb-4" />
            <p className="text-muted-foreground">Bitte warten, Beiträge werden generiert...</p>
          </div>
        )}

        {step === 'review' && (
          <div className="space-y-4">
            <div className="text-sm text-muted-foreground">Vorschau</div>
            <div className="rounded-lg border p-4">
              <div className="text-sm font-medium mb-2">Beschreibung</div>
              <div className="text-sm whitespace-pre-wrap">{description}</div>
              {selectedImages.length > 0 && (
                <div className="mt-4 flex gap-2 overflow-x-auto">
                  {selectedImages.map((img) => (
                    <img key={img.id} src={img.url} className="h-20 rounded border object-cover" />
                  ))}
                </div>
              )}
            </div>
            {aiPosts && (
              <div className="mt-4">
                <div className="font-semibold text-sm sm:text-base mb-2">KI-Vorschläge für Social Media:</div>
                <div className="flex gap-2 mb-3">
                  {languages.map((lang) => (
                    <button key={lang.code} className={`px-2 py-1 rounded text-xs sm:text-sm transition-colors duration-150 ${activeLang === (lang.code as any) ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-700'}`} onClick={() => setActiveLang(lang.code as any)} type="button">
                      {lang.label}
                    </button>
                  ))}
                </div>
                {defaultChannels.map((channel) => (
                  <div key={channel} className="mb-2">
                    <div className="text-xs font-bold">{channel}:</div>
                    <Textarea
                      value={editedPosts[activeLang]?.[channel.toLowerCase()] || ''}
                      onChange={(e) =>
                        setEditedPosts((prev) => ({
                          ...prev,
                          [activeLang]: {
                            ...(prev[activeLang] || {}),
                            [channel.toLowerCase()]: e.target.value,
                          },
                        }))
                      }
                      className="text-xs bg-muted"
                      rows={2}
                    />
                  </div>
                ))}
              </div>
            )}
            <div className="flex justify-between">
              <Button variant="outline" onClick={() => setStep('media')}>Zurück</Button>
              <div className="flex flex-col sm:flex-row gap-2 w-full sm:w-auto">
                <Button type="button" className="w-full sm:w-auto" onClick={handleImmediatePost} disabled={isSubmitting}>
                  Sofort senden
                </Button>
                <div className="flex gap-2 w-full sm:w-auto">
                  <input type="datetime-local" value={scheduledTime} onChange={(e) => setScheduledTime(e.target.value)} className="border rounded px-2 py-1 w-full sm:w-auto text-xs" />
                  <Button variant="outline" className="w-full" onClick={handleScheduledPost} disabled={isSubmitting || !scheduledTime}>
                    Später posten
                  </Button>
                </div>
              </div>
            </div>
          </div>
        )}
      </CardContent>
    </Card>
    {previewImage && (
      <div 
        className="fixed inset-0 bg-black/80 flex items-center justify-center z-50 p-4"
        onClick={() => setPreviewImage(null)}
      >
        <div className="relative max-w-4xl w-full max-h-[90vh]">
          <button 
            className="absolute -top-10 right-0 text-white hover:text-gray-300"
            onClick={(e) => {
              e.stopPropagation();
              setPreviewImage(null);
            }}
          >
            <X className="w-6 h-6" />
          </button>
          <div className="bg-background rounded-lg overflow-hidden">
            <img 
              src={previewImage} 
              alt="Vorschau" 
              className="w-full h-auto max-h-[80vh] object-contain mx-auto"
              onClick={(e) => e.stopPropagation()}
            />
          </div>
        </div>
      </div>
    )}
    </>
  );
};

export default PhotoPostWizard;
