import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { batchApi, type ScheduleResponse } from '../api/batchApi';
import { formatDateTime } from '../utils/formatters';
import { useToastContext } from '../contexts/ToastContext';
import ConfirmModal from '../components/ConfirmModal';
import EmptyState from '../components/EmptyState';
import LoadingSpinner from '../components/LoadingSpinner';
import { getNextExecutions } from '../utils/cronPreview';

type ScheduleMode = 'new' | 'existing';

interface ConfirmAction {
  type: 'toggle' | 'delete';
  schedule: ScheduleResponse;
}

const CRON_PRESETS = [
  { label: '매 분', cron: '0 * * * * ?' },
  { label: '매시 정각', cron: '0 0 * * * ?' },
  { label: '매 15분', cron: '0 0/15 * * * ?' },
  { label: '매일 00:00', cron: '0 0 0 * * ?' },
  { label: '매일 12:00', cron: '0 0 12 * * ?' },
  { label: '매주 월 00:00', cron: '0 0 0 ? * MON' },
];

function CronPreview({ cron }: { cron: string }) {
  const nextDates = useMemo(() => getNextExecutions(cron, 5), [cron]);

  if (nextDates.length === 0) {
    return (
      <div className="md:col-span-2">
        <p className="text-xs text-wing-muted">미리보기 불가 (복잡한 표현식)</p>
      </div>
    );
  }

  const fmt = new Intl.DateTimeFormat('ko-KR', {
    month: '2-digit',
    day: '2-digit',
    weekday: 'short',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
  });

  return (
    <div className="md:col-span-2">
      <label className="block text-sm font-medium text-wing-text mb-1">
        다음 5회 실행 예정
      </label>
      <div className="flex flex-wrap gap-2">
        {nextDates.map((d, i) => (
          <span
            key={i}
            className="inline-block bg-wing-accent/10 text-wing-accent text-xs font-mono px-2 py-1 rounded"
          >
            {fmt.format(d)}
          </span>
        ))}
      </div>
    </div>
  );
}

function getTriggerStateStyle(state: string | null): string {
  switch (state) {
    case 'NORMAL':
      return 'bg-emerald-100 text-emerald-700';
    case 'PAUSED':
      return 'bg-amber-100 text-amber-700';
    case 'BLOCKED':
      return 'bg-red-100 text-red-700';
    case 'ERROR':
      return 'bg-red-100 text-red-700';
    default:
      return 'bg-wing-card text-wing-muted';
  }
}

