"use client";

import React, { useState, useEffect, useCallback } from "react";
import { Button } from "@/components/ui/button";
import { Play, Pencil, Trash2, ChevronDown, ChevronRight, Clock } from "lucide-react";
import { BatchConfig } from "@/lib/api/batch";
import apiClient from "@/lib/api/client";
import { cn } from "@/lib/utils";

interface SparklineSlot {
  hour: string;
  success: number;
  failed: number;
}

interface BatchRecentLog {
  id?: number;
  started_at?: string;
  finished_at?: string;
  status?: string;
  total_records?: number;
  success_records?: number;
  failed_records?: number;
  error_message?: string | null;
  duration_ms?: number;
}

type LedStatus = "on" | "run" | "off" | "err";

function BatchLED({ status }: { status: LedStatus }) {
  return (
    <div
      className={cn(
        "mx-auto h-2 w-2 rounded-full",
        status === "on" && "bg-green-500 shadow-[0_0_8px_rgba(34,197,94,0.3)]",
        status === "run" &&
          "bg-amber-500 shadow-[0_0_8px_rgba(245,158,11,0.3)] animate-pulse",
        status === "off" && "bg-muted-foreground",
        status === "err" && "bg-red-500 shadow-[0_0_8px_rgba(239,68,68,0.3)]"
      )}
    />
  );
}

/** 스파크라인 24바 (div 기반, 높이 24px) */
function SparklineBars({ slots }: { slots: SparklineSlot[] }) {
  if (!slots || slots.length === 0) {
    return (
      <div className="flex h-6 items-end gap-[1px]">
        {Array.from({ length: 24 }).map((_, i) => (
          <div
            key={i}
            className="min-w-[3px] flex-1 rounded-t-[1px] bg-muted-foreground opacity-15"
            style={{ height: "5%" }}
          />
        ))}
      </div>
    );
  }
  return (
    <div className="flex h-6 items-end gap-[1px]">
      {slots.slice(0, 24).map((slot, i) => {
        const hasRun = slot.success + slot.failed > 0;
        const isFail = slot.failed > 0;
        const height =
          !hasRun ? 5 : isFail ? Math.min(40, 20 + slot.failed * 5) : Math.max(80, Math.min(95, 80 + slot.success));
        return (
          <div
            key={i}
            className={cn(
              "min-w-[3px] flex-1 rounded-t-[1px] transition-opacity hover:opacity-100",
              !hasRun && "bg-muted-foreground opacity-15",
              hasRun && isFail && "bg-red-500 opacity-80",
              hasRun && !isFail && "bg-green-500 opacity-60"
            )}
            style={{ height: `${height}%` }}
          />
        );
      })}
    </div>
  );
}

interface BatchCardProps {
  batch: BatchConfig;
  expanded: boolean;
  onToggleExpand: () => void;
  executingBatch: number | null;
  onExecute: (batchId: number) => void;
  onToggleStatus: (batchId: number, currentStatus: string) => void;
  onEdit: (batchId: number) => void;
  onDelete: (batchId: number, batchName: string) => void;
  cronToKorean: (cron: string) => string;
}

