// SPDX-License-Identifier: GPL-3.0-or-later

import { useState, useEffect, useCallback } from 'react';
import {
  Briefcase,
  Upload,
  Download,
  Trash2,
  Search,
  XCircle,
  RefreshCw,
  Clock,
  CheckCircle,
  AlertCircle,
  Ban,
  Play,
} from 'lucide-react';
import { useBackend } from '../contexts/BackendContext';
import { useToast } from '../components/Toast';
import Card from '../components/Card';
import StatusBadge from '../components/StatusBadge';
import ProgressBar from '../components/ProgressBar';
import Alert from '../components/Alert';
import Modal from '../components/Modal';
import { formatRelativeTime, formatTimeBetween, capitalize } from '../lib/utils';
import type { Job } from '../lib/api';

type FilterStatus = 'all' | 'running' | 'pending' | 'completed' | 'failed' | 'cancelled';

function getJobIcon(type: string) {
  switch (type) {
    case 'backup': return Upload;
    case 'restore': return Download;
    case 'prune': return Trash2;
    case 'check': return Search;
    default: return Briefcase;
  }
}

function getStatusIcon(status: string) {
  switch (status) {
    case 'running': return Play;
    case 'pending': return Clock;
    case 'completed': return CheckCircle;
    case 'failed': return AlertCircle;
    case 'cancelled': return Ban;
    default: return Clock;
  }
}

