import { useCallback, useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Card } from 'primereact/card';
import { Button } from 'primereact/button';
import { InputText } from 'primereact/inputtext';
import { Tag } from 'primereact/tag';
import { Paginator } from 'primereact/paginator';
import { api } from '../api/client';
import { classifyJob } from '../utils/jobTaxonomy';
import { getStatusLabel, getStatusSeverity, normalizeStatus } from '../utils/statusPresentation';

const ACTIVE_STATUSES = [
  'ANALYZING',
  'METADATA_SELECTION',
  'WAITING_FOR_USER_DECISION',
  'READY_TO_START',
  'MEDIAINFO_CHECK',
  'READY_TO_ENCODE',
  'RIPPING',
  'ENCODING',
  'CD_METADATA_SELECTION',
  'CD_READY_TO_RIP',
  'CD_ANALYZING',
  'CD_RIPPING',
  'CD_ENCODING'
];

const STATUS_FILTERS = [
  { key: 'all', label: 'Alle' },
  { key: 'active', label: 'Aktiv' },
  { key: 'errors', label: 'Fehler/Abbruch' }
];

const VIEW_FILTERS = [
  { key: 'all', label: 'Alle Jobs' },
  { key: 'ripper', label: 'Ripper-View' },
  { key: 'converter', label: 'Converter-View' },
  { key: 'audiobook', label: 'Audiobooks' }
];

function normalizeJobId(value) {
  const parsed = Number(value);
  if (!Number.isFinite(parsed) || parsed <= 0) {
    return null;
  }
  return Math.trunc(parsed);
}

function formatUpdatedAt(value) {
  if (!value) {
    return '-';
  }
  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) {
    return '-';
  }
  return parsed.toLocaleString('de-DE');
}

function getKindLabel(meta) {
  if (meta.family === 'converter') {
    if (meta.converterMediaType === 'audio') {
      return 'Converter Audio';
    }
    if (meta.converterMediaType === 'iso') {
      return 'Converter ISO';
    }
    return 'Converter Video';
  }
  if (meta.family === 'audiobook') {
    return 'Audiobook';
  }
  if (meta.mediaType === 'bluray') {
    return 'Blu-ray';
  }
  if (meta.mediaType === 'dvd') {
    return 'DVD';
  }
  if (meta.mediaType === 'cd') {
    return 'CD';
  }
  return 'Sonstiges';
}

function getKindSeverity(meta) {
  if (meta.family === 'converter') {
    return 'info';
  }
  if (meta.family === 'audiobook') {
    return 'warning';
  }
  if (meta.mediaType === 'bluray' || meta.mediaType === 'dvd') {
    return 'success';
  }
  return 'secondary';
}

