import { useState, useMemo, useCallback, useEffect } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { batchApi, type JobExecutionDto, type ExecutionSearchResponse, type JobDisplayName } from '../api/batchApi';
import { formatDateTime, calculateDuration } from '../utils/formatters';
import { usePoller } from '../hooks/usePoller';
import { useToastContext } from '../contexts/ToastContext';
import StatusBadge from '../components/StatusBadge';
import ConfirmModal from '../components/ConfirmModal';
import InfoModal from '../components/InfoModal';
import EmptyState from '../components/EmptyState';
import LoadingSpinner from '../components/LoadingSpinner';
import GuideModal, { HelpButton } from '../components/GuideModal';

type StatusFilter = 'ALL' | 'COMPLETED' | 'FAILED' | 'STARTED' | 'STOPPED';

const STATUS_FILTERS: { value: StatusFilter; label: string }[] = [
    { value: 'ALL', label: '전체' },
    { value: 'COMPLETED', label: '완료' },
    { value: 'FAILED', label: '실패' },
    { value: 'STARTED', label: '실행중' },
    { value: 'STOPPED', label: '중지됨' },
];

const POLLING_INTERVAL_MS = 5000;
const RECENT_LIMIT = 50;
const PAGE_SIZE = 50;

const EXECUTIONS_GUIDE = [
    {
        title: '작업 필터',
        content: '상단의 드롭다운에서 조회할 작업을 선택할 수 있습니다.\n여러 작업을 동시에 선택할 수 있으며, 단축 버튼으로 빠르게 필터링할 수 있습니다.\n• 전체: 모든 작업 표시\n• AIS 제외: AIS 관련 작업을 제외하고 표시\n• AIS만: AIS 관련 작업만 표시',
    },
    {
        title: '상태 필터',
        content: '완료 / 실패 / 실행중 / 중지됨 버튼으로 상태별 필터링이 가능합니다.\n"전체"를 선택하면 모든 상태의 실행 이력을 볼 수 있습니다.',
    },
    {
        title: '날짜 검색',
        content: '시작일과 종료일을 지정하여 특정 기간의 실행 이력을 조회할 수 있습니다.\n"검색" 버튼을 클릭하면 조건에 맞는 결과가 표시됩니다.\n"초기화" 버튼으로 검색 조건을 제거하고 최신 이력으로 돌아갑니다.',
    },
    {
        title: '실행 중인 작업 제어',
        content: '실행 중인 작업의 행에서 "중지" 또는 "강제 종료" 버튼을 사용할 수 있습니다.\n• 중지: 현재 Step 완료 후 안전하게 종료\n• 강제 종료: 즉시 중단 (데이터 정합성 주의)',
    },
    {
        title: '실패 로그 확인',
        content: '상태가 "FAILED"인 행을 클릭하면 실패 상세 정보를 확인할 수 있습니다.\n종료 코드(Exit Code)와 에러 메시지로 실패 원인을 파악하세요.\n상태가 "COMPLETED"이지만 실패 건수가 있으면 경고 아이콘이 표시됩니다.',
    },
];

