"use client";

/**
 * ImageLayoutTabs.tsx — 이미지 컴포넌트 설정 탭
 *
 * [역할]
 * - 모달 내 이미지 핵심 설정: 업로드 / 자르기(Crop) / 맞춤 방식 / 캡션
 * - 시각 스타일(투명도·모서리·회전 등)은 우측 패널에서 관리
 */

import React, { useState, useRef, useMemo, useCallback } from "react";
import ReactCrop, { type Crop, type PixelCrop } from "react-image-crop";
import "react-image-crop/dist/ReactCrop.css";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Button } from "@/components/ui/button";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Upload,
  Image as ImageIcon,
  Loader2,
  Trash2,
  Link,
  Crop as CropIcon,
  RotateCcw,
  AlignCenter,
} from "lucide-react";
import { useReportDesigner } from "@/contexts/ReportDesignerContext";
import { reportApi } from "@/lib/api/reportApi";
import { getFullImageUrl } from "@/lib/api/client";
import { useToast } from "@/hooks/use-toast";
import { Section as SharedSection, TabContent, Field, FieldGroup, Grid, InfoBox } from "./shared";
import type { ComponentConfig } from "@/types/report";

interface ImageLayoutTabsProps {
  component: ComponentConfig;
}

const OBJECT_FIT_OPTIONS = [
  { value: "contain", label: "비율 유지 (포함)", desc: "전체가 보이도록 축소" },
  { value: "cover", label: "영역 채우기", desc: "꽉 채우고 넘침 잘림" },
  { value: "fill", label: "늘리기", desc: "비율 무시 영역 맞춤" },
  { value: "none", label: "원본 크기", desc: "원본 그대로 표시" },
] as const;

