import { useState, useRef, useCallback } from "react";
import { Link } from "wouter";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { motion, AnimatePresence } from "framer-motion";
import {
  Download, Sparkles, Loader2, RefreshCw, ChevronDown, ChevronUp,
  CheckCircle, XCircle, Clock, Server, Upload, X, ImagePlus, LogIn, AlertTriangle, Lock, Globe,
} from "lucide-react";
import { useQueryClient } from "@tanstack/react-query";
import { useAuth } from "@/contexts/AuthContext";

import { useGenerateImage, getGetImageHistoryQueryKey } from "@workspace/api-client-react";
import type { ApiDebugInfo } from "@workspace/api-client-react";

import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Badge } from "@/components/ui/badge";
import { useToast } from "@/hooks/use-toast";
import { useLang } from "@/contexts/LanguageContext";
import { AuthModal } from "@/components/AuthModal";

const NANO_BANANA_MODELS = new Set(["nano-banana-pro", "nano-banana-2"]);

const formSchema = z.object({
  prompt: z.string().min(1),
  style: z.string().optional(),
  aspectRatio: z.string().optional(),
  model: z.string().optional(),
  resolution: z.string().optional(),
});

type FormValues = z.infer<typeof formSchema>;

const MODEL_KEYS = ["grok", "meta", "imagen-pro", "imagen-4", "imagen-flash", "nano-banana-pro", "nano-banana-2"] as const;
const STYLE_KEYS = ["none", "realistic", "anime", "artistic", "cartoon", "sketch", "oil_painting", "watercolor", "digital_art"] as const;
const STYLE_EMOJIS: Record<string, string> = {
  none: "🚫", realistic: "📷", anime: "🎌", artistic: "🎨", cartoon: "🖼️",
  sketch: "✏️", oil_painting: "🖌️", watercolor: "💧", digital_art: "💻",
};
const ASPECT_RATIO_KEYS = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"] as const;

function JsonBlock({ data }: { data: unknown }) {
  return (
    <pre className="text-xs font-mono text-emerald-300 bg-black/40 rounded-lg p-3 overflow-x-auto whitespace-pre-wrap break-all leading-5 max-h-48 overflow-y-auto">
      {JSON.stringify(data, null, 2)}
    </pre>
  );
}

function ApiDebugPanel({ debug }: { debug: ApiDebugInfo }) {
  const { t } = useLang();
  const [openSection, setOpenSection] = useState<string | null>("info");
  const toggle = (key: string) => setOpenSection(prev => prev === key ? null : key);
  const statusOk = debug.responseStatus >= 200 && debug.responseStatus < 300;

  return (
    <motion.div
      initial={{ opacity: 0, y: 16 }}
      animate={{ opacity: 1, y: 0 }}
      className="mt-6 rounded-xl border border-violet-500/30 bg-[#0e0a1a] overflow-hidden"
    >
      <div className="flex items-center gap-3 px-4 py-3 border-b border-violet-500/20 bg-violet-950/30">
        <Server className="w-4 h-4 text-violet-400" />
        <span className="text-sm font-semibold text-violet-300">{t.debugTitle}</span>
        <div className="ml-auto flex items-center gap-2">
          {debug.usedFallback ? (
            <Badge variant="destructive" className="text-xs">{t.debugFallback}</Badge>
          ) : (
            <Badge className="text-xs bg-emerald-600/20 text-emerald-400 border-emerald-500/30">{t.debugReal}</Badge>
          )}
          <div className="flex items-center gap-1 text-xs text-muted-foreground">
            <Clock className="w-3 h-3" />
            <span>{debug.durationMs} {t.debugMs}</span>
          </div>
        </div>
      </div>

      {[
        { key: "info", label: t.debugSectionInfo, content: (
          <div className="px-4 pb-3 space-y-2 text-xs">
            <div className="flex items-start gap-2">
              <span className="text-muted-foreground w-20 shrink-0">{t.debugEndpoint}</span>
              <span className="text-violet-200 font-mono break-all">{debug.requestUrl}</span>
            </div>
            <div className="flex items-center gap-2">
              <span className="text-muted-foreground w-20 shrink-0">{t.debugMethod}</span>
              <Badge className="text-xs bg-blue-600/20 text-blue-400 border-blue-500/30">{debug.requestMethod}</Badge>
            </div>
            <div className="flex items-center gap-2">
              <span className="text-muted-foreground w-20 shrink-0">{t.debugStatus}</span>
              <span className={`flex items-center gap-1 font-semibold ${statusOk ? "text-emerald-400" : "text-red-400"}`}>
                {statusOk ? <CheckCircle className="w-3.5 h-3.5" /> : <XCircle className="w-3.5 h-3.5" />}
                {debug.responseStatus === 0 ? t.debugNoResponse : debug.responseStatus}
              </span>
            </div>
            <div className="flex items-center gap-2">
              <span className="text-muted-foreground w-20 shrink-0">{t.debugDuration}</span>
              <span className="text-amber-400">{debug.durationMs} {t.debugMs}</span>
            </div>
            {debug.usedFallback && debug.fallbackReason && (
              <div className="flex items-start gap-2">
                <span className="text-muted-foreground w-20 shrink-0">{t.debugReason}</span>
                <span className="text-red-400 break-all">{debug.fallbackReason}</span>
              </div>
            )}
          </div>
        )},
        { key: "request", label: t.debugSectionRequest, content: (
          <div className="px-4 pb-3 space-y-2">
            <p className="text-xs text-muted-foreground mb-1">{t.debugHeaders}</p>
            <JsonBlock data={debug.requestHeaders} />
            <p className="text-xs text-muted-foreground mb-1 mt-2">{t.debugBody}</p>
            <JsonBlock data={debug.requestBody} />
          </div>
        )},
        { key: "response", label: t.debugSectionResponse, content: (
          <div className="px-4 pb-3">
            <JsonBlock data={debug.responseBody} />
          </div>
        )},
      ].map(({ key, label, content }, idx, arr) => (
        <div key={key} className={idx < arr.length - 1 ? "border-b border-violet-500/10" : ""}>
          <button
            onClick={() => toggle(key)}
            className="w-full flex items-center justify-between px-4 py-2.5 hover:bg-violet-900/20 transition-colors"
          >
            <span className="text-xs font-medium text-violet-300 uppercase tracking-wider">{label}</span>
            {openSection === key ? <ChevronUp className="w-3.5 h-3.5 text-muted-foreground" /> : <ChevronDown className="w-3.5 h-3.5 text-muted-foreground" />}
          </button>
          <AnimatePresence>
            {openSection === key && (
              <motion.div
                initial={{ height: 0, opacity: 0 }}
                animate={{ height: "auto", opacity: 1 }}
                exit={{ height: 0, opacity: 0 }}
                className="overflow-hidden"
              >
                {content}
              </motion.div>
            )}
          </AnimatePresence>
        </div>
      ))}
    </motion.div>
  );
}

