"use client";

import { createContext, useContext, useState, useCallback, ReactNode, useEffect } from "react";
import { ComponentConfig, ReportDetail, ReportLayout } from "@/types/report";
import { reportApi } from "@/lib/api/reportApi";
import { useToast } from "@/hooks/use-toast";

export interface ReportQuery {
  id: string;
  name: string;
  type: "MASTER" | "DETAIL";
  sqlQuery: string;
  parameters: string[];
  externalConnectionId?: number | null; // 외부 DB 연결 ID
}

// 템플릿 레이아웃 정의
interface TemplateLayout {
  components: ComponentConfig[];
  queries: ReportQuery[];
}

function getTemplateLayout(templateId: string): TemplateLayout | null {
  switch (templateId) {
    case "order":
      return {
        components: [
          {
            id: `comp-${Date.now()}-1`,
            type: "label",
            x: 50,
            y: 30,
            width: 200,
            height: 40,
            fontSize: 24,
            fontColor: "#000000",
            backgroundColor: "transparent",
            borderColor: "#cccccc",
            borderWidth: 0,
            zIndex: 1,
            defaultValue: "발주서",
          },
          {
            id: `comp-${Date.now()}-2`,
            type: "text",
            x: 50,
            y: 80,
            width: 150,
            height: 30,
            fontSize: 14,
            fontColor: "#000000",
            backgroundColor: "transparent",
            borderColor: "#cccccc",
            borderWidth: 0,
            zIndex: 1,
          },
          {
            id: `comp-${Date.now()}-3`,
            type: "text",
            x: 220,
            y: 80,
            width: 150,
            height: 30,
            fontSize: 14,
            fontColor: "#000000",
            backgroundColor: "transparent",
            borderColor: "#cccccc",
            borderWidth: 0,
            zIndex: 1,
          },
          {
            id: `comp-${Date.now()}-4`,
            type: "text",
            x: 390,
            y: 80,
            width: 150,
            height: 30,
            fontSize: 14,
            fontColor: "#000000",
            backgroundColor: "transparent",
            borderColor: "#cccccc",
            borderWidth: 0,
            zIndex: 1,
          },
          {
            id: `comp-${Date.now()}-5`,
            type: "table",
            x: 50,
            y: 130,
            width: 500,
            height: 200,
            fontSize: 12,
            fontColor: "#000000",
            backgroundColor: "transparent",
            borderColor: "#cccccc",
            borderWidth: 0,
            zIndex: 1,
          },
        ],
        queries: [
          {
            id: `query-${Date.now()}-1`,
            name: "발주 헤더",
            type: "MASTER",
            sqlQuery: "SELECT order_no, order_date, supplier_name FROM orders WHERE order_no = $1",
            parameters: ["$1"],
          },
          {
            id: `query-${Date.now()}-2`,
            name: "발주 품목",
            type: "DETAIL",
            sqlQuery: "SELECT item_name, quantity, unit_price FROM order_items WHERE order_no = $1",
            parameters: ["$1"],
          },
        ],
      };

    case "invoice":
      return {
        components: [
          {
            id: `comp-${Date.now()}-1`,
            type: "label",
            x: 50,
            y: 30,
            width: 200,
            height: 40,
            fontSize: 24,
            fontColor: "#000000",
            backgroundColor: "transparent",
            borderColor: "#cccccc",
            borderWidth: 0,
            zIndex: 1,
            defaultValue: "청구서",
          },
          {
            id: `comp-${Date.now()}-2`,
            type: "text",
            x: 50,
            y: 80,
            width: 150,
            height: 30,
            fontSize: 14,
            fontColor: "#000000",
            backgroundColor: "transparent",
            borderColor: "#cccccc",
            borderWidth: 0,
            zIndex: 1,
          },
          {
            id: `comp-${Date.now()}-3`,
            type: "text",
            x: 220,
            y: 80,
            width: 150,
            height: 30,
            fontSize: 14,
            fontColor: "#000000",
            backgroundColor: "transparent",
            borderColor: "#cccccc",
            borderWidth: 0,
            zIndex: 1,
          },
          {
            id: `comp-${Date.now()}-4`,
            type: "table",
            x: 50,
            y: 130,
            width: 500,
            height: 200,
            fontSize: 12,
            fontColor: "#000000",
            backgroundColor: "transparent",
            borderColor: "#cccccc",
            borderWidth: 0,
            zIndex: 1,
          },
          {
            id: `comp-${Date.now()}-5`,
            type: "label",
            x: 400,
            y: 350,
            width: 150,
            height: 30,
            fontSize: 16,
            fontColor: "#000000",
            backgroundColor: "#ffffcc",
            borderColor: "#000000",
            borderWidth: 1,
            zIndex: 1,
            defaultValue: "합계: 0원",
          },
        ],
        queries: [
          {
            id: `query-${Date.now()}-1`,
            name: "청구 헤더",
            type: "MASTER",
            sqlQuery: "SELECT invoice_no, invoice_date, customer_name FROM invoices WHERE invoice_no = $1",
            parameters: ["$1"],
          },
          {
            id: `query-${Date.now()}-2`,
            name: "청구 항목",
            type: "DETAIL",
            sqlQuery: "SELECT description, quantity, unit_price, amount FROM invoice_items WHERE invoice_no = $1",
            parameters: ["$1"],
          },
        ],
      };

    case "basic":
      return {
        components: [
          {
            id: `comp-${Date.now()}-1`,
            type: "label",
            x: 50,
            y: 30,
            width: 300,
            height: 40,
            fontSize: 20,
            fontColor: "#000000",
            backgroundColor: "transparent",
            borderColor: "#cccccc",
            borderWidth: 0,
            zIndex: 1,
            defaultValue: "리포트 제목",
          },
          {
            id: `comp-${Date.now()}-2`,
            type: "text",
            x: 50,
            y: 80,
            width: 500,
            height: 100,
            fontSize: 14,
            fontColor: "#000000",
            backgroundColor: "transparent",
            borderColor: "#cccccc",
            borderWidth: 0,
            zIndex: 1,
            defaultValue: "내용을 입력하세요",
          },
        ],
        queries: [
          {
            id: `query-${Date.now()}-1`,
            name: "기본 쿼리",
            type: "MASTER",
            sqlQuery: "SELECT * FROM table_name WHERE id = $1",
            parameters: ["$1"],
          },
        ],
      };

    default:
      return null;
  }
}