export default function Schedules() {
  const { showToast } = useToastContext();

  // Form state
  const [jobs, setJobs] = useState<string[]>([]);
  const [selectedJob, setSelectedJob] = useState('');
  const [cronExpression, setCronExpression] = useState('');
  const [description, setDescription] = useState('');
  const [scheduleMode, setScheduleMode] = useState<ScheduleMode>('new');
  const [formLoading, setFormLoading] = useState(false);
  const [saving, setSaving] = useState(false);

  // Schedule list state
  const [schedules, setSchedules] = useState<ScheduleResponse[]>([]);
  const [listLoading, setListLoading] = useState(true);

  // Confirm modal state
  const [confirmAction, setConfirmAction] = useState<ConfirmAction | null>(null);

  // 폼 영역 ref (편집 버튼 클릭 시 스크롤)
  const formRef = useRef<HTMLDivElement>(null);

  const loadSchedules = useCallback(async () => {
    try {
      const result = await batchApi.getSchedules();
      setSchedules(result.schedules);
    } catch (err) {
      showToast('스케줄 목록 조회 실패', 'error');
      console.error(err);
    } finally {
      setListLoading(false);
    }
  }, [showToast]);

  const loadJobs = useCallback(async () => {
    try {
      const result = await batchApi.getJobs();
      setJobs(result);
    } catch (err) {
      showToast('작업 목록 조회 실패', 'error');
      console.error(err);
    }
  }, [showToast]);

  useEffect(() => {
    loadJobs();
    loadSchedules();
  }, [loadJobs, loadSchedules]);

  const handleJobSelect = async (jobName: string) => {
    setSelectedJob(jobName);
    setCronExpression('');
    setDescription('');
    setScheduleMode('new');

    if (!jobName) return;

    setFormLoading(true);
    try {
      const schedule = await batchApi.getSchedule(jobName);
      setCronExpression(schedule.cronExpression);
      setDescription(schedule.description ?? '');
      setScheduleMode('existing');
    } catch {
      // 404 = new schedule
      setScheduleMode('new');
    } finally {
      setFormLoading(false);
    }
  };

  const handleSave = async () => {
    if (!selectedJob) {
      showToast('작업을 선택해주세요', 'error');
      return;
    }
    if (!cronExpression.trim()) {
      showToast('Cron 표현식을 입력해주세요', 'error');
      return;
    }

    setSaving(true);
    try {
      if (scheduleMode === 'existing') {
        await batchApi.updateSchedule(selectedJob, {
          cronExpression: cronExpression.trim(),
          description: description.trim() || undefined,
        });
        showToast('스케줄이 수정되었습니다', 'success');
      } else {
        await batchApi.createSchedule({
          jobName: selectedJob,
          cronExpression: cronExpression.trim(),
          description: description.trim() || undefined,
        });
        showToast('스케줄이 등록되었습니다', 'success');
      }
      await loadSchedules();
      // Reload schedule info for current job
      await handleJobSelect(selectedJob);
    } catch (err) {
      const message = err instanceof Error ? err.message : '저장 실패';
      showToast(message, 'error');
    } finally {
      setSaving(false);
    }
  };

  const handleToggle = async (schedule: ScheduleResponse) => {
    try {
      await batchApi.toggleSchedule(schedule.jobName, !schedule.active);
      showToast(
        `${schedule.jobName} 스케줄이 ${schedule.active ? '비활성화' : '활성화'}되었습니다`,
        'success',
      );
      await loadSchedules();
    } catch (err) {
      const message = err instanceof Error ? err.message : '토글 실패';
      showToast(message, 'error');
    }
    setConfirmAction(null);
  };

  const handleDelete = async (schedule: ScheduleResponse) => {
    try {
      await batchApi.deleteSchedule(schedule.jobName);
      showToast(`${schedule.jobName} 스케줄이 삭제되었습니다`, 'success');
      await loadSchedules();
      // Clear form if deleted schedule was selected
      if (selectedJob === schedule.jobName) {
        setSelectedJob('');
        setCronExpression('');
        setDescription('');
        setScheduleMode('new');
      }
    } catch (err) {
      const message = err instanceof Error ? err.message : '삭제 실패';
      showToast(message, 'error');
    }
    setConfirmAction(null);
  };

  const handleEditFromCard = (schedule: ScheduleResponse) => {
    setSelectedJob(schedule.jobName);
    setCronExpression(schedule.cronExpression);
    setDescription(schedule.description ?? '');
    setScheduleMode('existing');
    formRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
  };

  return (
    <div className="space-y-6">
      {/* Form Section */}
      <div ref={formRef} className="bg-wing-surface rounded-xl shadow-lg p-6">
        <h2 className="text-lg font-bold text-wing-text mb-4">스케줄 등록 / 수정</h2>

        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          {/* Job Select */}
          <div>
            <label className="block text-sm font-medium text-wing-text mb-1">
              작업 선택
            </label>
            <div className="flex items-center gap-2">
              <select
                value={selectedJob}
                onChange={(e) => handleJobSelect(e.target.value)}
                className="flex-1 rounded-lg border border-wing-border px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-wing-accent focus:border-wing-accent"
                disabled={formLoading}
              >
                <option value="">-- 작업을 선택하세요 --</option>
                {jobs.map((job) => (
                  <option key={job} value={job}>
                    {job}
                  </option>
                ))}
              </select>
              {selectedJob && (
                <span
                  className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-semibold whitespace-nowrap ${
                    scheduleMode === 'existing'
                      ? 'bg-blue-100 text-blue-700'
                      : 'bg-green-100 text-green-700'
                  }`}
                >
                  {scheduleMode === 'existing' ? '기존 스케줄' : '새 스케줄'}
                </span>
              )}
              {formLoading && (
                <div className="w-5 h-5 border-2 border-wing-accent/30 border-t-wing-accent rounded-full animate-spin" />
              )}
            </div>
          </div>

          {/* Cron Expression */}
          <div>
            <label className="block text-sm font-medium text-wing-text mb-1">
              Cron 표현식
            </label>
            <input
              type="text"
              value={cronExpression}
              onChange={(e) => setCronExpression(e.target.value)}
              placeholder="0 0/15 * * * ?"
              className="w-full rounded-lg border border-wing-border px-3 py-2 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-wing-accent focus:border-wing-accent"
              disabled={!selectedJob || formLoading}
            />
          </div>

          {/* Cron Presets */}
          <div className="md:col-span-2">
            <label className="block text-sm font-medium text-wing-text mb-1">
              프리셋
            </label>
            <div className="flex flex-wrap gap-2">
              {CRON_PRESETS.map(({ label, cron }) => (
                <button
                  key={cron}
                  type="button"
                  onClick={() => setCronExpression(cron)}
                  disabled={!selectedJob || formLoading}
                  className="px-3 py-1 text-xs font-medium bg-wing-card text-wing-text rounded-lg hover:bg-wing-accent/15 hover:text-wing-accent transition-colors disabled:opacity-50"
                >
                  {label}
                </button>
              ))}
            </div>
          </div>

          {/* Cron Preview */}
          {cronExpression.trim() && (
            <CronPreview cron={cronExpression.trim()} />
          )}

          {/* Description */}
          <div className="md:col-span-2">
            <label className="block text-sm font-medium text-wing-text mb-1">
              설명
            </label>
            <input
              type="text"
              value={description}
              onChange={(e) => setDescription(e.target.value)}
              placeholder="스케줄 설명 (선택)"
              className="w-full rounded-lg border border-wing-border px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-wing-accent focus:border-wing-accent"
              disabled={!selectedJob || formLoading}
            />
          </div>
        </div>

        {/* Save Button */}
        <div className="mt-4 flex justify-end">
          <button
            onClick={handleSave}
            disabled={!selectedJob || !cronExpression.trim() || saving || formLoading}
            className="px-6 py-2 text-sm font-medium text-white bg-wing-accent rounded-lg hover:bg-wing-accent/80 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
          >
            {saving ? '저장 중...' : '저장'}
          </button>
        </div>
      </div>

      {/* Schedule List */}
      <div className="bg-wing-surface rounded-xl shadow-lg p-6">
        <div className="flex items-center justify-between mb-4">
          <h2 className="text-lg font-bold text-wing-text">
            등록된 스케줄
            {schedules.length > 0 && (
              <span className="ml-2 text-sm font-normal text-wing-muted">
                ({schedules.length}개)
              </span>
            )}
          </h2>
          <button
            onClick={loadSchedules}
            className="px-3 py-1.5 text-sm text-wing-muted bg-wing-card rounded-lg hover:bg-wing-hover transition-colors"
          >
            새로고침
          </button>
        </div>

        {listLoading ? (
          <LoadingSpinner />
        ) : schedules.length === 0 ? (
          <EmptyState message="등록된 스케줄이 없습니다" sub="위 폼에서 새 스케줄을 등록하세요" />
        ) : (
          <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
            {schedules.map((schedule) => (
              <div
                key={schedule.id}
                className="border border-wing-border rounded-xl p-4 hover:shadow-md transition-shadow"
              >
                {/* Header */}
                <div className="flex items-center justify-between mb-3">
                  <div className="flex items-center gap-2 min-w-0">
                    <h3 className="text-sm font-bold text-wing-text truncate">
                      {schedule.jobName}
                    </h3>
                    <span
                      className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-semibold ${
                        schedule.active
                          ? 'bg-emerald-100 text-emerald-700'
                          : 'bg-wing-card text-wing-muted'
                      }`}
                    >
                      {schedule.active ? '활성' : '비활성'}
                    </span>
                    {schedule.triggerState && (
                      <span
                        className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-semibold ${getTriggerStateStyle(schedule.triggerState)}`}
                      >
                        {schedule.triggerState}
                      </span>
                    )}
                  </div>
                </div>

                {/* Cron Expression */}
                <div className="mb-2">
                  <span className="inline-block bg-wing-card text-wing-text font-mono text-xs px-2 py-1 rounded">
                    {schedule.cronExpression}
                  </span>
                </div>

                {/* Description */}
                {schedule.description && (
                  <p className="text-sm text-wing-muted mb-3">{schedule.description}</p>
                )}

                {/* Time Info */}
                <div className="grid grid-cols-2 gap-2 text-xs text-wing-muted mb-3">
                  <div>
                    <span className="font-medium text-wing-muted">다음 실행:</span>{' '}
                    {formatDateTime(schedule.nextFireTime)}
                  </div>
                  <div>
                    <span className="font-medium text-wing-muted">이전 실행:</span>{' '}
                    {formatDateTime(schedule.previousFireTime)}
                  </div>
                  <div>
                    <span className="font-medium text-wing-muted">등록일:</span>{' '}
                    {formatDateTime(schedule.createdAt)}
                  </div>
                  <div>
                    <span className="font-medium text-wing-muted">수정일:</span>{' '}
                    {formatDateTime(schedule.updatedAt)}
                  </div>
                </div>

                {/* Action Buttons */}
                <div className="flex gap-2 pt-2 border-t border-wing-border/50">
                  <button
                    onClick={() => handleEditFromCard(schedule)}
                    className="flex-1 px-3 py-1.5 text-xs font-medium text-wing-accent bg-wing-accent/10 rounded-lg hover:bg-wing-accent/20 transition-colors"
                  >
                    편집
                  </button>
                  <button
                    onClick={() =>
                      setConfirmAction({ type: 'toggle', schedule })
                    }
                    className={`flex-1 px-3 py-1.5 text-xs font-medium rounded-lg transition-colors ${
                      schedule.active
                        ? 'text-amber-700 bg-amber-50 hover:bg-amber-100'
                        : 'text-emerald-700 bg-emerald-50 hover:bg-emerald-100'
                    }`}
                  >
                    {schedule.active ? '비활성화' : '활성화'}
                  </button>
                  <button
                    onClick={() =>
                      setConfirmAction({ type: 'delete', schedule })
                    }
                    className="flex-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>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* Confirm Modal */}
      {confirmAction?.type === 'toggle' && (
        <ConfirmModal
          open
          title="스케줄 상태 변경"
          message={`${confirmAction.schedule.jobName} 스케줄을 ${
            confirmAction.schedule.active ? '비활성화' : '활성화'
          }하시겠습니까?`}
          confirmLabel={confirmAction.schedule.active ? '비활성화' : '활성화'}
          onConfirm={() => handleToggle(confirmAction.schedule)}
          onCancel={() => setConfirmAction(null)}
        />
      )}
      {confirmAction?.type === 'delete' && (
        <ConfirmModal
          open
          title="스케줄 삭제"
          message={`${confirmAction.schedule.jobName} 스케줄을 삭제하시겠습니까?\n이 작업은 되돌릴 수 없습니다.`}
          confirmLabel="삭제"
          confirmColor="bg-red-600 hover:bg-red-700"
          onConfirm={() => handleDelete(confirmAction.schedule)}
          onCancel={() => setConfirmAction(null)}
        />
      )}
    </div>
  );
}
