import { useState, useEffect, useRef, useCallback } from 'react';
import {
  Drawer,
  Input,
  Button,
  Space,
  Card,
  Tag,
  Progress,
  Typography,
  message,
  Empty,
  Collapse,
  List,
  Tooltip,
  Grid,
} from 'antd';
import {
  CloudDownloadOutlined,
  StopOutlined,
  ReloadOutlined,
  CheckCircleOutlined,
  CloseCircleOutlined,
  LoadingOutlined,
  ClockCircleOutlined,
  ExpandOutlined,
} from '@ant-design/icons';
import { mediaApi } from '@/lib/media-api';
import { getErrorMessage } from '@/utils/getErrorMessage';

const { TextArea } = Input;
const { Text } = Typography;

interface FetchJob {
  id: string;
  urls: string[];
  urlCount: number;
  state: string;
  progress: number;
  returnvalue: {
    results: Array<{
      url: string;
      success: boolean;
      videoId?: number;
      title?: string;
      error?: string;
    }>;
    totalUrls: number;
    successCount: number;
    failCount: number;
  } | null;
  failedReason: string | null;
  timestamp: number;
  finishedOn: number | null;
  processedOn: number | null;
}

interface FetchVideosDrawerProps {
  open: boolean;
  onClose: () => void;
  onSuccess?: () => void;
}

const STATE_COLORS: Record<string, string> = {
  active: 'processing',
  waiting: 'default',
  delayed: 'warning',
  completed: 'success',
  failed: 'error',
};

const STATE_ICONS: Record<string, React.ReactNode> = {
  active: <LoadingOutlined />,
  waiting: <ClockCircleOutlined />,
  completed: <CheckCircleOutlined />,
  failed: <CloseCircleOutlined />,
};