export default function JobsInboxPage() {
  const navigate = useNavigate();
  const [jobs, setJobs] = useState([]);
  const [loading, setLoading] = useState(false);
  const [viewFilter, setViewFilter] = useState('all');
  const [statusFilter, setStatusFilter] = useState('all');
  const [search, setSearch] = useState('');
  const [queuedJobIds, setQueuedJobIds] = useState(new Set());
  const [lastUpdatedAt, setLastUpdatedAt] = useState(null);
  const [first, setFirst] = useState(0);
  const [rows, setRows] = useState(25);

  const loadJobs = useCallback(async () => {
    setLoading(true);
    try {
      const query = { limit: 500, lite: true };
      if (statusFilter === 'active') {
        query.statuses = ACTIVE_STATUSES;
      } else if (statusFilter === 'errors') {
        query.statuses = ['ERROR', 'CANCELLED'];
      }

      const [jobsResponse, queueResponse] = await Promise.allSettled([
        api.getJobs(query),
        api.getPipelineQueue()
      ]);

      const nextJobs = jobsResponse.status === 'fulfilled' && Array.isArray(jobsResponse.value?.jobs)
        ? jobsResponse.value.jobs
        : [];
      setJobs(nextJobs);

      if (queueResponse.status === 'fulfilled') {
        const rows = Array.isArray(queueResponse.value?.queue?.queuedJobs)
          ? queueResponse.value.queue.queuedJobs
          : [];
        setQueuedJobIds(new Set(rows.map((item) => normalizeJobId(item?.jobId)).filter(Boolean)));
      } else {
        setQueuedJobIds(new Set());
      }
      setLastUpdatedAt(new Date().toISOString());
    } finally {
      setLoading(false);
    }
  }, [statusFilter]);

  useEffect(() => {
    loadJobs();
    const interval = setInterval(() => {
      loadJobs().catch(() => null);
    }, 7000);
    return () => clearInterval(interval);
  }, [loadJobs]);

  const jobsWithMeta = useMemo(() => (
    jobs.map((job) => ({
      job,
      meta: classifyJob(job)
    }))
  ), [jobs]);

  const viewCounts = useMemo(() => {
    let all = 0;
    let ripper = 0;
    let converter = 0;
    let audiobook = 0;
    for (const item of jobsWithMeta) {
      all += 1;
      if (item.meta.family === 'converter') {
        converter += 1;
      } else {
        ripper += 1;
      }
      if (item.meta.family === 'audiobook') {
        audiobook += 1;
      }
    }
    return { all, ripper, converter, audiobook };
  }, [jobsWithMeta]);

  const filteredRows = useMemo(() => {
    const normalizedSearch = String(search || '').trim().toLowerCase();
    return jobsWithMeta.filter(({ job, meta }) => {
      if (viewFilter === 'ripper' && meta.family === 'converter') {
        return false;
      }
      if (viewFilter === 'converter' && meta.family !== 'converter') {
        return false;
      }
      if (viewFilter === 'audiobook' && meta.family !== 'audiobook') {
        return false;
      }

      if (!normalizedSearch) {
        return true;
      }
      const haystack = [
        job?.title,
        job?.detected_title,
        job?.imdb_id,
        job?.status,
        job?.job_kind,
        job?.media_type
      ]
        .map((value) => String(value || '').trim().toLowerCase())
        .filter(Boolean)
        .join(' ');
      return haystack.includes(normalizedSearch);
    });
  }, [jobsWithMeta, search, viewFilter]);

  useEffect(() => {
    setFirst(0);
  }, [viewFilter, statusFilter, search]);

  useEffect(() => {
    if (filteredRows.length === 0) {
      if (first !== 0) {
        setFirst(0);
      }
      return;
    }
    if (first >= filteredRows.length) {
      const pageStart = Math.max(0, Math.floor((filteredRows.length - 1) / rows) * rows);
      setFirst(pageStart);
    }
  }, [filteredRows.length, first, rows]);

  const pagedRows = useMemo(
    () => filteredRows.slice(first, first + rows),
    [filteredRows, first, rows]
  );

  return (
    <Card
      title="Job Inbox"
      subTitle="Zentrale Jobliste mit denselben Datensätzen für Ripper-, Converter- und Audiobook-Sicht."
    >
      <div className="job-inbox-toolbar">
        <div className="job-inbox-filter-row">
          {VIEW_FILTERS.map((filter) => {
            const isActive = filter.key === viewFilter;
            const count = viewCounts[filter.key] ?? 0;
            return (
              <Button
                key={filter.key}
                label={`${filter.label} (${count})`}
                className={isActive ? 'job-inbox-filter-active' : 'job-inbox-filter'}
                outlined={!isActive}
                onClick={() => setViewFilter(filter.key)}
                size="small"
              />
            );
          })}
        </div>
        <div className="job-inbox-filter-row">
          {STATUS_FILTERS.map((filter) => {
            const isActive = filter.key === statusFilter;
            return (
              <Button
                key={filter.key}
                label={filter.label}
                className={isActive ? 'job-inbox-filter-active' : 'job-inbox-filter'}
                outlined={!isActive}
                onClick={() => setStatusFilter(filter.key)}
                size="small"
              />
            );
          })}
          <Button
            label="Aktualisieren"
            icon="pi pi-refresh"
            outlined
            size="small"
            loading={loading}
            onClick={() => {
              loadJobs().catch(() => null);
            }}
          />
        </div>
      </div>

      <div className="job-inbox-search-row">
        <InputText
          value={search}
          onChange={(event) => setSearch(event.target.value)}
          placeholder="Suche nach Titel, Status oder IMDB-ID"
          className="job-inbox-search-input"
        />
        <small>
          Letztes Update: {formatUpdatedAt(lastUpdatedAt)} | Treffer: {filteredRows.length}
        </small>
      </div>

      <div className="job-inbox-list">
        {loading && filteredRows.length === 0 ? (
          <p>Inbox wird geladen ...</p>
        ) : filteredRows.length === 0 ? (
          <p>Keine Jobs für den aktuellen Filter gefunden.</p>
        ) : (
          pagedRows.map(({ job, meta }) => {
            const jobId = normalizeJobId(job?.id);
            if (!jobId) {
              return null;
            }
            const isQueued = queuedJobIds.has(jobId);
            const normalizedStatus = normalizeStatus(job?.status);
            const targetPath = meta.family === 'converter' ? '/converter' : '/ripper';
            const jobTitle = String(job?.title || job?.detected_title || '').trim() || `Job #${jobId}`;
            return (
              <article key={jobId} className="job-inbox-row">
                <div className="job-inbox-row-main">
                  <strong>#{jobId} | {jobTitle}</strong>
                  <small>
                    Status: {getStatusLabel(normalizedStatus, { queued: isQueued })}
                    {' | '}
                    Aktualisiert: {formatUpdatedAt(job?.updated_at || job?.created_at || null)}
                  </small>
                </div>
                <div className="job-inbox-row-tags">
                  <Tag value={getKindLabel(meta)} severity={getKindSeverity(meta)} />
                  <Tag
                    value={getStatusLabel(normalizedStatus, { queued: isQueued })}
                    severity={getStatusSeverity(normalizedStatus, { queued: isQueued })}
                  />
                </div>
                <div className="job-inbox-row-actions">
                  <Button
                    label={meta.family === 'converter' ? 'Im Converter öffnen' : 'Im Ripper öffnen'}
                    icon={meta.family === 'converter' ? 'pi pi-external-link' : 'pi pi-arrow-right'}
                    outlined
                    size="small"
                    onClick={() => navigate(targetPath)}
                  />
                </div>
              </article>
            );
          })
        )}
      </div>

      {filteredRows.length > 0 ? (
        <div className="job-inbox-pagination">
          <Paginator
            first={first}
            rows={rows}
            totalRecords={filteredRows.length}
            rowsPerPageOptions={[25, 50, 100]}
            onPageChange={(event) => {
              setFirst(event.first);
              setRows(event.rows);
            }}
            template="PrevPageLink PageLinks NextPageLink RowsPerPageDropdown CurrentPageReport"
            currentPageReportTemplate="{first} - {last} von {totalRecords}"
          />
        </div>
      ) : null}
    </Card>
  );
}
