'use client';

import { useState, useCallback, useRef, useMemo, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Label } from '@/components/ui/label';
import { Slider } from '@/components/ui/slider';
import { Badge } from '@/components/ui/badge';
import { useAuth } from '@/lib/auth-store';
import { useCustomApiKeys } from '@/lib/custom-api-store';
import { useManagedSystemApis } from '@/lib/managed-model-store';
import {
  ASPECT_RATIOS,
  RESOLUTION_OPTIONS,
  STYLE_PRESETS,
  isCustomModel,
  isSystemModel,
  getCustomKeyId,
  getSystemApiId,
  buildCustomModelId,
  buildSystemModelId,
  calcImageCredits,
  resolveImageSize,
  resolveCustomApiImageSize,
} from '@/lib/model-config';
import { Sparkles, Loader2, Download, Wand2, Image as ImageIcon, History, ChevronDown, ChevronUp, Plus, KeyRound, Share2 } from 'lucide-react';
import { useCreationHistory, getCreationMode, isPlaceholder, shareToGallery, isUrlPublished, type CreationRecord } from '@/lib/creation-history-store';
import { addCreditRecord } from '@/lib/credit-records-store';
import { downloadFile } from '@/lib/utils';
import { runGenerationFinalCountdown, runGenerationJob, type GenerationJobStatus } from '@/lib/generation-job-client';
import { useSiteConfig } from '@/lib/site-config';
import { toast } from 'sonner';
import Link from 'next/link';
import { ImageLightbox } from '@/components/lightbox';
import { CreationDetailDialog } from '@/components/creation-detail-dialog';
import { GenerationErrorPanel, createGenerationError, type GenerationErrorState } from '@/components/create/generation-error-panel';
import { ExpandablePromptTextarea } from '@/components/create/expandable-prompt-textarea';
import { GenerationLoadingPanel } from '@/components/create/generation-loading-panel';

const TEXT_TO_IMAGE_DRAFT_KEY = 'miaojing:text-to-image-draft';

