"use client";

import React, { useState, useEffect, useCallback, useMemo } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Plus,
  Search,
  RefreshCw,
  Database,
  LayoutGrid,
  CheckCircle,
  Activity,
  AlertTriangle,
} from "lucide-react";
import { toast } from "sonner";
import { showErrorToast } from "@/lib/utils/toastUtils";
import { useRouter } from "next/navigation";
import { BatchAPI, type BatchConfig } from "@/lib/api/batch";
import apiClient from "@/lib/api/client";
import { ScrollToTop } from "@/components/common/ScrollToTop";
import { cn } from "@/lib/utils";
import BatchCard from "@/components/admin/BatchCard";

// 대시보드 통계 타입 (백엔드 GET /batch-management/stats)
interface BatchStats {
  totalBatches: number;
  activeBatches: number;
  todayExecutions: number;
  todayFailures: number;
  prevDayExecutions?: number;
  prevDayFailures?: number;
}

// 스파크라인/최근 로그 타입은 BatchCard 내부 정의 사용

/** Cron 표현식 → 한글 설명 */
function cronToKorean(cron: string): string {
  if (!cron || !cron.trim()) return "-";
  const parts = cron.trim().split(/\s+/);
  if (parts.length < 5) return cron;
  const [min, hour, dayOfMonth, month, dayOfWeek] = parts;

  // 매 30분: */30 * * * *
  if (min.startsWith("*/") && hour === "*" && dayOfMonth === "*" && month === "*" && dayOfWeek === "*") {
    const n = min.slice(2);
    return `매 ${n}분`;
  }
  // 매 N시간: 0 */2 * * *
  if (min === "0" && hour.startsWith("*/") && dayOfMonth === "*" && month === "*" && dayOfWeek === "*") {
    const n = hour.slice(2);
    return `매 ${n}시간`;
  }
  // 매일 HH:MM: 0 1 * * * 또는 0 6,18 * * *
  if (min === "0" && dayOfMonth === "*" && month === "*" && dayOfWeek === "*") {
    if (hour.includes(",")) {
      const times = hour.split(",").map((h) => `${h.padStart(2, "0")}:00`);
      return times.join(", ");
    }
    return `매일 ${hour.padStart(2, "0")}:00`;
  }
  // 매주 일 03:00: 0 3 * * 0
  if (min === "0" && dayOfMonth === "*" && month === "*" && dayOfWeek !== "*" && dayOfWeek !== "?") {
    const dayNames = ["일", "월", "화", "수", "목", "금", "토"];
    const d = dayNames[parseInt(dayOfWeek, 10)] ?? dayOfWeek;
    return `매주 ${d} ${hour.padStart(2, "0")}:00`;
  }
  // 매월 1일 00:00: 0 0 1 * *
  if (min === "0" && hour === "0" && dayOfMonth !== "*" && month === "*" && dayOfWeek === "*") {
    return `매월 ${dayOfMonth}일 00:00`;
  }
  return cron;
}

type StatusFilter = "all" | "active" | "inactive";
type TypeFilter = "all" | "mapping" | "restapi" | "node_flow";