export function ImageLayoutTabs({ component }: ImageLayoutTabsProps) {
  const { updateComponent } = useReportDesigner();
  const [uploadingImage, setUploadingImage] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const { toast } = useToast();

  const update = useCallback(
    (updates: Partial<ComponentConfig>) => {
      updateComponent(component.id, updates);
    },
    [component.id, updateComponent],
  );

  const handleImageUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    if (!file.type.startsWith("image/")) {
      toast({ title: "오류", description: "이미지 파일만 업로드 가능합니다.", variant: "destructive" });
      return;
    }

    if (file.size > 10 * 1024 * 1024) {
      toast({ title: "오류", description: "파일 크기는 10MB 이하여야 합니다.", variant: "destructive" });
      return;
    }

    try {
      setUploadingImage(true);
      const result = await reportApi.uploadImage(file);
      if (result.success) {
        update({
          imageUrl: result.data.fileUrl,
          imageCropX: undefined,
          imageCropY: undefined,
          imageCropWidth: undefined,
          imageCropHeight: undefined,
        });
        toast({ title: "성공", description: "이미지가 업로드되었습니다." });
      }
    } catch {
      toast({ title: "오류", description: "이미지 업로드 중 오류가 발생했습니다.", variant: "destructive" });
    } finally {
      setUploadingImage(false);
      if (fileInputRef.current) fileInputRef.current.value = "";
    }
  };

  const handleRemoveImage = () => {
    update({ imageUrl: "", imageCropX: undefined, imageCropY: undefined, imageCropWidth: undefined, imageCropHeight: undefined });
    toast({ title: "알림", description: "이미지가 제거되었습니다." });
  };

  const previewUrl = useMemo(() => {
    if (!component.imageUrl) return null;
    return getFullImageUrl(component.imageUrl);
  }, [component.imageUrl]);

  return (
    <TabContent>
      {/* 이미지 업로드 */}
      <SharedSection emphasis icon={<Upload className="h-3.5 w-3.5" />} title="이미지 소스">
        <FieldGroup>
          <Field label="이미지 파일" help="JPG, PNG, GIF, WEBP 파일을 업로드하세요 (최대 10MB)">
            <div className="flex gap-4">
              <div className="flex h-[120px] w-[140px] shrink-0 items-center justify-center overflow-hidden rounded-lg border-2 border-dashed border-blue-200 bg-white">
                {previewUrl ? (
                  <img src={previewUrl} alt="미리보기" className="h-full w-full object-contain" />
                ) : (
                  <div className="flex flex-col items-center gap-1 text-gray-400">
                    <ImageIcon className="h-8 w-8" />
                    <span className="text-xs">미리보기</span>
                  </div>
                )}
              </div>
              <div className="flex flex-1 flex-col justify-center gap-2">
                <input
                  ref={fileInputRef}
                  type="file"
                  accept="image/*"
                  onChange={handleImageUpload}
                  className="hidden"
                  disabled={uploadingImage}
                />
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  onClick={() => fileInputRef.current?.click()}
                  disabled={uploadingImage}
                  className="h-9 w-full text-xs"
                >
                  {uploadingImage ? (
                    <><Loader2 className="mr-1.5 h-3.5 w-3.5 animate-spin" />업로드 중...</>
                  ) : (
                    <><Upload className="mr-1.5 h-3.5 w-3.5" />{component.imageUrl ? "이미지 변경" : "이미지 업로드"}</>
                  )}
                </Button>
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  onClick={handleRemoveImage}
                  disabled={!component.imageUrl}
                  className="h-9 w-full text-xs text-red-500 hover:bg-red-50 hover:text-red-600 disabled:text-gray-300"
                >
                  <Trash2 className="mr-1.5 h-3.5 w-3.5" />이미지 제거
                </Button>
              </div>
            </div>
          </Field>
          {component.imageUrl && (
            <InfoBox variant="blue">
              <p className="truncate">
                <Link className="mr-1 inline h-3 w-3" />
                {component.imageUrl}
              </p>
            </InfoBox>
          )}
        </FieldGroup>
      </SharedSection>

      {/* 이미지 자르기 */}
      {previewUrl && (
        <SharedSection icon={<CropIcon className="h-3.5 w-3.5" />} title="이미지 자르기 (크롭)">
          <ImageCropEditor
            imageUrl={previewUrl}
            component={component}
            onUpdate={update}
          />
        </SharedSection>
      )}

      {/* 표시 방식 */}
      <SharedSection icon={<AlignCenter className="h-3.5 w-3.5" />} title="표시 방식">
        <FieldGroup>
          <Field label="이미지 맞춤 방식">
            <Select
              value={component.objectFit || "contain"}
              onValueChange={(v) => update({ objectFit: v as ComponentConfig["objectFit"] })}
            >
              <SelectTrigger className="h-9 text-sm">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {OBJECT_FIT_OPTIONS.map((opt) => (
                  <SelectItem key={opt.value} value={opt.value}>
                    <span>{opt.label}</span>
                    <span className="ml-1.5 text-[11px] text-gray-400">{opt.desc}</span>
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </Field>
          <Field label="대체 텍스트 (alt)">
            <Input
              value={component.imageAlt || ""}
              onChange={(e) => update({ imageAlt: e.target.value })}
              placeholder="이미지 설명 (접근성)"
              className="h-9 text-sm"
            />
          </Field>
        </FieldGroup>
      </SharedSection>

      {/* 캡션 */}
      <SharedSection icon={<ImageIcon className="h-3.5 w-3.5" />} title="캡션">
        <FieldGroup>
          <Field label="캡션 텍스트" help="이미지 아래에 설명 텍스트를 표시합니다">
            <Input
              value={component.imageCaption || ""}
              onChange={(e) => update({ imageCaption: e.target.value })}
              placeholder="이미지에 표시할 설명 텍스트"
              className="h-9 text-sm"
            />
          </Field>
          {component.imageCaption && (
            <Grid cols={2}>
              <Field label="위치">
                <Select
                  value={component.imageCaptionPosition || "bottom"}
                  onValueChange={(v) => update({ imageCaptionPosition: v as "top" | "bottom" })}
                >
                  <SelectTrigger className="h-9 text-sm"><SelectValue /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="top">상단</SelectItem>
                    <SelectItem value="bottom">하단</SelectItem>
                  </SelectContent>
                </Select>
              </Field>
              <Field label="정렬">
                <Select
                  value={component.imageCaptionAlign || "center"}
                  onValueChange={(v) => update({ imageCaptionAlign: v as "left" | "center" | "right" })}
                >
                  <SelectTrigger className="h-9 text-sm"><SelectValue /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="left">왼쪽</SelectItem>
                    <SelectItem value="center">가운데</SelectItem>
                    <SelectItem value="right">오른쪽</SelectItem>
                  </SelectContent>
                </Select>
              </Field>
            </Grid>
          )}
        </FieldGroup>
      </SharedSection>

      <InfoBox variant="gray">
        투명도, 테두리, 모서리, 회전 등 스타일 설정은 우측 패널에서 변경할 수 있습니다.
      </InfoBox>
    </TabContent>
  );
}

/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 * 이미지 자르기(Crop) 에디터
 * ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */

interface ImageCropEditorProps {
  imageUrl: string;
  component: ComponentConfig;
  onUpdate: (updates: Partial<ComponentConfig>) => void;
}

function ImageCropEditor({ imageUrl, component, onUpdate }: ImageCropEditorProps) {
  const imgRef = useRef<HTMLImageElement>(null);
  const hasCrop = component.imageCropWidth != null && component.imageCropHeight != null;

  const [crop, setCrop] = useState<Crop | undefined>(() => {
    if (hasCrop) {
      return {
        unit: "%" as const,
        x: component.imageCropX ?? 0,
        y: component.imageCropY ?? 0,
        width: component.imageCropWidth ?? 100,
        height: component.imageCropHeight ?? 100,
      };
    }
    return undefined;
  });

  const handleCropComplete = useCallback(
    (_pixelCrop: PixelCrop, percentCrop: Crop) => {
      if (percentCrop.width < 1 || percentCrop.height < 1) return;
      onUpdate({
        imageCropX: Math.round(percentCrop.x * 100) / 100,
        imageCropY: Math.round(percentCrop.y * 100) / 100,
        imageCropWidth: Math.round(percentCrop.width * 100) / 100,
        imageCropHeight: Math.round(percentCrop.height * 100) / 100,
      });
    },
    [onUpdate],
  );

  const handleResetCrop = () => {
    setCrop(undefined);
    onUpdate({
      imageCropX: undefined,
      imageCropY: undefined,
      imageCropWidth: undefined,
      imageCropHeight: undefined,
    });
  };

  return (
    <div className="space-y-3">
      <div className="overflow-hidden rounded-lg border border-gray-200 bg-gray-50">
        <ReactCrop
          crop={crop}
          onChange={(_, percentCrop) => setCrop(percentCrop)}
          onComplete={handleCropComplete}
        >
          <img
            ref={imgRef}
            src={imageUrl}
            alt="자르기 편집"
            style={{ maxWidth: "100%", maxHeight: 300, display: "block" }}
          />
        </ReactCrop>
      </div>
      <div className="flex items-center justify-between">
        <p className="text-[11px] text-gray-400">
          {hasCrop
            ? `자르기 영역: ${Math.round(component.imageCropWidth ?? 0)}% x ${Math.round(component.imageCropHeight ?? 0)}%`
            : "드래그하여 자르기 영역을 지정하세요"}
        </p>
        {hasCrop && (
          <Button
            type="button"
            variant="ghost"
            size="sm"
            onClick={handleResetCrop}
            className="h-7 text-xs text-gray-500"
          >
            <RotateCcw className="mr-1 h-3 w-3" />초기화
          </Button>
        )}
      </div>
    </div>
  );
}

export function getShadowStyle(shadow: string): string {
  switch (shadow) {
    case "sm": return "0 1px 2px rgba(0,0,0,0.05)";
    case "md": return "0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1)";
    case "lg": return "0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)";
    default: return "none";
  }
}