export default function Executions() {
    const navigate = useNavigate();
    const [searchParams, setSearchParams] = useSearchParams();

    const jobFromQuery = searchParams.get('job') || '';

    const [jobs, setJobs] = useState<string[]>([]);
    const [displayNames, setDisplayNames] = useState<JobDisplayName[]>([]);
    const [executions, setExecutions] = useState<JobExecutionDto[]>([]);
    const [selectedJobs, setSelectedJobs] = useState<string[]>(jobFromQuery ? [jobFromQuery] : []);
    const [jobDropdownOpen, setJobDropdownOpen] = useState(false);
    const [statusFilter, setStatusFilter] = useState<StatusFilter>('ALL');
    const [loading, setLoading] = useState(true);
    const [stopTarget, setStopTarget] = useState<JobExecutionDto | null>(null);

    // F1: 강제 종료
    const [abandonTarget, setAbandonTarget] = useState<JobExecutionDto | null>(null);

    // F4: 날짜 범위 필터 + 페이지네이션
    const [startDate, setStartDate] = useState('');
    const [endDate, setEndDate] = useState('');
    const [page, setPage] = useState(0);
    const [totalPages, setTotalPages] = useState(0);
    const [totalCount, setTotalCount] = useState(0);
    const [useSearch, setUseSearch] = useState(false);

    // F9: 실패 로그 뷰어
    const [failLogTarget, setFailLogTarget] = useState<JobExecutionDto | null>(null);

    const [guideOpen, setGuideOpen] = useState(false);

    const { showToast } = useToastContext();

    useEffect(() => {
        batchApi.getDisplayNames().then(setDisplayNames).catch(() => {});
    }, []);

    const displayNameMap = useMemo<Record<string, string>>(() => {
        const map: Record<string, string> = {};
        for (const dn of displayNames) {
            map[dn.jobName] = dn.displayName;
        }
        return map;
    }, [displayNames]);

    const loadJobs = useCallback(async () => {
        try {
            const data = await batchApi.getJobs();
            setJobs(data);
        } catch {
            /* Job 목록 로드 실패는 무시 */
        }
    }, []);

    const loadSearchExecutions = useCallback(async (targetPage: number) => {
        try {
            setLoading(true);
            const params: {
                jobNames?: string[];
                status?: string;
                startDate?: string;
                endDate?: string;
                page?: number;
                size?: number;
            } = {
                page: targetPage,
                size: PAGE_SIZE,
            };
            if (selectedJobs.length > 0) params.jobNames = selectedJobs;
            if (statusFilter !== 'ALL') params.status = statusFilter;
            if (startDate) params.startDate = `${startDate}T00:00:00`;
            if (endDate) params.endDate = `${endDate}T23:59:59`;

            const data: ExecutionSearchResponse = await batchApi.searchExecutions(params);
            setExecutions(data.executions);
            setTotalPages(data.totalPages);
            setTotalCount(data.totalCount);
            setPage(data.page);
        } catch {
            setExecutions([]);
            setTotalPages(0);
            setTotalCount(0);
        } finally {
            setLoading(false);
        }
    }, [selectedJobs, statusFilter, startDate, endDate]);

    const loadExecutions = useCallback(async () => {
        // 검색 모드에서는 폴링하지 않음 (검색 버튼 클릭 시에만 1회 조회)
        if (useSearch) return;
        try {
            let data: JobExecutionDto[];
            if (selectedJobs.length === 1) {
                data = await batchApi.getJobExecutions(selectedJobs[0]);
            } else if (selectedJobs.length > 1) {
                // 복수 Job 선택 시 search API 사용
                const result = await batchApi.searchExecutions({
                    jobNames: selectedJobs, size: RECENT_LIMIT,
                });
                data = result.executions;
            } else {
                try {
                    data = await batchApi.getRecentExecutions(RECENT_LIMIT);
                } catch {
                    data = [];
                }
            }
            setExecutions(data);
        } catch {
            setExecutions([]);
        } finally {
            setLoading(false);
        }
    }, [selectedJobs, useSearch, page, loadSearchExecutions]);

    /* 마운트 시 Job 목록 1회 로드 */
    usePoller(loadJobs, 60_000, []);

    /* 실행 이력 5초 폴링 */
    usePoller(loadExecutions, POLLING_INTERVAL_MS, [selectedJobs, useSearch, page]);

    const filteredExecutions = useMemo(() => {
        // 검색 모드에서는 서버 필터링 사용
        if (useSearch) return executions;
        if (statusFilter === 'ALL') return executions;
        return executions.filter((e) => e.status === statusFilter);
    }, [executions, statusFilter, useSearch]);

    const toggleJob = (jobName: string) => {
        setSelectedJobs((prev) => {
            const next = prev.includes(jobName)
                ? prev.filter((j) => j !== jobName)
                : [...prev, jobName];
            if (next.length === 1) {
                setSearchParams({ job: next[0] });
            } else {
                setSearchParams({});
            }
            return next;
        });
        setLoading(true);
        if (useSearch) {
            setPage(0);
        }
    };

    const clearSelectedJobs = () => {
        setSelectedJobs([]);
        setSearchParams({});
        setLoading(true);
        if (useSearch) {
            setPage(0);
        }
    };

    const handleStop = async () => {
        if (!stopTarget) return;
        try {
            const result = await batchApi.stopExecution(stopTarget.executionId);
            showToast(result.message || '실행이 중지되었습니다.', 'success');
        } catch (err) {
            showToast(
                err instanceof Error ? err.message : '중지 요청에 실패했습니다.',
                'error',
            );
        } finally {
            setStopTarget(null);
        }
    };

    // F1: 강제 종료 핸들러
    const handleAbandon = async () => {
        if (!abandonTarget) return;
        try {
            const result = await batchApi.abandonExecution(abandonTarget.executionId);
            showToast(result.message || '실행이 강제 종료되었습니다.', 'success');
        } catch (err) {
            showToast(
                err instanceof Error ? err.message : '강제 종료 요청에 실패했습니다.',
                'error',
            );
        } finally {
            setAbandonTarget(null);
        }
    };

    // F4: 검색 핸들러
    const handleSearch = async () => {
        setUseSearch(true);
        setPage(0);
        await loadSearchExecutions(0);
    };

    // F4: 초기화 핸들러
    const handleResetSearch = () => {
        setUseSearch(false);
        setStartDate('');
        setEndDate('');
        setPage(0);
        setTotalPages(0);
        setTotalCount(0);
        setLoading(true);
    };

    // F4: 페이지 이동 핸들러
    const handlePageChange = (newPage: number) => {
        if (newPage < 0 || newPage >= totalPages) return;
        setPage(newPage);
        loadSearchExecutions(newPage);
    };

    const isRunning = (status: string) =>
        status === 'STARTED' || status === 'STARTING';

    return (
        <div className="space-y-6">
            {/* 헤더 */}
            <div>
                <div className="flex items-center gap-2">
                    <h1 className="text-2xl font-bold text-wing-text">실행 이력</h1>
                    <HelpButton onClick={() => setGuideOpen(true)} />
                </div>
                <p className="mt-1 text-sm text-wing-muted">
                    배치 작업 실행 이력을 조회하고 관리합니다.
                </p>
            </div>

            {/* 필터 영역 */}
            <div className="bg-wing-surface rounded-xl shadow-md p-6">
                <div className="space-y-3">
                    {/* Job 멀티 선택 */}
                    <div>
                        <div className="flex items-center gap-3 mb-2">
                            <label className="text-sm font-medium text-wing-text shrink-0">
                                작업 선택
                            </label>
                            <div className="relative">
                                <button
                                    onClick={() => setJobDropdownOpen((v) => !v)}
                                    className="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-lg border border-wing-border bg-wing-surface hover:bg-wing-hover transition-colors"
                                >
                                    {selectedJobs.length === 0
                                        ? `전체 (최근 ${RECENT_LIMIT}건)`
                                        : `${selectedJobs.length}개 선택됨`}
                                    <svg className={`w-4 h-4 text-wing-muted transition-transform ${jobDropdownOpen ? 'rotate-180' : ''}`} fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" /></svg>
                                </button>
                                {jobDropdownOpen && (
                                    <>
                                        <div className="fixed inset-0 z-10" onClick={() => setJobDropdownOpen(false)} />
                                        <div className="absolute z-20 mt-1 w-72 max-h-60 overflow-y-auto bg-wing-surface border border-wing-border rounded-lg shadow-lg">
                                            {jobs.map((job) => (
                                                <label
                                                    key={job}
                                                    className="flex items-center gap-2 px-3 py-2 text-sm cursor-pointer hover:bg-wing-hover transition-colors"
                                                >
                                                    <input
                                                        type="checkbox"
                                                        checked={selectedJobs.includes(job)}
                                                        onChange={() => toggleJob(job)}
                                                        className="rounded border-wing-border text-wing-accent focus:ring-wing-accent"
                                                    />
                                                    <span className="text-wing-text truncate">{displayNameMap[job] || job}</span>
                                                </label>
                                            ))}
                                        </div>
                                    </>
                                )}
                            </div>
                            <div className="flex gap-1.5">
                                <button
                                    onClick={() => setSelectedJobs([])}
                                    className={`px-2 py-1 text-xs rounded-md transition-colors ${
                                        selectedJobs.length === 0
                                            ? 'bg-wing-accent text-white'
                                            : 'bg-wing-card text-wing-muted hover:bg-wing-hover'
                                    }`}
                                >
                                    전체
                                </button>
                            </div>
                            {selectedJobs.length > 0 && (
                                <button
                                    onClick={clearSelectedJobs}
                                    className="text-xs text-wing-muted hover:text-wing-accent transition-colors"
                                >
                                    초기화
                                </button>
                            )}
                        </div>
                        {/* 선택된 Job 칩 */}
                        {selectedJobs.length > 0 && (
                            <div className="flex flex-wrap gap-1.5">
                                {selectedJobs.map((job) => (
                                    <span
                                        key={job}
                                        className="inline-flex items-center gap-1 px-2.5 py-1 text-xs font-medium bg-wing-accent/15 text-wing-accent rounded-full"
                                    >
                                        {displayNameMap[job] || job}
                                        <button
                                            onClick={() => toggleJob(job)}
                                            className="hover:text-wing-text transition-colors"
                                        >
                                            &times;
                                        </button>
                                    </span>
                                ))}
                            </div>
                        )}
                    </div>

                    {/* 상태 필터 버튼 그룹 */}
                    <div className="flex flex-wrap gap-1">
                        {STATUS_FILTERS.map(({ value, label }) => (
                            <button
                                key={value}
                                onClick={() => {
                                    setStatusFilter(value);
                                    if (useSearch) {
                                        setPage(0);
                                    }
                                }}
                                className={`px-3 py-1.5 text-xs font-medium rounded-lg transition-colors ${
                                    statusFilter === value
                                        ? 'bg-wing-accent text-white shadow-sm'
                                        : 'bg-wing-card text-wing-muted hover:bg-wing-hover'
                                }`}
                            >
                                {label}
                            </button>
                        ))}
                    </div>
                </div>

                {/* F4: 날짜 범위 필터 */}
                <div className="flex flex-col gap-3 sm:flex-row sm:items-center mt-4 pt-4 border-t border-wing-border/50">
                    <label className="text-sm font-medium text-wing-text shrink-0">
                        기간 검색
                    </label>
                    <div className="flex items-center gap-2">
                        <input
                            type="date"
                            value={startDate}
                            onChange={(e) => setStartDate(e.target.value)}
                            className="block rounded-lg border border-wing-border bg-wing-surface px-3 py-2 text-sm shadow-sm focus:border-wing-accent focus:ring-1 focus:ring-wing-accent"
                        />
                        <span className="text-wing-muted text-sm">~</span>
                        <input
                            type="date"
                            value={endDate}
                            onChange={(e) => setEndDate(e.target.value)}
                            className="block rounded-lg border border-wing-border bg-wing-surface px-3 py-2 text-sm shadow-sm focus:border-wing-accent focus:ring-1 focus:ring-wing-accent"
                        />
                    </div>
                    <div className="flex items-center gap-2">
                        <button
                            onClick={handleSearch}
                            className="px-4 py-2 text-sm font-medium text-white bg-wing-accent rounded-lg hover:bg-wing-accent/80 transition-colors shadow-sm"
                        >
                            검색
                        </button>
                        {useSearch && (
                            <button
                                onClick={handleResetSearch}
                                className="px-4 py-2 text-sm font-medium text-wing-text bg-wing-card rounded-lg hover:bg-wing-hover transition-colors"
                            >
                                초기화
                            </button>
                        )}
                    </div>
                </div>
            </div>

            {/* 실행 이력 테이블 */}
            <div className="bg-wing-surface rounded-xl shadow-md overflow-hidden">
                {loading ? (
                    <LoadingSpinner />
                ) : filteredExecutions.length === 0 ? (
                    <EmptyState
                        message="실행 이력이 없습니다."
                        sub={
                            statusFilter !== 'ALL'
                                ? '다른 상태 필터를 선택해 보세요.'
                                : selectedJobs.length > 0
                                  ? '선택한 작업의 실행 이력이 없습니다.'
                                  : undefined
                        }
                    />
                ) : (
                    <div className="overflow-x-auto">
                        <table className="w-full text-sm text-left">
                            <thead className="bg-wing-card text-xs uppercase text-wing-muted">
                                <tr>
                                    <th className="px-6 py-3 font-medium">실행 ID</th>
                                    <th className="px-6 py-3 font-medium">작업명</th>
                                    <th className="px-6 py-3 font-medium">상태</th>
                                    <th className="px-6 py-3 font-medium">시작시간</th>
                                    <th className="px-6 py-3 font-medium">종료시간</th>
                                    <th className="px-6 py-3 font-medium">소요시간</th>
                                    <th className="px-6 py-3 font-medium text-right">
                                        액션
                                    </th>
                                </tr>
                            </thead>
                            <tbody className="divide-y divide-wing-border/50">
                                {filteredExecutions.map((exec) => (
                                    <tr
                                        key={exec.executionId}
                                        className="hover:bg-wing-hover transition-colors"
                                    >
                                        <td className="px-6 py-4 font-mono text-wing-text">
                                            #{exec.executionId}
                                        </td>
                                        <td className="px-6 py-4 text-wing-text">
                                            {displayNameMap[exec.jobName] || exec.jobName}
                                        </td>
                                        <td className="px-6 py-4">
                                            <div className="flex items-center gap-1.5">
                                                {/* F9: FAILED 상태 클릭 시 실패 로그 모달 */}
                                                {exec.status === 'FAILED' ? (
                                                    <button
                                                        onClick={() => setFailLogTarget(exec)}
                                                        className="cursor-pointer"
                                                        title="클릭하여 실패 로그 확인"
                                                    >
                                                        <StatusBadge status={exec.status} />
                                                    </button>
                                                ) : (
                                                    <StatusBadge status={exec.status} />
                                                )}
                                                {exec.status === 'COMPLETED' && exec.failedRecordCount != null && exec.failedRecordCount > 0 && (
                                                    <span
                                                        className="inline-flex items-center gap-0.5 px-1.5 py-0.5 text-[10px] font-semibold text-amber-700 bg-amber-50 border border-amber-200 rounded-full"
                                                        title={`미해결 실패 레코드 ${exec.failedRecordCount}건`}
                                                    >
                                                        <svg className="w-2.5 h-2.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                                                            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M12 9v2m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
                                                        </svg>
                                                        {exec.failedRecordCount}
                                                    </span>
                                                )}
                                            </div>
                                        </td>
                                        <td className="px-6 py-4 text-wing-muted whitespace-nowrap">
                                            {formatDateTime(exec.startTime)}
                                        </td>
                                        <td className="px-6 py-4 text-wing-muted whitespace-nowrap">
                                            {formatDateTime(exec.endTime)}
                                        </td>
                                        <td className="px-6 py-4 text-wing-muted whitespace-nowrap">
                                            {calculateDuration(
                                                exec.startTime,
                                                exec.endTime,
                                            )}
                                        </td>
                                        <td className="px-6 py-4 text-right">
                                            <div className="flex items-center justify-end gap-2">
                                                {isRunning(exec.status) && (
                                                    <>
                                                        <button
                                                            onClick={() =>
                                                                setStopTarget(exec)
                                                            }
                                                            className="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium text-red-700 bg-red-50 rounded-lg hover:bg-red-100 transition-colors"
                                                        >
                                                            중지
                                                        </button>
                                                        <button
                                                            onClick={() =>
                                                                setAbandonTarget(exec)
                                                            }
                                                            className="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium text-amber-700 bg-amber-50 rounded-lg hover:bg-amber-100 transition-colors"
                                                        >
                                                            강제 종료
                                                        </button>
                                                    </>
                                                )}
                                                <button
                                                    onClick={() =>
                                                        navigate(
                                                            `/executions/${exec.executionId}`,
                                                        )
                                                    }
                                                    className="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium text-wing-accent bg-wing-accent/10 rounded-lg hover:bg-wing-accent/15 transition-colors"
                                                >
                                                    상세
                                                </button>
                                            </div>
                                        </td>
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>
                )}

                {/* 결과 건수 표시 + F4: 페이지네이션 */}
                {!loading && filteredExecutions.length > 0 && (
                    <div className="px-6 py-3 bg-wing-card border-t border-wing-border/50 flex items-center justify-between">
                        <div className="text-xs text-wing-muted">
                            {useSearch ? (
                                <>총 {totalCount}건</>
                            ) : (
                                <>
                                    총 {filteredExecutions.length}건
                                    {statusFilter !== 'ALL' && (
                                        <span className="ml-1">
                                            (전체 {executions.length}건 중)
                                        </span>
                                    )}
                                </>
                            )}
                        </div>
                        {/* F4: 페이지네이션 UI */}
                        {useSearch && totalPages > 1 && (
                            <div className="flex items-center gap-2">
                                <button
                                    onClick={() => handlePageChange(page - 1)}
                                    disabled={page === 0}
                                    className="px-3 py-1.5 text-xs font-medium rounded-lg transition-colors disabled:opacity-40 disabled:cursor-not-allowed bg-wing-card text-wing-muted hover:bg-wing-hover"
                                >
                                    이전
                                </button>
                                <span className="text-xs text-wing-muted">
                                    {page + 1} / {totalPages}
                                </span>
                                <button
                                    onClick={() => handlePageChange(page + 1)}
                                    disabled={page >= totalPages - 1}
                                    className="px-3 py-1.5 text-xs font-medium rounded-lg transition-colors disabled:opacity-40 disabled:cursor-not-allowed bg-wing-card text-wing-muted hover:bg-wing-hover"
                                >
                                    다음
                                </button>
                            </div>
                        )}
                    </div>
                )}
            </div>

            {/* 중지 확인 모달 */}
            <ConfirmModal
                open={stopTarget !== null}
                title="실행 중지"
                message={
                    stopTarget
                        ? `실행 #${stopTarget.executionId} (${stopTarget.jobName})을 중지하시겠습니까?`
                        : ''
                }
                confirmLabel="중지"
                confirmColor="bg-red-600 hover:bg-red-700"
                onConfirm={handleStop}
                onCancel={() => setStopTarget(null)}
            />

            {/* F1: 강제 종료 확인 모달 */}
            <ConfirmModal
                open={abandonTarget !== null}
                title="강제 종료"
                message={
                    abandonTarget
                        ? `실행 #${abandonTarget.executionId} (${abandonTarget.jobName})을 강제 종료하시겠습니까?\n\n강제 종료는 실행 상태를 ABANDONED로 변경합니다.`
                        : ''
                }
                confirmLabel="강제 종료"
                confirmColor="bg-amber-600 hover:bg-amber-700"
                onConfirm={handleAbandon}
                onCancel={() => setAbandonTarget(null)}
            />

            <GuideModal
                open={guideOpen}
                onClose={() => setGuideOpen(false)}
                pageTitle="실행 이력"
                sections={EXECUTIONS_GUIDE}
            />

            {/* F9: 실패 로그 뷰어 모달 */}
            <InfoModal
                open={failLogTarget !== null}
                title={
                    failLogTarget
                        ? `실패 로그 - #${failLogTarget.executionId} (${failLogTarget.jobName})`
                        : '실패 로그'
                }
                onClose={() => setFailLogTarget(null)}
            >
                {failLogTarget && (
                    <div className="space-y-4">
                        <div>
                            <h4 className="text-xs font-semibold text-wing-muted uppercase mb-1">
                                Exit Code
                            </h4>
                            <p className="text-sm text-wing-text font-mono bg-wing-card px-3 py-2 rounded-lg">
                                {failLogTarget.exitCode || '-'}
                            </p>
                        </div>
                        <div>
                            <h4 className="text-xs font-semibold text-wing-muted uppercase mb-1">
                                Exit Message
                            </h4>
                            <pre className="text-sm text-wing-text font-mono bg-wing-card px-3 py-2 rounded-lg whitespace-pre-wrap break-words max-h-64 overflow-y-auto">
                                {failLogTarget.exitMessage || '메시지 없음'}
                            </pre>
                        </div>
                    </div>
                )}
            </InfoModal>
        </div>
    );
}