export function TextToImagePanel() {
  const { user, accessToken } = useAuth();
  const { config: siteConfig } = useSiteConfig();
  const membershipEnabled = siteConfig.membershipEnabled !== false;
  const { imageKeys, textKeys } = useCustomApiKeys();
  const managedSystemApis = useManagedSystemApis();

  // Form state
  const [prompt, setPrompt] = useState('');
  const [negativePrompt, setNegativePrompt] = useState('');
  const [aspectRatio, setAspectRatio] = useState('1:1');
  const [resolution, setResolution] = useState('2K');
  const [count, setCount] = useState(1);
  const [guidanceScale, setGuidanceScale] = useState(7);

  // Generation state
  const [generating, setGenerating] = useState(false);
  const [generationStartedAt, setGenerationStartedAt] = useState(() => Date.now());
  const [generationJobStatus, setGenerationJobStatus] = useState<GenerationJobStatus | null>(null);
  const [finalCountdownSeconds, setFinalCountdownSeconds] = useState<number | null>(null);
  const [results, setResults] = useState<string[]>([]);
  const [generationError, setGenerationError] = useState<GenerationErrorState | null>(null);
  const [optimizing, setOptimizing] = useState(false);

  // History state
  const { records, add: addRecord } = useCreationHistory();
  const [showHistory, setShowHistory] = useState(false);
  const imageHistory = records.filter(r => getCreationMode(r) === 'text2img');

  // Lightbox state
  const [lightboxSrc, setLightboxSrc] = useState<string | null>(null);

  // History detail dialog
  const [selectedHistoryRecord, setSelectedHistoryRecord] = useState<CreationRecord | null>(null);

  const applyPromptDraft = useCallback((draft: unknown) => {
    if (!draft || typeof draft !== 'object') return;
    const data = draft as { prompt?: unknown; negativePrompt?: unknown };
    if (typeof data.prompt === 'string') setPrompt(data.prompt);
    if (typeof data.negativePrompt === 'string') setNegativePrompt(data.negativePrompt);
  }, []);

  useEffect(() => {
    try {
      const raw = window.localStorage.getItem(TEXT_TO_IMAGE_DRAFT_KEY);
      if (raw) applyPromptDraft(JSON.parse(raw));
    } catch {
      // Ignore malformed local draft data.
    }

    const handleDraft = (event: Event) => {
      applyPromptDraft((event as CustomEvent).detail);
    };
    window.addEventListener('miaojing:text-to-image-draft', handleDraft);
    return () => window.removeEventListener('miaojing:text-to-image-draft', handleDraft);
  }, [applyPromptDraft]);

  // System APIs
  const systemImageApis = managedSystemApis.filter(api => api.type === 'image' && api.isActive);
  const systemTextApis = managedSystemApis.filter(api => api.type === 'text' && api.isActive);

  // Model options — only system + custom (no builtin)
  const modelOptions = useMemo(() => [
    ...systemImageApis.map(api => ({ id: buildSystemModelId(api.id), label: `${api.name} (系统)`, group: '系统模型' })),
    ...imageKeys.map(k => ({ id: buildCustomModelId(k.id), label: `${k.modelName || k.provider} (自定义)`, group: '自定义模型' })),
  ], [systemImageApis, imageKeys]);

  const hasModels = modelOptions.length > 0;

  // Default to first available: system > custom; prefer custom if available
  const [selectedModel, setSelectedModel] = useState('');
  useEffect(() => {
    if (modelOptions.length > 0 && !modelOptions.find(o => o.id === selectedModel)) {
      // Prefer custom model as default
      const customOpt = modelOptions.find(o => o.group === '自定义模型');
      setSelectedModel(customOpt ? customOpt.id : modelOptions[0].id);
    }
  }, [modelOptions, selectedModel]);

  // Text model options for prompt optimization — memoized
  const textModelOptions = useMemo(() => [
    ...textKeys.map(k => ({ id: buildCustomModelId(k.id), label: `${k.modelName || k.provider} (自定义)`, config: { customApiKeyId: k.id, modelName: k.modelName } })),
    ...systemTextApis.map(api => ({ id: buildSystemModelId(api.id), label: `${api.name} (系统)`, config: { systemApiId: api.id, modelName: api.modelName } })),
  ], [textKeys, systemTextApis]);

  const getCurrentModelLabel = useCallback(() => {
    if (isCustomModel(selectedModel)) {
      const key = imageKeys.find(k => k.id === getCustomKeyId(selectedModel));
      return key?.modelName || key?.provider || '自定义模型';
    }
    if (isSystemModel(selectedModel)) {
      const api = systemImageApis.find(a => a.id === getSystemApiId(selectedModel));
      return api?.name || '系统模型';
    }
    return 'AI模型';
  }, [selectedModel, imageKeys, systemImageApis]);

  // Prompt optimization
  const handleOptimizePrompt = useCallback(async () => {
    if (!prompt.trim()) { toast.error('请先输入创作描述'); return; }
    if (!user || !accessToken) { toast.error('请先登录后再优化提示词'); return; }
    if (textModelOptions.length === 0) { toast.error('未配置多模态模型，请先在API设置中添加多模态模型'); return; }

    setOptimizing(true);
    try {
      const textModel = textModelOptions[0];
      const modelLabel = getCurrentModelLabel();
      const res = await fetch('/api/generate/suggest-prompt', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}),
        },
        body: JSON.stringify({
          prompt: prompt.trim(),
          modelName: textModel.config.modelName,
          customApiConfig: textModel.config,
          systemPrefix: `针对${modelLabel}图片生成优化提示词`,
        }),
      });
      const data = await res.json().catch(() => ({}));
      if (res.ok) {
        if (data.prompt) {
          setPrompt(data.prompt);
          if (typeof data.negativePrompt === 'string' && data.negativePrompt.trim()) {
            setNegativePrompt(data.negativePrompt.trim());
          }
          toast.success('提示词已优化');
        }
        else toast.error(data.error || '优化失败');
      } else toast.error(data.error || '提示词优化请求失败');
    } catch (err: unknown) {
      if (err instanceof DOMException && err.name === 'AbortError') {
        toast.error('请求超时，请尝试减少生成数量或降低分辨率');
      } else {
        toast.error(err instanceof Error ? err.message : '网络错误，请重试');
      }
    }
    finally { setOptimizing(false); }
  }, [prompt, user, accessToken, textModelOptions, getCurrentModelLabel]);

  const credits = calcImageCredits(selectedModel, resolution, aspectRatio, count);

  // Generate
  const handleGenerate = useCallback(async () => {
    if (!prompt.trim()) { toast.error('请输入创作描述'); return; }
    if (!user) { toast.error('请先登录'); return; }

    setGenerationError(null);
    setResults([]);
    setGenerationStartedAt(Date.now());
    setGenerationJobStatus(null);
    setFinalCountdownSeconds(null);
    setGenerating(true);
    try {
      // Keep custom/system API size aligned with the selected resolution.
      const useCustomApiSize = isCustomModel(selectedModel) || isSystemModel(selectedModel);
      const resolvedSize = useCustomApiSize
        ? resolveCustomApiImageSize(aspectRatio, resolution)
        : resolveImageSize(aspectRatio, resolution);

      let requestBody: Record<string, unknown> = {
        prompt: prompt.trim(),
        negativePrompt: negativePrompt.trim() || undefined,
        model: selectedModel,
        aspectRatio,
        resolution,
        size: resolvedSize,
        count,
        guidanceScale,
      };

      if (isCustomModel(selectedModel)) {
        const key = imageKeys.find(k => k.id === getCustomKeyId(selectedModel));
        if (key) {
          requestBody = { ...requestBody, model: key.modelName, customApiConfig: { customApiKeyId: key.id, modelName: key.modelName } };
        }
      } else if (isSystemModel(selectedModel)) {
        const api = systemImageApis.find(a => a.id === getSystemApiId(selectedModel));
        if (api) {
          requestBody = { ...requestBody, model: api.modelName, customApiConfig: { systemApiId: api.id, modelName: api.modelName } };
        }
      }

      // Fetch with 180s timeout for image generation
      const data = await runGenerationJob<{ images?: string[]; error?: string }>(
        'image',
        requestBody,
        { timeoutMs: 300_000, onStatus: setGenerationJobStatus },
      );
      await runGenerationFinalCountdown(setFinalCountdownSeconds, 3);
      if (data.images && data.images.length > 0) {
        setResults(data.images);
        setGenerationError(null);
        for (const url of data.images) {
          addRecord({
            type: 'image', url, prompt: prompt.trim(),
            negativePrompt: negativePrompt.trim() || undefined,
            model: selectedModel,
            modelLabel: getCurrentModelLabel(),
            isCustomModel: isCustomModel(selectedModel) || isSystemModel(selectedModel),
            params: { creationMode: 'text2img', aspectRatio, resolution, count, guidanceScale },
          });
        }
        toast.success(`生成 ${data.images.length} 张图片`);
        // Record credit consumption (custom/system models cost 0 credits)
        if (membershipEnabled && credits > 0 && user) {
          const currentCredits = typeof user.creditsBalance === 'number' ? user.creditsBalance : 0;
          addCreditRecord({
            type: 'consume',
            amount: -credits,
            balanceAfter: Math.max(0, currentCredits - credits),
            description: `文生图 - ${getCurrentModelLabel()}`,
          });
        }
      } else {
        setGenerationError(createGenerationError(data.error || '图片生成失败'));
      }
    } catch (err: unknown) {
      if (err instanceof DOMException && err.name === 'AbortError') {
        setGenerationError(createGenerationError('请求超时，请尝试减少生成数量或降低分辨率'));
      } else {
        setGenerationError(createGenerationError(err instanceof Error ? err.message : '网络错误，请重试'));
      }
    }
    finally { setGenerating(false); setFinalCountdownSeconds(null); }
  }, [prompt, negativePrompt, selectedModel, aspectRatio, resolution, count, guidanceScale, user, imageKeys, systemImageApis, getCurrentModelLabel, addRecord, credits, membershipEnabled]);

  // Download
  const handleDownload = useCallback(async (url: string, index: number) => {
    const result = await downloadFile(url, `miaojing-${Date.now()}-${index}.png`);
    if (!result.ok) toast.error(result.error || '下载失败');
  }, []);

  const handleShareToGallery = useCallback((url: string) => {
    if (isUrlPublished(url)) {
      toast.info('该作品已分享到画廊');
      return;
    }
    shareToGallery({
      type: 'image',
      url,
      prompt: prompt.trim(),
      model: selectedModel,
      modelLabel: getCurrentModelLabel(),
    });
    toast.success('已分享到画廊');
  }, [prompt, selectedModel, getCurrentModelLabel]);

  return (
    <div className="grid min-h-[600px] grid-cols-1 gap-6 xl:grid-cols-[minmax(0,4fr)_minmax(0,6fr)]">
      {/* Left: Settings (scrollable) */}
      <div className="min-w-0 space-y-5 overflow-y-auto max-h-[calc(100vh-200px)] pr-2">
        {/* Model Selection */}
        <div className="space-y-2">
          <Label>生成模型</Label>
          {hasModels ? (
            <Select value={selectedModel} onValueChange={setSelectedModel}>
              <SelectTrigger><SelectValue placeholder="选择模型" /></SelectTrigger>
              <SelectContent>
                {modelOptions.map(opt => (
                  <SelectItem key={opt.id} value={opt.id}>{opt.label}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          ) : (
            <div className="liquid-glass-soft rounded-2xl border-dashed p-4 text-center space-y-2">
              <KeyRound className="h-8 w-8 mx-auto text-muted-foreground/50" />
              <p className="text-sm text-muted-foreground">暂无可用模型</p>
              <Link href="/profile" className="text-sm text-primary hover:underline">
                前往 我的 → API 中添加API密钥
              </Link>
            </div>
          )}
        </div>

        {/* Prompt */}
        <div className="space-y-2">
          <div className="flex items-center justify-between">
            <Label>创作描述</Label>
            {textModelOptions.length > 0 && (
              <Button variant="ghost" size="sm" className="h-7 gap-1.5 text-xs text-primary hover:text-primary" onClick={handleOptimizePrompt} disabled={optimizing || !prompt.trim()}>
                {optimizing ? <Loader2 className="h-3 w-3 animate-spin" /> : <Wand2 className="h-3 w-3" />}
                {optimizing ? '优化中...' : '优化提示词'}
              </Button>
            )}
          </div>
          <ExpandablePromptTextarea
            title="创作描述"
            placeholder="描述你想要生成的图片，越详细效果越好..."
            rows={4}
            className="h-32 resize-none overflow-y-auto"
            value={prompt}
            onValueChange={setPrompt}
          />
          <div className="flex flex-wrap gap-1.5">
            {STYLE_PRESETS.map(s => (
              <Badge key={s} variant="outline" className="cursor-pointer hover:bg-primary/10 text-xs" onClick={() => setPrompt(prev => prev ? `${prev}, ${s}` : s)}>
                {s}
              </Badge>
            ))}
          </div>
        </div>

        {/* Negative Prompt */}
        <div className="space-y-2">
          <Label>负面提示词 <span className="text-muted-foreground text-xs">(可选)</span></Label>
          <ExpandablePromptTextarea
            title="负面提示词"
            placeholder="不希望出现的元素..."
            rows={2}
            className="h-24 resize-none overflow-y-auto"
            value={negativePrompt}
            onValueChange={setNegativePrompt}
          />
        </div>

        {/* Aspect Ratio + Resolution */}
        <div className="grid grid-cols-2 gap-3">
          <div className="space-y-2">
            <Label>画面比例</Label>
            <Select value={aspectRatio} onValueChange={setAspectRatio}>
              <SelectTrigger><SelectValue /></SelectTrigger>
              <SelectContent>
                {ASPECT_RATIOS.map(ar => (
                  <SelectItem key={ar.value} value={ar.value}>{ar.label}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <div className="space-y-2">
            <Label>分辨率</Label>
            <Select value={resolution} onValueChange={setResolution}>
              <SelectTrigger><SelectValue /></SelectTrigger>
              <SelectContent>
                {RESOLUTION_OPTIONS.map(r => (
                  <SelectItem key={r.value} value={r.value}>{r.label}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        </div>

        {/* Guidance Scale */}
        <div className="space-y-2">
          <div className="flex items-center justify-between">
            <Label>引导系数</Label>
            <span className="text-xs text-muted-foreground">{guidanceScale}</span>
          </div>
          <Slider value={[guidanceScale]} onValueChange={([v]) => setGuidanceScale(v)} min={1} max={20} step={1} />
          <p className="text-xs text-muted-foreground">低=画面更自由自然，高=更严格贴合提示词</p>
        </div>

        {/* Count */}
        <div className="space-y-2">
          <Label>生成数量</Label>
          <Select value={String(count)} onValueChange={v => setCount(Number(v))}>
            <SelectTrigger><SelectValue /></SelectTrigger>
            <SelectContent>
              <SelectItem value="1">1 张</SelectItem>
              <SelectItem value="2">2 张</SelectItem>
              <SelectItem value="4">4 张</SelectItem>
            </SelectContent>
          </Select>
        </div>

        {/* Generate Button */}
        <Button className="w-full gap-2" size="lg" onClick={handleGenerate} disabled={generating || !hasModels}>
          {generating ? (<><Loader2 className="h-4 w-4 animate-spin" />生成中...</>) : (<><Sparkles className="h-4 w-4" />生成图片 {membershipEnabled && credits > 0 && `(${credits} 积分)`}</>)}
        </Button>
      </div>

      {/* Right: Results + History (flex-1, takes remaining space) */}
      <div className="min-w-0 space-y-4">
        {/* Results area */}
        {generating ? (
          <div className="liquid-glass min-h-[300px] overflow-hidden rounded-2xl border-dashed text-muted-foreground">
            <GenerationLoadingPanel
              startedAt={generationStartedAt}
              estimateSeconds={90}
              jobStatus={generationJobStatus}
              finalCountdownSeconds={finalCountdownSeconds}
              title="正在生成图片"
            />
          </div>
        ) : generationError ? (
          <GenerationErrorPanel error={generationError} />
        ) : results.length > 0 ? (
          <div className="space-y-3">
            <div className="flex items-center gap-2 text-sm font-medium"><ImageIcon className="h-4 w-4" />生成结果</div>
            <div className="grid grid-cols-2 gap-3">
              {results.map((url, i) => (
                <div key={i} className="liquid-glass-soft group relative overflow-hidden rounded-2xl">
                  {/* eslint-disable-next-line @next/next/no-img-element */}
                  <img
                    src={url}
                    alt={`生成结果 ${i + 1}`}
                    className="w-full aspect-square object-cover cursor-zoom-in"
                    onDoubleClick={() => setLightboxSrc(url)}
                  />
                  <div className="absolute inset-0 bg-black/0 group-hover:bg-black/30 transition-colors flex items-center justify-center gap-2 opacity-0 group-hover:opacity-100">
                    <Button size="sm" variant="secondary" className="gap-1" onClick={() => setLightboxSrc(url)}><ImageIcon className="h-3.5 w-3.5" />预览</Button>
                    <Button size="sm" variant="secondary" className="gap-1" onClick={() => handleShareToGallery(url)}><Share2 className="h-3.5 w-3.5" />分享</Button>
                    <Button size="sm" variant="secondary" className="gap-1" onClick={() => handleDownload(url, i)}><Download className="h-3.5 w-3.5" />下载</Button>
                  </div>
                </div>
              ))}
            </div>
          </div>
        ) : (
          <div className="liquid-glass flex min-h-[300px] flex-col items-center justify-center rounded-2xl border-dashed py-24 text-muted-foreground">
            <ImageIcon className="h-14 w-14 mb-3 opacity-20" />
            <p className="text-sm">生成结果将显示在这里</p>
          </div>
        )}

        {/* History */}
        {imageHistory.length > 0 && (
          <div className="space-y-2">
            <button className="flex items-center gap-2 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors" onClick={() => setShowHistory(!showHistory)}>
              <History className="h-4 w-4" />历史创作 ({imageHistory.length})
              {showHistory ? <ChevronUp className="h-3.5 w-3.5" /> : <ChevronDown className="h-3.5 w-3.5" />}
            </button>
            {showHistory && (
              <div className="grid grid-cols-3 gap-2 max-h-[400px] overflow-y-auto">
                {imageHistory.map(record => (
                  <div
                    key={record.id}
                    className="liquid-glass-soft group relative cursor-pointer overflow-hidden rounded-xl"
                    onClick={() => setSelectedHistoryRecord(record)}
                  >
                    {isPlaceholder(record.url) ? (
                      <div className="w-full aspect-square flex items-center justify-center"><ImageIcon className="h-6 w-6 text-muted-foreground/30" /></div>
                    ) : (
                      /* eslint-disable-next-line @next/next/no-img-element */
                      <img src={record.url} alt={record.prompt?.slice(0, 20) || '历史记录'} className="w-full aspect-square object-cover" />
                    )}
                    <div className="absolute inset-0 bg-black/0 group-hover:bg-black/40 transition-colors flex items-end p-1.5 opacity-0 group-hover:opacity-100">
                      <p className="text-xs text-white line-clamp-2">{record.prompt}</p>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>
        )}
      </div>

      {/* Lightbox */}
      <ImageLightbox src={lightboxSrc || ''} open={!!lightboxSrc} onClose={() => setLightboxSrc(null)} />

      {/* History Detail Dialog */}
      <CreationDetailDialog
        record={selectedHistoryRecord}
        open={!!selectedHistoryRecord}
        onClose={() => setSelectedHistoryRecord(null)}
      />
    </div>
  );
}