export default function FetchVideosDrawer({ open, onClose, onSuccess }: FetchVideosDrawerProps) {
  const [urls, setUrls] = useState('');
  const screens = Grid.useBreakpoint();
  const isMobile = !screens.md;
  const [submitting, setSubmitting] = useState(false);
  const [jobs, setJobs] = useState<FetchJob[]>([]);
  const [expandedJobId, setExpandedJobId] = useState<string | null>(null);
  const [logLines, setLogLines] = useState<string[]>([]);
  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const eventSourceRef = useRef<EventSource | null>(null);
  const logContainerRef = useRef<HTMLDivElement>(null);
  const prevCompletedRef = useRef<Set<string>>(new Set());

  // Poll for job updates
  const fetchJobs = useCallback(async () => {
    try {
      const { data } = await mediaApi.get<{ jobs: FetchJob[] }>('/videos/fetch/jobs');
      setJobs(data.jobs);

      // Check for newly completed jobs to trigger refresh
      const currentCompleted = new Set(
        data.jobs.filter(j => j.state === 'completed').map(j => j.id)
      );
      const prev = prevCompletedRef.current;
      for (const id of currentCompleted) {
        if (!prev.has(id)) {
          // A job just completed
          onSuccess?.();
          break;
        }
      }
      prevCompletedRef.current = currentCompleted;
    } catch (err) {
      // Silently ignore poll errors
    }
  }, [onSuccess]);

  useEffect(() => {
    if (open) {
      fetchJobs();
      pollRef.current = setInterval(fetchJobs, 3000);
    }

    return () => {
      if (pollRef.current) {
        clearInterval(pollRef.current);
        pollRef.current = null;
      }
    };
  }, [open, fetchJobs]);

  // SSE log connection
  useEffect(() => {
    if (!expandedJobId) {
      if (eventSourceRef.current) {
        eventSourceRef.current.close();
        eventSourceRef.current = null;
      }
      setLogLines([]);
      return;
    }

    // Construct SSE URL through the media API proxy
    const baseUrl = '/media/api/videos/fetch/jobs/' + expandedJobId + '/log';

    // We need the auth token for the SSE connection
    // Use fetch with EventSource-like manual parsing since ES doesn't support auth headers
    const controller = new AbortController();
    let cancelled = false;

    const connectSSE = async () => {
      try {
        // Get auth token from in-memory store (not localStorage)
        const { useAuthStore } = await import('@/stores/auth.store');
        const token = useAuthStore.getState().accessToken || '';

        const response = await fetch(baseUrl, {
          headers: {
            Authorization: `Bearer ${token}`,
            Accept: 'text/event-stream',
          },
          signal: controller.signal,
        });

        if (!response.ok || !response.body) {
          return;
        }

        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        let buffer = '';

        while (!cancelled) {
          const { done, value } = await reader.read();
          if (done) break;

          buffer += decoder.decode(value, { stream: true });
          const lines = buffer.split('\n');
          buffer = lines.pop() || '';

          for (const line of lines) {
            if (line.startsWith('data: ')) {
              const payload = line.slice(6);
              try {
                const parsed = JSON.parse(payload);
                if (parsed.type === 'log' && parsed.data) {
                  setLogLines(prev => [...prev, parsed.data]);
                } else if (parsed.type === 'status') {
                  // Job completed or failed
                  fetchJobs();
                }
              } catch {
                // Not JSON, might be raw text
              }
            } else if (line.startsWith('event: progress')) {
              // Progress events are handled by polling
            } else if (line.startsWith('event: done')) {
              fetchJobs();
            }
          }
        }
      } catch (err) {
        if (!cancelled) {
          // Connection error, will retry on next expand
        }
      }
    };

    setLogLines([]);
    connectSSE();

    return () => {
      cancelled = true;
      controller.abort();
    };
  }, [expandedJobId, fetchJobs]);

  // Auto-scroll log to bottom
  useEffect(() => {
    if (logContainerRef.current) {
      logContainerRef.current.scrollTop = logContainerRef.current.scrollHeight;
    }
  }, [logLines]);

  // Clean up on close
  useEffect(() => {
    if (!open) {
      setExpandedJobId(null);
      if (eventSourceRef.current) {
        eventSourceRef.current.close();
        eventSourceRef.current = null;
      }
    }
  }, [open]);

  const handleSubmit = async () => {
    const urlList = urls
      .split('\n')
      .map(u => u.trim())
      .filter(u => u.length > 0);

    if (urlList.length === 0) {
      message.warning('Please enter at least one URL');
      return;
    }

    if (urlList.length > 20) {
      message.error('Maximum 20 URLs per submission');
      return;
    }

    setSubmitting(true);
    try {
      const { data } = await mediaApi.post('/videos/fetch', { urls: urlList });
      message.success(`Fetch job submitted with ${data.urlCount} URL(s)`);
      setUrls('');
      // Immediately expand the new job
      setExpandedJobId(data.jobId);
      fetchJobs();
    } catch (err: unknown) {
      message.error(getErrorMessage(err, 'Failed to submit fetch job'));
    } finally {
      setSubmitting(false);
    }
  };

  const handleCancel = async (jobId: string) => {
    try {
      await mediaApi.delete(`/videos/fetch/jobs/${jobId}`);
      message.success('Job cancelled');
      fetchJobs();
    } catch (err: unknown) {
      message.error(getErrorMessage(err, 'Failed to cancel job'));
    }
  };

  const formatTime = (ts: number | null) => {
    if (!ts) return '-';
    return new Date(ts).toLocaleTimeString();
  };

  const activeJobs = jobs.filter(j => j.state === 'active' || j.state === 'waiting');
  const recentJobs = jobs.filter(j => j.state === 'completed' || j.state === 'failed');

  return (
    <Drawer
      title={
        <Space>
          <CloudDownloadOutlined />
          Fetch Videos
        </Space>
      }
      open={open}
      onClose={onClose}
      width={isMobile ? '100%' : 560}
      destroyOnClose
    >
      {/* URL Input Section */}
      <Card
        size="small"
        title="Download from URL"
        style={{ marginBottom: 16 }}
      >
        <TextArea
          rows={4}
          placeholder={'Paste video URLs here, one per line.\n\nSupports YouTube, Twitter/X, Reddit, Vimeo, and 1000+ sites via yt-dlp.'}
          value={urls}
          onChange={(e) => setUrls(e.target.value)}
          disabled={submitting}
          style={{ marginBottom: 12, fontFamily: 'monospace', fontSize: 12 }}
        />
        <Space>
          <Button
            type="primary"
            icon={<CloudDownloadOutlined />}
            loading={submitting}
            onClick={handleSubmit}
            disabled={!urls.trim()}
          >
            Fetch
          </Button>
          <Text type="secondary" style={{ fontSize: 12 }}>
            Max 20 URLs per submission
          </Text>
        </Space>
      </Card>

      {/* Active Jobs */}
      {activeJobs.length > 0 && (
        <Card
          size="small"
          title={`Active Jobs (${activeJobs.length})`}
          style={{ marginBottom: 16 }}
        >
          {activeJobs.map(job => (
            <div key={job.id} style={{ marginBottom: 12 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 4 }}>
                <Space size="small">
                  <Tag color={STATE_COLORS[job.state]} icon={STATE_ICONS[job.state]}>
                    {job.state}
                  </Tag>
                  <Text type="secondary" style={{ fontSize: 12 }}>
                    {job.urlCount} URL{job.urlCount !== 1 ? 's' : ''}
                  </Text>
                </Space>
                <Space size="small">
                  <Tooltip title={expandedJobId === job.id ? 'Collapse log' : 'Expand log'}>
                    <Button
                      size="small"
                      type="text"
                      icon={<ExpandOutlined />}
                      onClick={() => setExpandedJobId(expandedJobId === job.id ? null : job.id)}
                    />
                  </Tooltip>
                  <Button
                    size="small"
                    danger
                    icon={<StopOutlined />}
                    onClick={() => handleCancel(job.id)}
                  >
                    Cancel
                  </Button>
                </Space>
              </div>
              {job.state === 'active' && (
                <Progress
                  percent={job.progress || 0}
                  size="small"
                  status="active"
                />
              )}
              {/* Log viewer */}
              {expandedJobId === job.id && (
                <div
                  ref={logContainerRef}
                  style={{
                    marginTop: 8,
                    maxHeight: 300,
                    overflow: 'auto',
                    background: '#1a1a2e',
                    borderRadius: 4,
                    padding: 8,
                    fontFamily: 'monospace',
                    fontSize: 11,
                    lineHeight: 1.5,
                    color: '#e0e0e0',
                  }}
                >
                  {logLines.length === 0 ? (
                    <Text type="secondary" style={{ fontSize: 11 }}>Waiting for output...</Text>
                  ) : (
                    logLines.map((line, i) => (
                      <div key={i} style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all' }}>
                        {line.startsWith('[stderr]') ? (
                          <span style={{ color: '#ff6b6b' }}>{line}</span>
                        ) : line.startsWith('FAILED:') ? (
                          <span style={{ color: '#ff6b6b' }}>{line}</span>
                        ) : line.startsWith('---') ? (
                          <span style={{ color: '#74b9ff' }}>{line}</span>
                        ) : line.includes('Imported as video') ? (
                          <span style={{ color: '#55efc4' }}>{line}</span>
                        ) : (
                          line
                        )}
                      </div>
                    ))
                  )}
                </div>
              )}
              {/* URL list */}
              <div style={{ marginTop: 4 }}>
                {job.urls.slice(0, 3).map((url, i) => (
                  <Text key={i} type="secondary" ellipsis style={{ display: 'block', fontSize: 11 }}>
                    {url}
                  </Text>
                ))}
                {job.urls.length > 3 && (
                  <Text type="secondary" style={{ fontSize: 11 }}>
                    ...and {job.urls.length - 3} more
                  </Text>
                )}
              </div>
            </div>
          ))}
        </Card>
      )}

      {/* Recent Jobs */}
      {recentJobs.length > 0 && (
        <Card size="small" title="Recent Jobs">
          <Collapse
            accordion
            ghost
            activeKey={expandedJobId && recentJobs.some(j => j.id === expandedJobId) ? expandedJobId : undefined}
            onChange={(key) => setExpandedJobId(typeof key === 'string' ? key : key?.[0] || null)}
            items={recentJobs.map(job => ({
              key: job.id,
              label: (
                <Space>
                  <Tag color={STATE_COLORS[job.state]} icon={STATE_ICONS[job.state]}>
                    {job.state}
                  </Tag>
                  <Text type="secondary" style={{ fontSize: 12 }}>
                    {job.urlCount} URL{job.urlCount !== 1 ? 's' : ''}
                    {job.returnvalue && (
                      <> — {job.returnvalue.successCount} ok, {job.returnvalue.failCount} failed</>
                    )}
                  </Text>
                  <Text type="secondary" style={{ fontSize: 11 }}>
                    {formatTime(job.finishedOn || job.timestamp)}
                  </Text>
                </Space>
              ),
              children: (
                <div>
                  {/* Results list */}
                  {job.returnvalue?.results && (
                    <List
                      size="small"
                      dataSource={job.returnvalue.results}
                      renderItem={(result) => (
                        <List.Item>
                          <Space direction="vertical" size={0} style={{ width: '100%' }}>
                            <Text ellipsis style={{ fontSize: 12, maxWidth: 450 }}>
                              {result.url}
                            </Text>
                            {result.success ? (
                              <Tag color="success" style={{ fontSize: 11 }}>
                                Imported: {result.title || `Video #${result.videoId}`}
                              </Tag>
                            ) : (
                              <Tag color="error" style={{ fontSize: 11 }}>
                                {result.error || 'Unknown error'}
                              </Tag>
                            )}
                          </Space>
                        </List.Item>
                      )}
                    />
                  )}
                  {job.failedReason && (
                    <Text type="danger" style={{ fontSize: 12 }}>
                      {job.failedReason}
                    </Text>
                  )}
                  {/* Log viewer for recent jobs */}
                  {expandedJobId === job.id && logLines.length > 0 && (
                    <div
                      ref={logContainerRef}
                      style={{
                        marginTop: 8,
                        maxHeight: 200,
                        overflow: 'auto',
                        background: '#1a1a2e',
                        borderRadius: 4,
                        padding: 8,
                        fontFamily: 'monospace',
                        fontSize: 11,
                        lineHeight: 1.5,
                        color: '#e0e0e0',
                      }}
                    >
                      {logLines.map((line, i) => (
                        <div key={i} style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all' }}>
                          {line}
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              ),
            }))}
          />
        </Card>
      )}

      {/* Empty state */}
      {jobs.length === 0 && !submitting && (
        <Empty
          description="No fetch jobs yet"
          style={{ marginTop: 32 }}
        />
      )}

      {/* Refresh button */}
      {jobs.length > 0 && (
        <div style={{ textAlign: 'center', marginTop: 16 }}>
          <Button
            type="text"
            icon={<ReloadOutlined />}
            onClick={fetchJobs}
            size="small"
          >
            Refresh
          </Button>
        </div>
      )}
    </Drawer>
  );
}