export default function BatchManagementPage() {
  const router = useRouter();
  const [batchConfigs, setBatchConfigs] = useState<BatchConfig[]>([]);
  const [loading, setLoading] = useState(false);
  const [stats, setStats] = useState<BatchStats | null>(null);
  const [statsLoading, setStatsLoading] = useState(false);
  const [searchTerm, setSearchTerm] = useState("");
  const [statusFilter, setStatusFilter] = useState<StatusFilter>("all");
  const [typeFilter, setTypeFilter] = useState<TypeFilter>("all");
  const [executingBatch, setExecutingBatch] = useState<number | null>(null);
  const [expandedId, setExpandedId] = useState<number | null>(null);
  const [isBatchTypeModalOpen, setIsBatchTypeModalOpen] = useState(false);

  const loadBatchConfigs = useCallback(async () => {
    setLoading(true);
    try {
      const response = await BatchAPI.getBatchConfigs({
        limit: 500,
        search: searchTerm || undefined,
      });
      if (response.success && response.data) {
        setBatchConfigs(response.data);
      } else {
        setBatchConfigs([]);
      }
    } catch (error) {
      console.error("배치 목록 조회 실패:", error);
      toast.error("배치 목록을 불러오는데 실패했습니다.");
      setBatchConfigs([]);
    } finally {
      setLoading(false);
    }
  }, [searchTerm]);

  const loadStats = useCallback(async () => {
    setStatsLoading(true);
    try {
      const res = await apiClient.get<{ success: boolean; data?: BatchStats }>("/batch-management/stats");
      if (res.data?.success && res.data.data) {
        setStats(res.data.data);
      } else {
        setStats(null);
      }
    } catch {
      setStats(null);
    } finally {
      setStatsLoading(false);
    }
  }, []);

  useEffect(() => {
    loadBatchConfigs();
  }, [loadBatchConfigs]);

  useEffect(() => {
    loadStats();
  }, [loadStats]);

  const executeBatch = async (batchId: number) => {
    setExecutingBatch(batchId);
    try {
      const response = await BatchAPI.executeBatchConfig(batchId);
      if (response.success) {
        toast.success(
          `배치가 성공적으로 실행되었습니다! (처리: ${response.data?.totalRecords ?? 0}개, 성공: ${response.data?.successRecords ?? 0}개)`
        );
        loadBatchConfigs();
        loadStats();
      } else {
        toast.error("배치 실행에 실패했습니다.");
      }
    } catch (error) {
      showErrorToast("배치 실행에 실패했습니다", error, {
        guidance: "배치 설정을 확인하고 다시 시도해 주세요.",
      });
    } finally {
      setExecutingBatch(null);
    }
  };

  const toggleBatchStatus = async (batchId: number, currentStatus: string) => {
    try {
      const newStatus = currentStatus === "Y" ? "N" : "Y";
      await BatchAPI.updateBatchConfig(batchId, { isActive: newStatus === "Y" });
      toast.success(`배치가 ${newStatus === "Y" ? "활성화" : "비활성화"}되었습니다.`);
      loadBatchConfigs();
      loadStats();
    } catch (error) {
      console.error("배치 상태 변경 실패:", error);
      toast.error("배치 상태 변경에 실패했습니다.");
    }
  };

  const deleteBatch = async (batchId: number, batchName: string) => {
    if (!confirm(`'${batchName}' 배치를 삭제하시겠습니까?`)) return;
    try {
      await BatchAPI.deleteBatchConfig(batchId);
      toast.success("배치가 삭제되었습니다.");
      loadBatchConfigs();
      loadStats();
    } catch (error) {
      console.error("배치 삭제 실패:", error);
      toast.error("배치 삭제에 실패했습니다.");
    }
  };

  const handleCreateBatch = () => setIsBatchTypeModalOpen(true);

  const handleBatchTypeSelect = (type: "db-to-db" | "restapi-to-db") => {
    setIsBatchTypeModalOpen(false);
    if (type === "db-to-db") {
      router.push("/admin/batchmng/create");
    } else {
      router.push("/admin/batch-management-new");
    }
  };

  const filteredBatches = useMemo(() => {
    let list = batchConfigs;
    if (statusFilter === "active") list = list.filter((b) => b.is_active === "Y");
    else if (statusFilter === "inactive") list = list.filter((b) => b.is_active !== "Y");
    const et = (b: BatchConfig) => (b as { execution_type?: string }).execution_type;
    if (typeFilter === "mapping") list = list.filter((b) => !et(b) || et(b) === "mapping");
    else if (typeFilter === "restapi") list = list.filter((b) => et(b) === "restapi");
    else if (typeFilter === "node_flow") list = list.filter((b) => et(b) === "node_flow");
    return list;
  }, [batchConfigs, statusFilter, typeFilter]);

  return (
    <div className="flex min-h-screen flex-col bg-background">
      <div className="space-y-6 p-6">
        {/* 헤더 */}
        <div className="flex flex-col gap-4 border-b pb-4 sm:flex-row sm:items-end sm:justify-between">
          <div className="space-y-1">
            <h1 className="text-xl font-extrabold tracking-tight sm:text-3xl">배치 관리</h1>
            <p className="text-xs text-muted-foreground sm:text-sm">
              데이터 동기화 배치 작업을 모니터링하고 관리합니다.
            </p>
          </div>
          <div className="flex gap-2">
            <Button variant="outline" size="default" onClick={loadBatchConfigs} disabled={loading} className="gap-2">
              <RefreshCw className={cn("h-4 w-4", loading && "animate-spin")} />
              새로고침
            </Button>
            <Button size="default" onClick={handleCreateBatch} className="gap-2">
              <Plus className="h-4 w-4" />
              새 배치
            </Button>
          </div>
        </div>

        {/* 통계 카드 4개 */}
        <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
          <div className="flex justify-between rounded-xl border bg-card p-4">
            <div>
              <p className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">전체 배치</p>
              <p className="mt-1 font-mono text-2xl font-extrabold sm:text-3xl">
                {statsLoading ? "-" : (stats?.totalBatches ?? 0).toLocaleString()}
              </p>
            </div>
            <div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-indigo-500/10">
              <LayoutGrid className="h-5 w-5 text-indigo-500" />
            </div>
          </div>
          <div className="flex justify-between rounded-xl border bg-card p-4">
            <div>
              <p className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">활성 배치</p>
              <p className="mt-1 font-mono text-2xl font-extrabold text-green-600 sm:text-3xl">
                {statsLoading ? "-" : (stats?.activeBatches ?? 0).toLocaleString()}
              </p>
            </div>
            <div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-green-500/10">
              <CheckCircle className="h-5 w-5 text-green-500" />
            </div>
          </div>
          <div className="flex justify-between rounded-xl border bg-card p-4">
            <div>
              <p className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">오늘 실행</p>
              <p className="mt-1 font-mono text-2xl font-extrabold text-cyan-600 sm:text-3xl">
                {statsLoading ? "-" : (stats?.todayExecutions ?? 0).toLocaleString()}
              </p>
            </div>
            <div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-cyan-500/10">
              <Activity className="h-5 w-5 text-cyan-500" />
            </div>
          </div>
          <div className="flex justify-between rounded-xl border bg-card p-4">
            <div>
              <p className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">오늘 실패</p>
              <p className="mt-1 font-mono text-2xl font-extrabold text-destructive sm:text-3xl">
                {statsLoading ? "-" : (stats?.todayFailures ?? 0).toLocaleString()}
              </p>
            </div>
            <div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-destructive/10">
              <AlertTriangle className="h-5 w-5 text-destructive" />
            </div>
          </div>
        </div>

        {/* 툴바 */}
        <div className="flex flex-col gap-3 sm:flex-row sm:items-center">
          <div className="relative max-w-[320px] flex-1">
            <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
            <Input
              placeholder="배치 이름으로 검색..."
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              className="h-9 rounded-lg border bg-card pl-9 text-xs"
            />
          </div>
          <div className="flex gap-2">
            <div className="flex gap-0.5 rounded-lg border bg-card p-0.5">
              {(["all", "active", "inactive"] as const).map((s) => (
                <button
                  key={s}
                  type="button"
                  onClick={() => setStatusFilter(s)}
                  className={cn(
                    "rounded-md px-3 py-1.5 text-[11px] font-semibold",
                    statusFilter === s ? "bg-primary/10 text-primary" : "text-muted-foreground hover:opacity-80"
                  )}
                >
                  {s === "all" ? "전체" : s === "active" ? "활성" : "비활성"}
                </button>
              ))}
            </div>
            <div className="flex gap-0.5 rounded-lg border bg-card p-0.5">
              {(["all", "mapping", "restapi", "node_flow"] as const).map((t) => (
                <button
                  key={t}
                  type="button"
                  onClick={() => setTypeFilter(t)}
                  className={cn(
                    "rounded-md px-3 py-1.5 text-[11px] font-semibold",
                    typeFilter === t ? "bg-primary/10 text-primary" : "text-muted-foreground hover:opacity-80"
                  )}
                >
                  {t === "all" ? "전체" : t === "mapping" ? "DB-DB" : t === "restapi" ? "API-DB" : "노드 플로우"}
                </button>
              ))}
            </div>
          </div>
          <div className="ml-auto text-[11px] text-muted-foreground">
            총 <span className="font-bold text-foreground">{filteredBatches.length}</span>건
          </div>
        </div>

        {/* 배치 테이블 */}
        {filteredBatches.length === 0 ? (
          <div className="flex h-64 flex-col items-center justify-center rounded-xl border bg-card">
            <Database className="h-12 w-12 text-muted-foreground" />
            <p className="mt-2 text-sm text-muted-foreground">
              {searchTerm || statusFilter !== "all" || typeFilter !== "all" ? "검색 결과가 없습니다." : "배치가 없습니다."}
            </p>
            {!searchTerm && statusFilter === "all" && typeFilter === "all" && (
              <Button onClick={handleCreateBatch} className="mt-4 gap-2" size="sm">
                <Plus className="h-4 w-4" />
                첫 배치 추가
              </Button>
            )}
          </div>
        ) : (
          <div className="overflow-hidden rounded-xl border bg-card">
            <table className="w-full table-fixed border-collapse" style={{ tableLayout: "fixed" }}>
              <thead>
                <tr className="h-10 bg-muted/50">
                  <th className="w-[44px] border-b px-2 text-[10px] font-bold uppercase tracking-wider text-muted-foreground" />
                  <th className="border-b px-3 text-left text-[10px] font-bold uppercase tracking-wider text-muted-foreground">
                    배치
                  </th>
                  <th className="w-[100px] border-b px-2 text-[10px] font-bold uppercase tracking-wider text-muted-foreground">
                    타입
                  </th>
                  <th className="w-[130px] border-b px-2 text-[10px] font-bold uppercase tracking-wider text-muted-foreground">
                    스케줄
                  </th>
                  <th className="w-[160px] border-b px-2 text-[10px] font-bold uppercase tracking-wider text-muted-foreground">
                    최근 24h
                  </th>
                  <th className="w-[100px] border-b px-2 text-[10px] font-bold uppercase tracking-wider text-muted-foreground">
                    마지막 실행
                  </th>
                  <th className="w-[120px] border-b px-2 text-right text-[10px] font-bold uppercase tracking-wider text-muted-foreground">
                    액션
                  </th>
                </tr>
              </thead>
              <tbody>
                {filteredBatches.map((batch) => (
                  <BatchCard
                    key={batch.id}
                    batch={batch}
                    expanded={expandedId === batch.id}
                    onToggleExpand={() => setExpandedId((id) => (id === batch.id ? null : batch.id ?? null))}
                    executingBatch={executingBatch}
                    onExecute={executeBatch}
                    onToggleStatus={toggleBatchStatus}
                    onEdit={(id) => router.push(`/admin/batchmng/edit/${id}`)}
                    onDelete={deleteBatch}
                    cronToKorean={cronToKorean}
                  />
                ))}
              </tbody>
            </table>
          </div>
        )}

        {/* 배치 타입 선택 모달 */}
        {isBatchTypeModalOpen && (
          <div className="fixed inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm">
            <div className="w-full max-w-2xl rounded-lg border bg-card p-6 shadow-lg">
              <h2 className="text-center text-xl font-semibold">배치 타입 선택</h2>
              <div className="mt-6 grid grid-cols-1 gap-4 md:grid-cols-2">
                <button
                  type="button"
                  className="flex flex-col items-center gap-4 rounded-lg border bg-card p-6 shadow-sm transition-all hover:border-primary hover:bg-accent"
                  onClick={() => handleBatchTypeSelect("db-to-db")}
                >
                  <div className="flex items-center gap-2">
                    <Database className="h-8 w-8 text-primary" />
                    <span className="text-muted-foreground">→</span>
                    <Database className="h-8 w-8 text-primary" />
                  </div>
                  <div className="space-y-1 text-center">
                    <div className="text-lg font-medium">DB → DB</div>
                    <div className="text-sm text-muted-foreground">데이터베이스 간 데이터 동기화</div>
                  </div>
                </button>
                <button
                  type="button"
                  className="flex flex-col items-center gap-4 rounded-lg border bg-card p-6 shadow-sm transition-all hover:border-primary hover:bg-accent"
                  onClick={() => handleBatchTypeSelect("restapi-to-db")}
                >
                  <div className="flex items-center gap-2">
                    <span className="text-2xl text-muted-foreground">API</span>
                    <span className="text-muted-foreground">→</span>
                    <Database className="h-8 w-8 text-primary" />
                  </div>
                  <div className="space-y-1 text-center">
                    <div className="text-lg font-medium">REST API → DB</div>
                    <div className="text-sm text-muted-foreground">REST API에서 DB로 데이터 수집</div>
                  </div>
                </button>
              </div>
              <div className="mt-6 flex justify-center">
                <Button variant="outline" onClick={() => setIsBatchTypeModalOpen(false)}>
                  취소
                </Button>
              </div>
            </div>
          </div>
        )}
      </div>
      <ScrollToTop />
    </div>
  );
}