export default function BatchCard({
  batch,
  expanded,
  onToggleExpand,
  executingBatch,
  onExecute,
  onToggleStatus,
  onEdit,
  onDelete,
  cronToKorean,
}: BatchCardProps) {
  const [sparkline, setSparkline] = useState<SparklineSlot[]>([]);
  const [recentLogs, setRecentLogs] = useState<BatchRecentLog[]>([]);
  const [detailLoading, setDetailLoading] = useState(false);

  const isExecuting = executingBatch === batch.id;
  const isActive = batch.is_active === "Y";
  const ledStatus: LedStatus = isExecuting ? "run" : isActive ? "on" : "off";

  const executionType = (batch as { execution_type?: string }).execution_type;
  const typeLabel =
    executionType === "node_flow"
      ? "노드 플로우"
      : executionType === "restapi" || (batch.batch_mappings?.some((m) => m.from_connection_type === "external"))
      ? "API→DB"
      : "DB→DB";
  const typeBadgeClass =
    executionType === "node_flow"
      ? "bg-indigo-500/10 text-indigo-600"
      : executionType === "restapi" || batch.batch_mappings?.some((m) => m.from_connection_type === "external")
      ? "bg-violet-500/10 text-violet-600"
      : "bg-cyan-500/10 text-cyan-600";

  const loadDetail = useCallback(async () => {
    if (!batch.id) return;
    setDetailLoading(true);
    try {
      const [sparkRes, logsRes] = await Promise.all([
        apiClient.get<{ success: boolean; data?: SparklineSlot[] }>(
          `/batch-management/batch-configs/${batch.id}/sparkline`
        ),
        apiClient.get<{ success: boolean; data?: BatchRecentLog[] }>(
          `/batch-management/batch-configs/${batch.id}/recent-logs?limit=5`
        ),
      ]);
      if (sparkRes.data?.success && Array.isArray(sparkRes.data.data)) {
        setSparkline(sparkRes.data.data);
      }
      if (logsRes.data?.success && Array.isArray(logsRes.data.data)) {
        setRecentLogs(logsRes.data.data);
      }
    } catch {
      setSparkline([]);
      setRecentLogs([]);
    } finally {
      setDetailLoading(false);
    }
  }, [batch.id]);

  useEffect(() => {
    if (expanded) loadDetail();
  }, [expanded, loadDetail]);

  const lastLog = recentLogs[0];
  const lastRunText = isExecuting
    ? "실행 중..."
    : !isActive
    ? "-"
    : lastLog?.started_at
    ? new Date(lastLog.started_at).toLocaleTimeString("ko-KR", { hour: "2-digit", minute: "2-digit", second: "2-digit" })
    : "-";
  const lastRunSub =
    !isActive || !lastLog?.started_at
      ? "비활성"
      : isExecuting
      ? ""
      : (() => {
          const min = Math.floor((Date.now() - new Date(lastLog.started_at).getTime()) / 60000);
          if (min < 1) return "방금 전";
          if (min < 60) return `${min}분 전`;
          return `${Math.floor(min / 60)}시간 전`;
        })();

  const handleRowClick = (e: React.MouseEvent) => {
    if ((e.target as HTMLElement).closest("button")) return;
    onToggleExpand();
  };

  return (
    <>
      <tr
        role="button"
        tabIndex={0}
        onClick={handleRowClick}
        onKeyDown={(e) => (e.key === "Enter" || e.key === " ") && onToggleExpand()}
        className={cn(
          "min-h-[60px] border-b transition-colors hover:bg-card/80",
          expanded && "bg-primary/5 shadow-[inset_3px_0_0_0_hsl(var(--primary))]"
        )}
      >
        <td className="w-[44px] border-b px-2 py-2 align-middle">
          <div className="flex items-center justify-center gap-0.5">
            {expanded ? (
              <ChevronDown className="h-4 w-4 text-muted-foreground" />
            ) : (
              <ChevronRight className="h-4 w-4 text-muted-foreground" />
            )}
            <BatchLED status={ledStatus} />
          </div>
        </td>
        <td className="border-b px-3 py-2 align-middle">
          <div className="min-w-0">
            <p className={cn("truncate text-[13px] font-bold", !isActive && "text-muted-foreground")}>
              {batch.batch_name}
            </p>
            <p className="truncate text-[10px] text-muted-foreground">{batch.description || "설명 없음"}</p>
          </div>
        </td>
        <td className="w-[100px] border-b px-2 py-2 align-middle">
          <span className={cn("inline-flex rounded-[5px] px-2 py-0.5 text-[10px] font-bold", typeBadgeClass)}>
            {typeLabel}
          </span>
        </td>
        <td className="w-[130px] border-b px-2 py-2 align-middle">
          <p className={cn("font-mono text-[11px] font-medium", !isActive && "text-muted-foreground")}>
            {batch.cron_schedule}
          </p>
          <p className="text-[9px] text-muted-foreground">{cronToKorean(batch.cron_schedule)}</p>
        </td>
        <td className="w-[160px] border-b px-2 py-2 align-middle">
          {expanded ? (
            <SparklineBars slots={sparkline} />
          ) : (
            <div className="flex h-6 items-end gap-[1px]">
              {Array.from({ length: 24 }).map((_, i) => (
                <div
                  key={i}
                  className="min-w-[3px] flex-1 rounded-t-[1px] bg-muted-foreground opacity-15"
                  style={{ height: "5%" }}
                />
              ))}
            </div>
          )}
        </td>
        <td className="w-[100px] border-b px-2 py-2 align-middle">
          <p className={cn("font-mono text-[10px]", isExecuting && "text-amber-600")}>{lastRunText}</p>
          <p className="text-[9px] text-muted-foreground">{lastRunSub}</p>
        </td>
        <td className="w-[120px] border-b px-2 py-2 align-middle text-right">
          <div className="flex justify-end gap-1" onClick={(e) => e.stopPropagation()}>
            <Button
              variant="ghost"
              size="icon"
              className="h-7 w-7 hover:bg-green-500/20 hover:text-green-600"
              onClick={() => batch.id != null && onExecute(batch.id)}
              disabled={isExecuting}
              aria-label="수동 실행"
            >
              <Play className="h-3.5 w-3.5" />
            </Button>
            <Button
              variant="ghost"
              size="icon"
              className="h-7 w-7"
              onClick={() => batch.id != null && onEdit(batch.id)}
              aria-label="편집"
            >
              <Pencil className="h-3.5 w-3.5" />
            </Button>
            <Button
              variant="ghost"
              size="icon"
              className="h-7 w-7 hover:bg-destructive/20 hover:text-destructive"
              onClick={() => batch.id != null && onDelete(batch.id, batch.batch_name)}
              aria-label="삭제"
            >
              <Trash2 className="h-3.5 w-3.5" />
            </Button>
          </div>
        </td>
      </tr>
      {expanded && (
        <tr className="bg-muted/30">
          <td colSpan={7} className="border-b px-6 py-5 align-top">
            <div className="rounded-b-xl border border-t-0">
              {detailLoading ? (
                <div className="flex items-center justify-center py-8 text-sm text-muted-foreground">로딩 중...</div>
              ) : (
                <div className="space-y-4">
                  <div
                    className="rounded-lg border border-primary/10 bg-gradient-to-br from-primary/[0.06] to-cyan-500/5 px-4 py-3"
                    style={{
                      background: "linear-gradient(135deg, hsl(var(--primary) / 0.06), hsl(186 100% 50% / 0.04)",
                    }}
                  >
                    <p className="text-[11px] leading-relaxed text-muted-foreground">
                      {batch.description || batch.batch_name} 배치입니다. 스케줄: {cronToKorean(batch.cron_schedule)}
                      {recentLogs.length > 0 &&
                        ` · 최근 실행 ${recentLogs.length}건`}
                    </p>
                  </div>
                  <div className="grid gap-5 sm:grid-cols-2">
                    <div>
                      <h4 className="mb-2 flex items-center gap-1.5 text-[11px] font-bold text-muted-foreground">
                        <Clock className="h-3 w-3" />
                        최근 24시간
                      </h4>
                      <div className="h-10 w-full">
                        <SparklineBars slots={sparkline} />
                      </div>
                    </div>
                    <div>
                      <h4 className="mb-2 flex items-center gap-1.5 text-[11px] font-bold text-muted-foreground">
                        <Clock className="h-3 w-3" />
                        실행 이력 (최근 5건)
                      </h4>
                      <div className="overflow-x-auto rounded-md border bg-card">
                        <table className="w-full text-[10px]">
                          <thead>
                            <tr className="border-b bg-muted/50">
                              <th className="px-2 py-1.5 text-left font-semibold">시간</th>
                              <th className="px-2 py-1.5 text-left font-semibold">상태</th>
                              <th className="px-2 py-1.5 text-right font-semibold">처리</th>
                              <th className="max-w-[120px] truncate px-2 py-1.5 text-left font-semibold">에러</th>
                            </tr>
                          </thead>
                          <tbody>
                            {recentLogs.length === 0 ? (
                              <tr>
                                <td colSpan={4} className="px-2 py-3 text-center text-muted-foreground">
                                  이력 없음
                                </td>
                              </tr>
                            ) : (
                              recentLogs.map((log, i) => (
                                <tr key={i} className="border-b last:border-0">
                                  <td className="whitespace-nowrap px-2 py-1.5 font-mono">
                                    {log.started_at
                                      ? new Date(log.started_at).toLocaleString("ko-KR", {
                                          month: "2-digit",
                                          day: "2-digit",
                                          hour: "2-digit",
                                          minute: "2-digit",
                                        })
                                      : "-"}
                                  </td>
                                  <td className="px-2 py-1.5">
                                    <span
                                      className={cn(
                                        "rounded px-1.5 py-0.5 text-[9px] font-bold",
                                        log.status === "SUCCESS" || log.status === "success"
                                          ? "bg-green-500/10 text-green-600"
                                          : "bg-red-500/10 text-red-600"
                                      )}
                                    >
                                      {log.status === "SUCCESS" || log.status === "success" ? "성공" : "실패"}
                                    </span>
                                  </td>
                                  <td className="px-2 py-1.5 text-right font-mono">
                                    {log.success_records ?? log.total_records ?? 0}건
                                    {log.duration_ms != null ? ` / ${(log.duration_ms / 1000).toFixed(1)}s` : ""}
                                  </td>
                                  <td className="max-w-[120px] truncate px-2 py-1.5 text-muted-foreground">
                                    {log.error_message || "-"}
                                  </td>
                                </tr>
                              ))
                            )}
                          </tbody>
                        </table>
                      </div>
                    </div>
                  </div>
                </div>
              )}
            </div>
          </td>
        </tr>
      )}
    </>
  );
}