export interface QueryResult {
  queryId: string;
  fields: string[];
  rows: Record<string, unknown>[];
}

interface ReportDesignerContextType {
  reportId: string;
  reportDetail: ReportDetail | null;
  layout: ReportLayout | null;
  components: ComponentConfig[];
  selectedComponentId: string | null;
  isLoading: boolean;
  isSaving: boolean;

  // 쿼리 관리
  queries: ReportQuery[];
  setQueries: (queries: ReportQuery[]) => void;

  // 쿼리 실행 결과
  queryResults: QueryResult[];
  setQueryResult: (queryId: string, fields: string[], rows: Record<string, unknown>[]) => void;
  getQueryResult: (queryId: string) => QueryResult | null;

  // 컴포넌트 관리
  addComponent: (component: ComponentConfig) => void;
  updateComponent: (id: string, updates: Partial<ComponentConfig>) => void;
  removeComponent: (id: string) => void;
  selectComponent: (id: string | null) => void;

  // 레이아웃 관리
  updateLayout: (updates: Partial<ReportLayout>) => void;
  saveLayout: () => Promise<void>;
  loadLayout: () => Promise<void>;

  // 템플릿 적용
  applyTemplate: (templateId: string) => void;

  // 캔버스 설정
  canvasWidth: number;
  canvasHeight: number;
  pageOrientation: string;
  margins: {
    top: number;
    bottom: number;
    left: number;
    right: number;
  };
}

const ReportDesignerContext = createContext<ReportDesignerContextType | undefined>(undefined);