export function Home() {
  const { toast } = useToast();
  const { t } = useLang();
  const queryClient = useQueryClient();
  const { isSignedIn, isAdmin } = useAuth();
  const [authModalOpen, setAuthModalOpen] = useState(false);
  const [generatedImageUrl, setGeneratedImageUrl] = useState<string | null>(null);
  const [apiDebug, setApiDebug] = useState<ApiDebugInfo | null>(null);
  const [tokenError, setTokenError] = useState<{ expired: boolean; message: string } | null>(null);
  const [referenceImage, setReferenceImage] = useState<{ base64: string; mime: string; preview: string } | null>(null);
  const [isPrivate, setIsPrivate] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const { mutate: generateImage, isPending } = useGenerateImage();

  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      prompt: "",
      style: "realistic",
      aspectRatio: "1:1",
      model: "grok",
    },
  });

  const handleFileUpload = useCallback((file: File) => {
    if (!file.type.startsWith("image/")) {
      toast({ variant: "destructive", title: t.errorFormatTitle, description: t.errorFormatDesc });
      return;
    }
    const reader = new FileReader();
    reader.onload = (e) => {
      const dataUrl = e.target?.result as string;
      const base64 = dataUrl.split(",")[1];
      setReferenceImage({ base64, mime: file.type, preview: dataUrl });
    };
    reader.readAsDataURL(file);
  }, [toast, t]);

  const handleDrop = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    const file = e.dataTransfer.files[0];
    if (file) handleFileUpload(file);
  }, [handleFileUpload]);

  function onSubmit(values: FormValues) {
    if (!isSignedIn) {
      setAuthModalOpen(true);
      return;
    }
    setGeneratedImageUrl(null);
    setApiDebug(null);
    setTokenError(null);
    const resolution = values.resolution === "none" || !values.resolution ? undefined : values.resolution;
    generateImage(
      {
        data: {
          ...values as any,
          resolution,
          referenceImageBase64: referenceImage?.base64,
          referenceImageMime: referenceImage?.mime,
          isPrivate,
        },
      },
      {
        onSuccess: (data: any) => {
          setGeneratedImageUrl(data.imageUrl);
          setApiDebug(data.apiDebug);
          queryClient.invalidateQueries({ queryKey: getGetImageHistoryQueryKey() });
          if (data.tokenExpired) {
            setTokenError({ expired: true, message: data.error || t.tokenExpiredFallback });
          } else if (data.error) {
            setTokenError({ expired: false, message: data.error });
          }
        },
        onError: () => {
          toast({ variant: "destructive", title: t.errorGenTitle, description: t.errorGenDesc });
        },
      }
    );
  }

  const handleDownload = () => {
    if (!generatedImageUrl) return;
    const a = document.createElement("a");
    a.href = generatedImageUrl;
    a.download = "generated-image.jpg";
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
  };

  const selectedModel = form.watch("model") as string;
  const selectedModelInfo = t.models[selectedModel as keyof typeof t.models];

  return (
    <div className="container mx-auto px-4 py-8 max-w-7xl">
      <div className="grid grid-cols-1 lg:grid-cols-12 gap-8 items-start">
        {/* Left Form Panel */}
        <div className="lg:col-span-4 space-y-5 bg-card p-6 rounded-xl border border-border shadow-sm">
          <div>
            <h1 className="text-2xl font-bold mb-1">{t.canvasTitle}</h1>
            <p className="text-sm text-muted-foreground">{t.canvasSubtitle}</p>
          </div>

          <Form {...form}>
            <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
              {/* Prompt */}
              <FormField
                control={form.control}
                name="prompt"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>{t.promptLabel}</FormLabel>
                    <FormControl>
                      <Textarea
                        placeholder={t.promptPlaceholder}
                        className="resize-none h-28 focus-visible:ring-primary"
                        {...field}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />

              {/* Model Selection */}
              <FormField
                control={form.control}
                name="model"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>{t.modelLabel}</FormLabel>
                    <Select onValueChange={field.onChange} defaultValue={field.value}>
                      <FormControl>
                        <SelectTrigger>
                          <SelectValue placeholder={t.modelPlaceholder} />
                        </SelectTrigger>
                      </FormControl>
                      <SelectContent>
                        {MODEL_KEYS.map((key) => {
                          const m = t.models[key];
                          return (
                            <SelectItem key={key} value={key}>
                              <div className="flex items-center gap-2">
                                <span>{m.label}</span>
                                {m.badge && (
                                  <Badge variant="outline" className="text-[10px] px-1.5 py-0 h-4 border-primary/40 text-primary">
                                    {m.badge}
                                  </Badge>
                                )}
                              </div>
                            </SelectItem>
                          );
                        })}
                      </SelectContent>
                    </Select>
                    {selectedModelInfo && (
                      <p className="text-xs text-muted-foreground mt-1">{selectedModelInfo.desc}</p>
                    )}
                    <FormMessage />
                  </FormItem>
                )}
              />

              {/* Style + Ratio */}
              <div className="grid grid-cols-2 gap-3">
                <FormField
                  control={form.control}
                  name="style"
                  render={({ field }) => (
                    <FormItem>
                      <FormLabel>{t.styleLabel}</FormLabel>
                      <Select onValueChange={field.onChange} defaultValue={field.value}>
                        <FormControl>
                          <SelectTrigger>
                            <SelectValue placeholder={t.stylePlaceholder} />
                          </SelectTrigger>
                        </FormControl>
                        <SelectContent>
                          {STYLE_KEYS.map((key) => (
                            <SelectItem key={key} value={key}>
                              {STYLE_EMOJIS[key]} {t.styles[key]}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                      <FormMessage />
                    </FormItem>
                  )}
                />

                <FormField
                  control={form.control}
                  name="aspectRatio"
                  render={({ field }) => (
                    <FormItem>
                      <FormLabel>{t.ratioLabel}</FormLabel>
                      <Select onValueChange={field.onChange} defaultValue={field.value}>
                        <FormControl>
                          <SelectTrigger>
                            <SelectValue placeholder={t.ratioPlaceholder} />
                          </SelectTrigger>
                        </FormControl>
                        <SelectContent>
                          {ASPECT_RATIO_KEYS.map((key) => (
                            <SelectItem key={key} value={key}>
                              {key} <span className="text-muted-foreground text-xs">({t.ratios[key]})</span>
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                      <FormMessage />
                    </FormItem>
                  )}
                />
              </div>

              {/* Private toggle */}
              <div className="flex items-center justify-between py-2 px-3 rounded-lg bg-secondary/40 border border-border/50">
                <div className="flex items-center gap-2">
                  {isPrivate ? <Lock className="w-4 h-4 text-amber-400" /> : <Globe className="w-4 h-4 text-muted-foreground" />}
                  <div>
                    <p className="text-sm font-medium">{isPrivate ? (t.privateLabel ?? "私人記錄") : (t.publicLabel ?? "公開記錄")}</p>
                    <p className="text-xs text-muted-foreground">{isPrivate ? (t.privateDesc ?? "僅您本人可見") : (t.publicDesc ?? "所有人可見")}</p>
                  </div>
                </div>
                <button
                  type="button"
                  onClick={() => setIsPrivate(!isPrivate)}
                  className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none ${isPrivate ? "bg-amber-500" : "bg-muted"}`}
                >
                  <span className={`inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${isPrivate ? "translate-x-6" : "translate-x-1"}`} />
                </button>
              </div>

              {/* Resolution — only for Nano Banana models */}
              {NANO_BANANA_MODELS.has(selectedModel) && (
                <FormField
                  control={form.control}
                  name="resolution"
                  render={({ field }) => (
                    <FormItem>
                      <FormLabel className="flex items-center gap-1.5">
                        {t.resolutionLabel}
                        <Badge variant="outline" className="text-[10px] px-1.5 py-0 h-4 border-amber-400/40 text-amber-400">Nano Banana</Badge>
                      </FormLabel>
                      <Select onValueChange={field.onChange} value={field.value || ""}>
                        <FormControl>
                          <SelectTrigger>
                            <SelectValue placeholder={t.resolutionPlaceholder} />
                          </SelectTrigger>
                        </FormControl>
                        <SelectContent>
                          <SelectItem value="none">
                            <span className="text-muted-foreground">— {t.resolutionPlaceholder} —</span>
                          </SelectItem>
                          <SelectItem value="1K">
                            <div className="flex items-center gap-2">
                              <span className="font-semibold text-violet-300">1K</span>
                              <span className="text-xs text-muted-foreground">{t.resolutionDesc1K.replace("1K — ", "")}</span>
                            </div>
                          </SelectItem>
                          <SelectItem value="2K">
                            <div className="flex items-center gap-2">
                              <span className="font-semibold text-violet-300">2K</span>
                              <span className="text-xs text-muted-foreground">{t.resolutionDesc2K.replace("2K — ", "")}</span>
                            </div>
                          </SelectItem>
                          <SelectItem value="4K">
                            <div className="flex items-center gap-2">
                              <span className="font-semibold text-amber-400">4K</span>
                              <span className="text-xs text-muted-foreground">{t.resolutionDesc4K.replace("4K — ", "")}</span>
                            </div>
                          </SelectItem>
                        </SelectContent>
                      </Select>
                      <FormMessage />
                    </FormItem>
                  )}
                />
              )}

              {/* Reference Image Upload */}
              <div>
                <div className="text-sm font-medium mb-2 flex items-center gap-1.5">
                  <ImagePlus className="w-4 h-4" />
                  <span>{t.refImageLabel}</span>
                  <Badge variant="outline" className="text-[10px] px-1.5 py-0 h-4 border-violet-400/40 text-violet-400">{t.refImageBadge}</Badge>
                </div>

                {referenceImage ? (
                  <div className="relative rounded-lg overflow-hidden border border-border group">
                    <img src={referenceImage.preview} alt="reference" className="w-full h-32 object-cover" />
                    <div className="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
                      <Button
                        type="button"
                        variant="destructive"
                        size="sm"
                        onClick={() => setReferenceImage(null)}
                        className="gap-1.5"
                      >
                        <X className="w-3.5 h-3.5" />
                        {t.refImageRemove}
                      </Button>
                    </div>
                  </div>
                ) : (
                  <div
                    className="border-2 border-dashed border-border rounded-lg p-4 text-center cursor-pointer hover:border-primary/50 hover:bg-primary/5 transition-colors"
                    onClick={() => fileInputRef.current?.click()}
                    onDrop={handleDrop}
                    onDragOver={(e) => e.preventDefault()}
                  >
                    <Upload className="w-6 h-6 mx-auto mb-2 text-muted-foreground" />
                    <p className="text-xs text-muted-foreground">{t.refImageDrop}</p>
                    <p className="text-[11px] text-muted-foreground/60 mt-0.5">{t.refImageFormats}</p>
                  </div>
                )}
                <input
                  ref={fileInputRef}
                  type="file"
                  accept="image/*"
                  className="hidden"
                  onChange={(e) => {
                    const file = e.target.files?.[0];
                    if (file) handleFileUpload(file);
                  }}
                />
              </div>

              {isSignedIn ? (
                <Button
                  type="submit"
                  className="w-full h-12 text-lg font-medium shadow-lg shadow-primary/20 transition-all hover:shadow-primary/40"
                  disabled={isPending}
                >
                  {isPending ? (
                    <><Loader2 className="mr-2 h-5 w-5 animate-spin" />{t.btnGenerating}</>
                  ) : (
                    <><Sparkles className="mr-2 h-5 w-5" />{referenceImage ? t.btnImg2Img : t.btnGenerate}</>
                  )}
                </Button>
              ) : (
                <Button
                  type="submit"
                  variant="outline"
                  className="w-full h-12 text-lg font-medium border-primary/40 text-primary hover:bg-primary/10 hover:border-primary/70 transition-all"
                >
                  <LogIn className="mr-2 h-5 w-5" />
                  {t.navSignIn}
                </Button>
              )}
            </form>
          </Form>
        </div>

        {/* Right Panel */}
        <div className="lg:col-span-8 space-y-3">
          {/* Token error banner */}
          {tokenError && (
            <div className={`flex items-start gap-3 p-4 rounded-xl border text-sm ${
              tokenError.expired
                ? "bg-red-500/10 border-red-500/30 text-red-300"
                : "bg-amber-500/10 border-amber-500/30 text-amber-300"
            }`}>
              <AlertTriangle className="w-5 h-5 flex-shrink-0 mt-0.5" />
              <div className="flex-1 min-w-0">
                {tokenError.expired ? (
                  <>
                    <p className="font-semibold">{t.tokenExpiredTitle}</p>
                    <p className="mt-1 text-xs opacity-80">{t.tokenExpiredDesc}{" "}
                      {isAdmin
                        ? <Link href="/admin" className="underline font-medium">{t.tokenExpiredLink}</Link>
                        : <span>{t.tokenExpiredLink}</span>
                      }
                      {" "}{t.tokenExpiredSuffix}
                    </p>
                  </>
                ) : (
                  <>
                    <p className="font-semibold">{t.tokenErrorTitle}</p>
                    <p className="mt-1 text-xs opacity-80">{tokenError.message}</p>
                  </>
                )}
              </div>
              <button onClick={() => setTokenError(null)} className="opacity-60 hover:opacity-100 flex-shrink-0">
                <X className="w-4 h-4" />
              </button>
            </div>
          )}
          <div className="relative w-full aspect-square md:aspect-[16/9] lg:aspect-auto lg:h-[480px] bg-secondary/50 rounded-xl border border-border/50 overflow-hidden flex flex-col items-center justify-center">
            <AnimatePresence mode="wait">
              {isPending ? (
                <motion.div
                  key="loading"
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  exit={{ opacity: 0 }}
                  className="absolute inset-0 flex flex-col items-center justify-center bg-background/50 backdrop-blur-sm z-10"
                >
                  <div className="relative">
                    <div className="w-24 h-24 rounded-full border-4 border-primary/20 border-t-primary animate-spin" />
                    <div className="absolute inset-0 flex items-center justify-center">
                      <RefreshCw className="w-8 h-8 text-primary animate-pulse" />
                    </div>
                  </div>
                  <p className="mt-6 text-lg font-medium text-primary animate-pulse tracking-widest">
                    {t.loadingTitle}
                  </p>
                  <p className="mt-2 text-sm text-muted-foreground">
                    {selectedModelInfo?.label} — {t.loadingSubtitle}
                  </p>
                </motion.div>
              ) : generatedImageUrl ? (
                <motion.div
                  key="result"
                  initial={{ opacity: 0, scale: 0.95 }}
                  animate={{ opacity: 1, scale: 1 }}
                  className="relative w-full h-full group"
                >
                  <img
                    src={generatedImageUrl}
                    alt="Generated artwork"
                    className="w-full h-full object-contain"
                  />
                  <div className="absolute bottom-6 right-6 opacity-0 group-hover:opacity-100 transition-opacity">
                    <Button size="icon" className="h-12 w-12 rounded-full shadow-xl" onClick={handleDownload}>
                      <Download className="h-5 w-5" />
                    </Button>
                  </div>
                </motion.div>
              ) : (
                <motion.div
                  key="empty"
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  className="text-center text-muted-foreground"
                >
                  <div className="w-20 h-20 mx-auto mb-6 rounded-2xl bg-secondary flex items-center justify-center border border-border">
                    <Sparkles className="w-10 h-10 opacity-50" />
                  </div>
                  <p className="text-lg">{t.emptyTitle}</p>
                  <p className="text-sm mt-1 opacity-60">{t.emptySubtitle}</p>
                </motion.div>
              )}
            </AnimatePresence>
          </div>

          {apiDebug && <ApiDebugPanel debug={apiDebug} />}
        </div>
      </div>
      <AuthModal open={authModalOpen} onOpenChange={setAuthModalOpen} />
    </div>
  );
}
