'use client';

import React, { useEffect, useState, ReactNode, useCallback } from 'react';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { toast } from 'sonner';
import { printArea } from '@/lib/print-utils';
import { DocumentToolbar } from './DocumentToolbar';
import { DocumentContent } from './DocumentContent';
import { useZoom, useDrag } from './hooks';
import { mergeWithPreset } from '../presets';
import {
  DocumentViewerProps,
  ActionType,
  DocumentFeatures,
} from '../types';
import { getTodayString } from '@/lib/utils/date';

/**
 * 문서 뷰어 (Shell)
 *
 * 사용법 1: Config 기반
 * ```tsx
 * <DocumentViewer
 *   config={importInspectionConfig}
 *   data={inspectionData}
 *   open={isOpen}
 *   onOpenChange={setIsOpen}
 * />
 * ```
 *
 * 사용법 2: 개별 props
 * ```tsx
 * <DocumentViewer
 *   title="수입검사 성적서"
 *   preset="inspection"
 *   open={isOpen}
 *   onOpenChange={setIsOpen}
 *   onPrint={handlePrint}
 * >
 *   <ImportInspectionDocument data={data} />
 * </DocumentViewer>
 * ```
 */
export function DocumentViewer({
  // Config
  config,

  // 개별 props
  title: propTitle,
  subtitle,
  preset: propPreset,
  features: propFeatures,
  actions: propActions,

  // 데이터
  data,

  // PDF 메타 정보
  pdfMeta,

  // 액션 핸들러
  onPrint: propOnPrint,
  onDownload,
  onEdit,
  onDelete,
  onSubmit,
  onApprove,
  onReject,
  onCopy,
  onPdf,
  onEmail,
  onFax,
  onKakao,

  // 모달 제어
  open = false,
  onOpenChange,

  // 정적 모드용 children
  children,

  // 툴바 확장
  toolbarExtra,
}: DocumentViewerProps) {
  // Config 또는 개별 props에서 값 추출
  const title = config?.title || propTitle || '문서';
  const preset = config?.preset || propPreset;

  // 프리셋과 커스텀 설정 병합
  const merged = mergeWithPreset(
    preset,
    config?.features || propFeatures,
    config?.actions || propActions
  );

  const features: DocumentFeatures = merged.features;
  const actions: ActionType[] = merged.actions;

  // 로딩 상태
  const [loadingAction, setLoadingAction] = useState<ActionType | null>(null);

  // 줌 훅
  const zoomBase = useZoom();

  // 드래그 훅
  const drag = useDrag({ enabled: features.drag !== false && zoomBase.zoom > 100 });

  // 맞춤 클릭 시 드래그 위치도 함께 리셋
  const zoom = {
    ...zoomBase,
    zoomReset: () => {
      zoomBase.zoomReset();
      drag.resetPosition();
    },
  };

  // 모달 열릴 때 상태 초기화
  useEffect(() => {
    if (open) {
      zoom.zoomReset();
      drag.resetPosition();
    }
  }, [open]);

  // 인쇄 핸들러
  const handlePrint = () => {
    if (propOnPrint) {
      propOnPrint();
    } else {
      printArea({ title });
    }
  };

  // 인라인 스타일 적용된 HTML 복제 생성
  const cloneWithInlineStyles = (element: HTMLElement): HTMLElement => {
    const clone = element.cloneNode(true) as HTMLElement;

    // 원본 요소들과 복제 요소들 매칭
    const originalElements = element.querySelectorAll('*');
    const clonedElements = clone.querySelectorAll('*');

    // 루트 요소 스타일 적용
    const rootStyle = window.getComputedStyle(element);
    applyStyles(clone, rootStyle);

    // 모든 하위 요소 스타일 적용
    originalElements.forEach((orig, index) => {
      const cloned = clonedElements[index] as HTMLElement;
      if (cloned) {
        const computedStyle = window.getComputedStyle(orig);
        applyStyles(cloned, computedStyle);
      }
    });

    return clone;
  };

  // 이미지를 base64 data URL로 인라인 변환 (PDF 이미지 누락 해결)
  const convertImagesToBase64 = async (original: HTMLElement, clone: HTMLElement): Promise<void> => {
    const originalImages = Array.from(original.querySelectorAll('img'));
    const clonedImages = Array.from(clone.querySelectorAll('img'));

    await Promise.all(
      originalImages.map(async (img, index) => {
        const clonedImg = clonedImages[index];
        if (!clonedImg) return;

        const src = img.src;
        if (!src || src.startsWith('data:')) return;

        // cross-origin 이미지는 서버 프록시를 통해 fetch (CORS 우회)
        const isSameOrigin = src.startsWith(window.location.origin) || src.startsWith('/');
        const fetchUrl = isSameOrigin ? src : `/api/image-proxy?url=${encodeURIComponent(src)}`;

        try {
          const response = await fetch(fetchUrl);
          if (!response.ok) throw new Error(`HTTP ${response.status}`);
          const blob = await response.blob();
          const dataUrl = await new Promise<string>((resolve, reject) => {
            const reader = new FileReader();
            reader.onloadend = () => resolve(reader.result as string);
            reader.onerror = reject;
            reader.readAsDataURL(blob);
          });
          clonedImg.setAttribute('src', dataUrl);
        } catch {
          try {
            if (img.complete && img.naturalWidth > 0) {
              const canvas = document.createElement('canvas');
              canvas.width = img.naturalWidth;
              canvas.height = img.naturalHeight;
              const ctx = canvas.getContext('2d');
              if (ctx) {
                ctx.drawImage(img, 0, 0);
                clonedImg.setAttribute('src', canvas.toDataURL('image/png'));
              }
            }
          } catch {
            // 변환 실패 시 빈 이미지로 대체 (Puppeteer에서 proxy URL 요청 방지)
            clonedImg.setAttribute('src', 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7');
          }
        }
      })
    );
  };

  // 계산된 스타일을 인라인으로 적용
  const applyStyles = (element: HTMLElement, computedStyle: CSSStyleDeclaration) => {
    const importantStyles = [
      'display', 'position', 'width', 'height', 'min-width', 'min-height', 'max-width', 'max-height',
      'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',
      'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',
      'border', 'border-width', 'border-style', 'border-color',
      'border-top', 'border-right', 'border-bottom', 'border-left',
      'border-collapse', 'border-spacing',
      'background', 'background-color',
      'color', 'font-family', 'font-size', 'font-weight', 'font-style',
      'text-align', 'text-decoration', 'vertical-align', 'line-height', 'white-space',
      'flex', 'flex-direction', 'flex-wrap', 'justify-content', 'align-items', 'gap',
      'grid-template-columns', 'grid-template-rows', 'grid-gap',
      'table-layout', 'overflow', 'visibility', 'opacity',
    ];

    importantStyles.forEach((prop) => {
      const value = computedStyle.getPropertyValue(prop);
      if (value && value !== 'none' && value !== 'normal' && value !== 'auto') {
        element.style.setProperty(prop, value);
      }
    });
  };

  // PDF 핸들러 (서버사이드 Puppeteer로 생성)
  const handlePdf = useCallback(async () => {
    if (onPdf) {
      onPdf();
      return;
    }

    try {
      setLoadingAction('pdf');
      toast.loading('PDF 생성 중...', { id: 'pdf-generating' });

      // print-area 영역 찾기
      const printAreaEl = document.querySelector('.print-area') as HTMLElement;
      if (!printAreaEl) {
        toast.error('PDF 생성 실패: 문서 영역을 찾을 수 없습니다.', { id: 'pdf-generating' });
        return;
      }

      // 인라인 스타일 적용된 HTML 복제 + 이미지 base64 인라인 변환
      const clonedElement = cloneWithInlineStyles(printAreaEl);
      await convertImagesToBase64(printAreaEl, clonedElement);
      const html = clonedElement.outerHTML;

      // 서버 API 호출
      const response = await fetch('/api/pdf/generate', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          html,
          title,
          orientation: 'portrait',
          documentNumber: pdfMeta?.documentNumber || '',
          createdDate: pdfMeta?.createdDate || getTodayString(),
          showHeaderFooter: pdfMeta?.showHeaderFooter !== false,
        }),
      });

      if (!response.ok) {
        throw new Error('PDF 생성 API 오류');
      }

      // PDF Blob 다운로드
      const blob = await response.blob();
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;

      // 파일명 생성 (날짜 포함)
      const date = new Date().toISOString().slice(0, 10).replace(/-/g, '');
      link.download = `${title}_${date}.pdf`;

      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(url);

      toast.success('PDF가 생성되었습니다.', { id: 'pdf-generating' });
    } catch (error) {
      console.error('PDF 생성 오류:', error);
      toast.error('PDF 생성 중 오류가 발생했습니다.', { id: 'pdf-generating' });
    } finally {
      setLoadingAction(null);
    }
  }, [onPdf, title, pdfMeta]);

  // 콘텐츠 렌더링
  const renderContent = (): ReactNode => {
    // 1. children이 있으면 children 사용 (정적 모드)
    if (children) {
      return children;
    }

    // 2. Config에 component가 있으면 컴포넌트 렌더링
    if (config?.component) {
      const Component = config.component;
      return <Component data={data} />;
    }

    // 3. Config에 blocks가 있으면 블록 렌더링 (Phase 2)
    if (config?.blocks) {
      // TODO: BlockRenderer 구현 시 연결
      return (
        <div className="p-8 text-center text-gray-500">
          블록 기반 렌더링은 준비 중입니다.
        </div>
      );
    }

    // 4. 아무것도 없으면 빈 상태
    return (
      <div className="p-8 text-center text-gray-500">
        문서 콘텐츠가 없습니다.
      </div>
    );
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="w-[95vw] max-w-[1200px] sm:max-w-[1200px] h-[90vh] p-0 overflow-hidden bg-gray-50 flex flex-col">
        {/* 헤더 */}
        <DialogHeader className="p-4 bg-white border-b border-gray-200 flex flex-row items-center justify-between space-y-0 shrink-0 print:hidden">
          <div>
            <DialogTitle className="text-lg font-bold text-gray-800">
              {title}
            </DialogTitle>
            {subtitle && (
              <p className="text-xs text-gray-500 mt-1">{subtitle}</p>
            )}
          </div>
        </DialogHeader>

        {/* 툴바 */}
        <DocumentToolbar
          zoom={zoom}
          features={features}
          actions={actions}
          onPrint={features.print ? handlePrint : undefined}
          onDownload={features.download ? onDownload : undefined}
          onEdit={onEdit}
          onDelete={onDelete}
          onSubmit={onSubmit}
          onApprove={onApprove}
          onReject={onReject}
          onCopy={onCopy}
          onPdf={handlePdf}
          onEmail={onEmail}
          onFax={onFax}
          onKakao={onKakao}
          toolbarExtra={toolbarExtra}
          loadingAction={loadingAction}
        />

        {/* 콘텐츠 */}
        <DocumentContent
          zoom={zoom.zoom}
          drag={drag}
          enableDrag={features.drag !== false}
        >
          <div className="print-area">{renderContent()}</div>
        </DocumentContent>
      </DialogContent>
    </Dialog>
  );
}