export function ReportDesignerProvider({ reportId, children }: { reportId: string; children: ReactNode }) {
  const [reportDetail, setReportDetail] = useState<ReportDetail | null>(null);
  const [layout, setLayout] = useState<ReportLayout | null>(null);
  const [components, setComponents] = useState<ComponentConfig[]>([]);
  const [queries, setQueries] = useState<ReportQuery[]>([]);
  const [queryResults, setQueryResults] = useState<QueryResult[]>([]);
  const [selectedComponentId, setSelectedComponentId] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [isSaving, setIsSaving] = useState(false);
  const { toast } = useToast();

  // 캔버스 설정 (기본값)
  const [canvasWidth, setCanvasWidth] = useState(210);
  const [canvasHeight, setCanvasHeight] = useState(297);
  const [pageOrientation, setPageOrientation] = useState("portrait");
  const [margins, setMargins] = useState({
    top: 20,
    bottom: 20,
    left: 20,
    right: 20,
  });

  // 리포트 및 레이아웃 로드
  const loadLayout = useCallback(async () => {
    setIsLoading(true);
    try {
      // 'new'는 새 리포트 생성 모드
      if (reportId === "new") {
        setIsLoading(false);
        return;
      }

      // 리포트 상세 조회 (쿼리 포함)
      const detailResponse = await reportApi.getReportById(reportId);
      if (detailResponse.success && detailResponse.data) {
        setReportDetail(detailResponse.data);

        // 쿼리 로드
        if (detailResponse.data.queries && detailResponse.data.queries.length > 0) {
          const loadedQueries = detailResponse.data.queries.map((q) => ({
            id: q.query_id,
            name: q.query_name,
            type: q.query_type,
            sqlQuery: q.sql_query,
            parameters: Array.isArray(q.parameters) ? q.parameters : [],
          }));
          setQueries(loadedQueries);
        }
      }

      // 레이아웃 조회
      try {
        const layoutResponse = await reportApi.getLayout(reportId);
        if (layoutResponse.success && layoutResponse.data) {
          const layoutData = layoutResponse.data;
          setLayout(layoutData);
          setComponents(layoutData.components || []);
          setCanvasWidth(layoutData.canvas_width);
          setCanvasHeight(layoutData.canvas_height);
          setPageOrientation(layoutData.page_orientation);
          setMargins({
            top: layoutData.margin_top,
            bottom: layoutData.margin_bottom,
            left: layoutData.margin_left,
            right: layoutData.margin_right,
          });
        }
      } catch {
        // 레이아웃이 없으면 기본값 사용
        console.log("레이아웃 없음, 기본값 사용");
      }

      // 쿼리 조회는 이미 위에서 처리됨 (reportResponse.data.queries)
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : "리포트를 불러오는데 실패했습니다.";
      toast({
        title: "오류",
        description: errorMessage,
        variant: "destructive",
      });
    } finally {
      setIsLoading(false);
    }
  }, [reportId, toast]);

  // 초기 로드
  useEffect(() => {
    loadLayout();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [reportId]);

  // 쿼리 결과 저장
  const setQueryResult = useCallback((queryId: string, fields: string[], rows: Record<string, unknown>[]) => {
    setQueryResults((prev) => {
      const existing = prev.find((r) => r.queryId === queryId);
      if (existing) {
        return prev.map((r) => (r.queryId === queryId ? { queryId, fields, rows } : r));
      }
      return [...prev, { queryId, fields, rows }];
    });
  }, []);

  // 쿼리 결과 조회
  const getQueryResult = useCallback(
    (queryId: string): QueryResult | null => {
      return queryResults.find((r) => r.queryId === queryId) || null;
    },
    [queryResults],
  );

  // 컴포넌트 추가
  const addComponent = useCallback((component: ComponentConfig) => {
    setComponents((prev) => [...prev, component]);
  }, []);

  // 컴포넌트 업데이트
  const updateComponent = useCallback((id: string, updates: Partial<ComponentConfig>) => {
    setComponents((prev) => prev.map((comp) => (comp.id === id ? { ...comp, ...updates } : comp)));
  }, []);

  // 컴포넌트 삭제
  const removeComponent = useCallback(
    (id: string) => {
      setComponents((prev) => prev.filter((comp) => comp.id !== id));
      if (selectedComponentId === id) {
        setSelectedComponentId(null);
      }
    },
    [selectedComponentId],
  );

  // 컴포넌트 선택
  const selectComponent = useCallback((id: string | null) => {
    setSelectedComponentId(id);
  }, []);

  // 레이아웃 업데이트
  const updateLayout = useCallback((updates: Partial<ReportLayout>) => {
    setLayout((prev) => (prev ? { ...prev, ...updates } : null));

    if (updates.canvas_width !== undefined) setCanvasWidth(updates.canvas_width);
    if (updates.canvas_height !== undefined) setCanvasHeight(updates.canvas_height);
    if (updates.page_orientation !== undefined) setPageOrientation(updates.page_orientation);
    if (
      updates.margin_top !== undefined ||
      updates.margin_bottom !== undefined ||
      updates.margin_left !== undefined ||
      updates.margin_right !== undefined
    ) {
      setMargins((prev) => ({
        top: updates.margin_top ?? prev.top,
        bottom: updates.margin_bottom ?? prev.bottom,
        left: updates.margin_left ?? prev.left,
        right: updates.margin_right ?? prev.right,
      }));
    }
  }, []);

  // 레이아웃 저장
  const saveLayout = useCallback(async () => {
    setIsSaving(true);
    try {
      let actualReportId = reportId;

      // 새 리포트인 경우 먼저 리포트 생성
      if (reportId === "new") {
        const createResponse = await reportApi.createReport({
          reportNameKor: "새 리포트",
          reportType: "BASIC",
          description: "새로 생성된 리포트입니다.",
        });

        if (!createResponse.success || !createResponse.data) {
          throw new Error("리포트 생성에 실패했습니다.");
        }

        actualReportId = createResponse.data.reportId;

        // URL 업데이트 (페이지 리로드 없이)
        window.history.replaceState({}, "", `/admin/report/designer/${actualReportId}`);
      }

      // 레이아웃 저장 (쿼리 포함)
      await reportApi.saveLayout(actualReportId, {
        canvasWidth,
        canvasHeight,
        pageOrientation,
        marginTop: margins.top,
        marginBottom: margins.bottom,
        marginLeft: margins.left,
        marginRight: margins.right,
        components,
        queries,
      });

      toast({
        title: "성공",
        description: reportId === "new" ? "리포트가 생성되었습니다." : "레이아웃이 저장되었습니다.",
      });

      // 새 리포트였다면 데이터 다시 로드
      if (reportId === "new") {
        await loadLayout();
      }
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : "저장에 실패했습니다.";
      toast({
        title: "오류",
        description: errorMessage,
        variant: "destructive",
      });
    } finally {
      setIsSaving(false);
    }
  }, [reportId, canvasWidth, canvasHeight, pageOrientation, margins, components, queries, toast, loadLayout]);

  // 템플릿 적용
  const applyTemplate = useCallback(
    async (templateId: string) => {
      try {
        // 기존 컴포넌트가 있으면 확인
        if (components.length > 0) {
          if (!confirm("현재 레이아웃을 덮어씁니다. 계속하시겠습니까?")) {
            return;
          }
        }

        // 1. 먼저 하드코딩된 시스템 템플릿 확인 (order, invoice, basic)
        const systemTemplate = getTemplateLayout(templateId);

        if (systemTemplate) {
          // 시스템 템플릿 적용
          setComponents(systemTemplate.components);
          setQueries(systemTemplate.queries);

          toast({
            title: "성공",
            description: "템플릿이 적용되었습니다.",
          });
          return;
        }

        // 2. 사용자 정의 템플릿은 백엔드에서 조회
        const response = await reportApi.getTemplates();

        if (!response.success || !response.data) {
          throw new Error("템플릿 목록을 불러올 수 없습니다.");
        }

        // 커스텀 템플릿 찾기
        const customTemplates = response.data.custom || [];
        const template = customTemplates.find((t: any) => t.template_id === templateId);

        if (!template) {
          throw new Error("템플릿을 찾을 수 없습니다.");
        }

        // 3. 템플릿 데이터 파싱 및 적용
        const layoutConfig =
          typeof template.layout_config === "string" ? JSON.parse(template.layout_config) : template.layout_config;

        const defaultQueries =
          typeof template.default_queries === "string"
            ? JSON.parse(template.default_queries)
            : template.default_queries || [];

        // 컴포넌트 적용 (ID 재생성)
        const newComponents = layoutConfig.components.map((comp: any) => ({
          ...comp,
          id: `comp-${Date.now()}-${Math.random()}`,
        }));

        // 쿼리 적용 (ID 재생성)
        const newQueries = defaultQueries.map((q: any) => ({
          id: `query-${Date.now()}-${Math.random()}`,
          name: q.name,
          type: q.type,
          sqlQuery: q.sqlQuery,
          parameters: q.parameters || [],
          externalConnectionId: q.externalConnectionId || null,
        }));

        setComponents(newComponents);
        setQueries(newQueries);

        toast({
          title: "성공",
          description: "사용자 정의 템플릿이 적용되었습니다.",
        });
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : "템플릿 적용에 실패했습니다.";
        toast({
          title: "오류",
          description: errorMessage,
          variant: "destructive",
        });
      }
    },
    [components.length, toast],
  );

  const value: ReportDesignerContextType = {
    reportId,
    reportDetail,
    layout,
    components,
    queries,
    setQueries,
    queryResults,
    setQueryResult,
    getQueryResult,
    selectedComponentId,
    isLoading,
    isSaving,
    addComponent,
    updateComponent,
    removeComponent,
    selectComponent,
    updateLayout,
    saveLayout,
    loadLayout,
    applyTemplate,
    canvasWidth,
    canvasHeight,
    pageOrientation,
    margins,
  };

  return <ReportDesignerContext.Provider value={value}>{children}</ReportDesignerContext.Provider>;
}

export function useReportDesigner() {
  const context = useContext(ReportDesignerContext);
  if (context === undefined) {
    throw new Error("useReportDesigner must be used within a ReportDesignerProvider");
  }
  return context;
}