export default function Jobs() {
  const { listJobs, getJob, cancelJob } = useBackend();
  const toast = useToast();
  const [jobs, setJobs] = useState<Job[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [filter, setFilter] = useState<FilterStatus>('all');
  const [isRefreshing, setIsRefreshing] = useState(false);

  // Detail modal
  const [selectedJob, setSelectedJob] = useState<Job | null>(null);
  const [showDetailModal, setShowDetailModal] = useState(false);

  // Cancel confirmation
  const [cancellingId, setCancellingId] = useState<string | null>(null);

  const fetchJobs = useCallback(async () => {
    try {
      const status = filter === 'all' ? undefined : filter;
      const result = await listJobs(status);
      setJobs(result);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load jobs');
    } finally {
      setIsLoading(false);
    }
  }, [listJobs, filter]);

  // Initial load
  useEffect(() => {
    fetchJobs();
  }, [fetchJobs]);

  // Poll active jobs
  useEffect(() => {
    const hasActiveJobs = jobs.some((j) => j.status === 'running' || j.status === 'pending');
    if (!hasActiveJobs) return;

    const interval = setInterval(fetchJobs, 2000);
    return () => clearInterval(interval);
  }, [jobs, fetchJobs]);

  // Poll selected job detail if active
  useEffect(() => {
    if (!selectedJob || (selectedJob.status !== 'running' && selectedJob.status !== 'pending')) return;

    const poll = async () => {
      try {
        const updated = await getJob(selectedJob.id);
        setSelectedJob(updated);
        // Also update in list
        setJobs((prev) => prev.map((j) => (j.id === updated.id ? updated : j)));
      } catch (err) {
        console.error('Failed to poll job:', err);
      }
    };

    const interval = setInterval(poll, 1000);
    return () => clearInterval(interval);
  }, [selectedJob, getJob]);

  const handleRefresh = async () => {
    setIsRefreshing(true);
    await fetchJobs();
    setIsRefreshing(false);
  };

  const handleCancel = async (jobId: string) => {
    try {
      await cancelJob(jobId);
      toast.warning('Job cancelled');
      setCancellingId(null);
      await fetchJobs();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Failed to cancel job');
    }
  };

  const handleViewDetail = (job: Job) => {
    setSelectedJob(job);
    setShowDetailModal(true);
  };

  const filterButtons: { label: string; value: FilterStatus }[] = [
    { label: 'All', value: 'all' },
    { label: 'Running', value: 'running' },
    { label: 'Pending', value: 'pending' },
    { label: 'Completed', value: 'completed' },
    { label: 'Failed', value: 'failed' },
    { label: 'Cancelled', value: 'cancelled' },
  ];

  if (isLoading) {
    return (
      <div className="flex items-center justify-center h-64">
        <div className="animate-spin rounded-full h-8 w-8 border-2 border-primary-600 border-t-transparent"></div>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold text-slate-900 dark:text-white">Jobs</h1>
          <p className="text-slate-600 dark:text-slate-400 mt-1">
            View and manage background operations
          </p>
        </div>
        <button onClick={handleRefresh} disabled={isRefreshing} className="btn-secondary">
          <RefreshCw className={`w-4 h-4 mr-2 ${isRefreshing ? 'animate-spin' : ''}`} />
          Refresh
        </button>
      </div>

      {error && (
        <Alert type="error" onClose={() => setError(null)}>
          {error}
        </Alert>
      )}

      {/* Filters */}
      <div className="flex flex-wrap gap-2">
        {filterButtons.map((btn) => (
          <button
            key={btn.value}
            onClick={() => { setFilter(btn.value); setIsLoading(true); }}
            className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${
              filter === btn.value
                ? 'bg-primary-600 text-white'
                : 'bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-300 hover:bg-slate-200 dark:hover:bg-slate-700'
            }`}
          >
            {btn.label}
          </button>
        ))}
      </div>

      {/* Jobs List */}
      {jobs.length === 0 ? (
        <Card>
          <div className="text-center py-12">
            <Briefcase className="w-16 h-16 text-slate-300 dark:text-slate-600 mx-auto mb-4" />
            <h3 className="text-lg font-medium text-slate-900 dark:text-white mb-2">
              No Jobs Found
            </h3>
            <p className="text-slate-500 dark:text-slate-400">
              {filter === 'all'
                ? 'No jobs in this session. Jobs from previous runs are not persisted.'
                : `No ${filter} jobs found.`}
            </p>
          </div>
        </Card>
      ) : (
        <div className="space-y-3">
          {jobs.map((job) => {
            const Icon = getJobIcon(job.type);
            const isActive = job.status === 'running' || job.status === 'pending';

            return (
              <Card key={job.id}>
                <div className="flex items-center justify-between">
                  <div className="flex items-center space-x-4 min-w-0 flex-1">
                    <div className={`p-2.5 rounded-lg ${
                      isActive ? 'bg-primary-100 dark:bg-primary-900/30' : 'bg-slate-100 dark:bg-slate-700'
                    }`}>
                      <Icon className={`w-5 h-5 ${isActive ? 'text-primary-600' : 'text-slate-500 dark:text-slate-400'}`} />
                    </div>
                    <div className="min-w-0 flex-1">
                      <div className="flex items-center space-x-2">
                        <h3 className="font-medium text-slate-900 dark:text-white">
                          {capitalize(job.type)}
                        </h3>
                        <StatusBadge status={job.status} />
                      </div>
                      <p className="text-sm text-slate-500 dark:text-slate-400 mt-0.5">
                        {job.status === 'running' || job.status === 'pending'
                          ? `Started ${formatRelativeTime(job.started_at || job.created_at)}`
                          : job.completed_at
                            ? `Finished ${formatRelativeTime(job.completed_at)} · Duration: ${formatTimeBetween(job.started_at, job.completed_at)}`
                            : `Created ${formatRelativeTime(job.created_at)}`}
                      </p>
                      {job.error && (
                        <p className="text-sm text-red-500 mt-1 truncate">{job.error}</p>
                      )}
                      {isActive && (
                        <div className="mt-2 max-w-xs">
                          <ProgressBar value={job.progress} size="sm" />
                          <p className="text-xs text-slate-400 mt-1">{job.progress}%</p>
                        </div>
                      )}
                    </div>
                  </div>
                  <div className="flex items-center space-x-2 ml-4">
                    <button
                      onClick={() => handleViewDetail(job)}
                      className="btn-ghost text-sm"
                    >
                      Details
                    </button>
                    {isActive && (
                      <button
                        onClick={() => setCancellingId(job.id)}
                        className="btn-ghost text-sm text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-900/20"
                      >
                        <XCircle className="w-4 h-4 mr-1" />
                        Cancel
                      </button>
                    )}
                  </div>
                </div>
              </Card>
            );
          })}
        </div>
      )}

      {/* Cancel Confirmation */}
      <Modal
        isOpen={!!cancellingId}
        onClose={() => setCancellingId(null)}
        title="Cancel Job"
      >
        <div className="space-y-4">
          <p className="text-slate-600 dark:text-slate-300">
            Are you sure you want to cancel this job? This action cannot be undone.
          </p>
          <div className="flex justify-end space-x-3">
            <button onClick={() => setCancellingId(null)} className="btn-secondary">
              Keep Running
            </button>
            <button
              onClick={() => cancellingId && handleCancel(cancellingId)}
              className="btn-primary bg-red-600 hover:bg-red-700"
            >
              Cancel Job
            </button>
          </div>
        </div>
      </Modal>

      {/* Job Detail Modal */}
      <Modal
        isOpen={showDetailModal}
        onClose={() => { setShowDetailModal(false); setSelectedJob(null); }}
        title="Job Details"
        size="lg"
      >
        {selectedJob && (() => {
          const StatusIcon = getStatusIcon(selectedJob.status);
          const JobIcon = getJobIcon(selectedJob.type);
          const isActive = selectedJob.status === 'running' || selectedJob.status === 'pending';

          return (
            <div className="space-y-4">
              {/* Header */}
              <div className="flex items-center space-x-3">
                <div className="p-3 rounded-lg bg-primary-100 dark:bg-primary-900/30">
                  <JobIcon className="w-6 h-6 text-primary-600" />
                </div>
                <div>
                  <h3 className="text-lg font-semibold text-slate-900 dark:text-white">
                    {capitalize(selectedJob.type)} Job
                  </h3>
                  <div className="flex items-center space-x-2 mt-1">
                    <StatusIcon className={`w-4 h-4 ${
                      selectedJob.status === 'completed' ? 'text-green-500' :
                      selectedJob.status === 'failed' ? 'text-red-500' :
                      selectedJob.status === 'running' ? 'text-blue-500' :
                      'text-slate-400'
                    }`} />
                    <StatusBadge status={selectedJob.status} />
                  </div>
                </div>
              </div>

              {/* Progress */}
              {isActive && (
                <div>
                  <ProgressBar value={selectedJob.progress} size="lg" />
                  <p className="text-sm text-slate-500 dark:text-slate-400 text-center mt-2">
                    {selectedJob.progress}% complete
                  </p>
                </div>
              )}

              {/* Details */}
              <div className="bg-slate-50 dark:bg-slate-700/50 rounded-lg p-4 space-y-2">
                <div className="flex justify-between">
                  <span className="text-sm text-slate-500 dark:text-slate-400">Job ID</span>
                  <span className="text-sm font-mono text-slate-900 dark:text-white">{selectedJob.id}</span>
                </div>
                <div className="flex justify-between">
                  <span className="text-sm text-slate-500 dark:text-slate-400">Created</span>
                  <span className="text-sm text-slate-900 dark:text-white">{formatRelativeTime(selectedJob.created_at)}</span>
                </div>
                {selectedJob.started_at && (
                  <div className="flex justify-between">
                    <span className="text-sm text-slate-500 dark:text-slate-400">Started</span>
                    <span className="text-sm text-slate-900 dark:text-white">{formatRelativeTime(selectedJob.started_at)}</span>
                  </div>
                )}
                {selectedJob.completed_at && (
                  <div className="flex justify-between">
                    <span className="text-sm text-slate-500 dark:text-slate-400">Completed</span>
                    <span className="text-sm text-slate-900 dark:text-white">{formatRelativeTime(selectedJob.completed_at)}</span>
                  </div>
                )}
                {selectedJob.started_at && (
                  <div className="flex justify-between">
                    <span className="text-sm text-slate-500 dark:text-slate-400">Duration</span>
                    <span className="text-sm text-slate-900 dark:text-white">
                      {formatTimeBetween(selectedJob.started_at, selectedJob.completed_at)}
                    </span>
                  </div>
                )}
              </div>

              {/* Paths */}
              {selectedJob.paths && selectedJob.paths.length > 0 && (
                <div>
                  <h4 className="text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Paths</h4>
                  <div className="space-y-1">
                    {selectedJob.paths.map((p) => (
                      <p key={p} className="text-sm font-mono text-slate-600 dark:text-slate-400">{p}</p>
                    ))}
                  </div>
                </div>
              )}

              {/* Metadata */}
              {selectedJob.metadata && Object.keys(selectedJob.metadata).length > 0 && (
                <div>
                  <h4 className="text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Metadata</h4>
                  <pre className="text-xs font-mono bg-slate-100 dark:bg-slate-800 p-3 rounded-lg overflow-x-auto">
                    {JSON.stringify(selectedJob.metadata, null, 2)}
                  </pre>
                </div>
              )}

              {/* Error */}
              {selectedJob.error && (
                <Alert type="error" title="Error">
                  {selectedJob.error}
                </Alert>
              )}

              {/* Actions */}
              <div className="flex justify-end space-x-3 pt-2">
                <button onClick={() => { setShowDetailModal(false); setSelectedJob(null); }} className="btn-secondary">
                  Close
                </button>
                {isActive && (
                  <button
                    onClick={() => { setShowDetailModal(false); setCancellingId(selectedJob.id); }}
                    className="btn-primary bg-red-600 hover:bg-red-700"
                  >
                    Cancel Job
                  </button>
                )}
              </div>
            </div>
          );
        })()}
      </Modal>
    </div>
  );
}
