import React, { useEffect, useState, useCallback } from 'react';
import {
  Box, Table, TableBody, TableCell, TableContainer, TableHead, TableRow,
  Paper, Checkbox, FormControl, InputLabel, Select, MenuItem, ToggleButtonGroup,
  ToggleButton, Button, CircularProgress, TablePagination, Typography, Chip, Tooltip,
} from '@mui/material';
import { adminService } from '../../api/adminService';
import type { MissingMediaRecord, MissingMediaSummary, MissingMediaFilter } from '../../api/adminService';
import { accountService } from '../../api/accountService';
import { useToastStore } from '../../store/toastStore';

interface Organization {
  org_id: string;
  org_name: string;
  db_name: string;
}

const PAGE_SIZE = 25;

const missingColor = (missing: string): 'default' | 'warning' | 'error' => {
  if (missing === 'not checked yet') return 'default';
  if (missing === 'video') return 'warning';
  return 'error'; // image or image + video - definitely unauditable
};

export const MissingMedia: React.FC = () => {
  const [organizations, setOrganizations] = useState<Organization[]>([]);
  const [dbName, setDbName] = useState('');
  const [type, setType] = useState<'audits' | 'rectification'>('audits');
  const [missing, setMissing] = useState<'all' | MissingMediaFilter>('all');
  const [records, setRecords] = useState<MissingMediaRecord[]>([]);
  const [summary, setSummary] = useState<MissingMediaSummary | null>(null);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(0);
  const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set());
  const [loading, setLoading] = useState(false);
  const [rechecking, setRechecking] = useState(false);

  useEffect(() => {
    (async () => {
      try {
        const orgs = ((await accountService.getOrganizations()) as any) || [];
        setOrganizations(orgs);
        if (orgs.length > 0) setDbName(orgs[0].db_name);
      } catch {
        useToastStore.getState().showToast('Failed to load organizations.', 'error');
      }
    })();
  }, []);

  const load = useCallback(async () => {
    if (!dbName) return;
    setLoading(true);
    try {
      const result = await adminService.getMissingMedia({
        dbName, type, limit: PAGE_SIZE, offset: page * PAGE_SIZE,
        ...(missing !== 'all' ? { missing } : {}),
      });
      setRecords(result.records);
      setTotal(result.total);
      setSummary(result.summary);
      // A recheck under an active filter can shrink the filtered total below
      // the current page - snap back instead of stranding on an empty page.
      if (page > 0 && result.total <= page * PAGE_SIZE) setPage(0);
    } catch {
      useToastStore.getState().showToast('Failed to load missing-media records.', 'error');
    } finally {
      setLoading(false);
    }
  }, [dbName, type, page, missing]);

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

  useEffect(() => {
    setPage(0);
    setSelectedIds(new Set());
  }, [dbName, type, missing]);

  const toggleRow = (id: number) => {
    setSelectedIds((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  };

  const toggleAll = () => {
    setSelectedIds(selectedIds.size === records.length ? new Set() : new Set(records.map((r) => r.id)));
  };

  const handleRecheck = async (ids: number[]) => {
    setRechecking(true);
    try {
      const result = await adminService.recheckMedia({ dbName, type, ids });
      useToastStore.getState().showToast(
        `Rechecked ${result.checked}: ${result.ready} now ready, ${result.missing} still missing${result.skipped ? `, ${result.skipped} unreachable` : ''}.`,
        result.ready > 0 ? 'success' : 'info'
      );
      setSelectedIds(new Set());
      load();
    } catch (err: any) {
      useToastStore.getState().showToast(err?.response?.data?.message || 'Recheck failed.', 'error');
    } finally {
      setRechecking(false);
    }
  };

  const summaryChip = (label: string, value: number | undefined, color: 'default' | 'warning' | 'error' | 'info') => (
    <Chip label={`${label}: ${value ?? '…'}`} color={color === 'default' ? undefined : color} variant="outlined" />
  );

  return (
    <Box>
      <Box sx={{ display: 'flex', gap: 2, mb: 2, flexWrap: 'wrap', alignItems: 'center' }}>
        <FormControl size="small" sx={{ minWidth: 180 }}>
          <InputLabel>Organization</InputLabel>
          <Select label="Organization" value={dbName} onChange={(e) => setDbName(e.target.value)}>
            {organizations.map((o) => <MenuItem key={o.org_id} value={o.db_name}>{o.org_name}</MenuItem>)}
          </Select>
        </FormControl>

        <ToggleButtonGroup value={type} exclusive onChange={(_, v) => v && setType(v)} size="small">
          <ToggleButton value="audits">Audits</ToggleButton>
          <ToggleButton value="rectification">Rectification</ToggleButton>
        </ToggleButtonGroup>

        <ToggleButtonGroup value={missing} exclusive onChange={(_, v) => v && setMissing(v)} size="small">
          <ToggleButton value="all">All</ToggleButton>
          <ToggleButton value="image">Image missing</ToggleButton>
          <ToggleButton value="video">Video missing</ToggleButton>
          <ToggleButton value="both">Both missing</ToggleButton>
        </ToggleButtonGroup>

        <Button
          variant="contained"
          disabled={selectedIds.size === 0 || selectedIds.size > 50 || rechecking}
          onClick={() => handleRecheck(Array.from(selectedIds))}
        >
          {rechecking ? <CircularProgress size={20} sx={{ color: 'white' }} /> : `Recheck selected (${selectedIds.size})`}
        </Button>
        <Typography variant="caption" sx={{ color: 'text.secondary' }}>
          max 50 at a time — the 15-min cron keeps checking the rest automatically
        </Typography>
      </Box>

      <Box sx={{ display: 'flex', gap: 1.5, mb: 2, flexWrap: 'wrap' }}>
        {summaryChip('Hidden from auditing', summary?.total, 'error')}
        {summaryChip('Not checked yet', summary?.neverChecked, 'default')}
        {summaryChip('Image missing', summary?.missingImage, 'error')}
        {summaryChip('Video missing', summary?.missingVideo, 'warning')}
        {summaryChip('Both missing', summary?.missingBoth, 'error')}
        {summaryChip('Gave up (24h of retries)', summary?.gaveUp, 'info')}
      </Box>

      {loading ? (
        <Box sx={{ display: 'flex', justifyContent: 'center', p: 4 }}><CircularProgress /></Box>
      ) : (
        <TableContainer component={Paper}>
          <Table size="small">
            <TableHead>
              <TableRow>
                <TableCell padding="checkbox">
                  <Checkbox
                    checked={records.length > 0 && selectedIds.size === records.length}
                    indeterminate={selectedIds.size > 0 && selectedIds.size < records.length}
                    onChange={toggleAll}
                  />
                </TableCell>
                <TableCell>Record ID</TableCell>
                <TableCell>Asset</TableCell>
                <TableCell>Plaza</TableCell>
                <TableCell>Site</TableCell>
                <TableCell>Video Date</TableCell>
                <TableCell>Missing</TableCell>
                <TableCell align="right">Checks</TableCell>
                <TableCell>Last Checked</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {records.length === 0 && (
                <TableRow>
                  <TableCell colSpan={9} align="center" sx={{ color: 'text.secondary' }}>
                    {missing !== 'all'
                      ? 'No records match this filter.'
                      : 'No pending records with missing media — everything is auditable. 🎉'}
                  </TableCell>
                </TableRow>
              )}
              {records.map((r) => (
                <TableRow key={r.id} selected={selectedIds.has(r.id)}>
                  <TableCell padding="checkbox">
                    <Checkbox checked={selectedIds.has(r.id)} onChange={() => toggleRow(r.id)} />
                  </TableCell>
                  <TableCell>{r.id}</TableCell>
                  <TableCell>{r.Asset || '—'}</TableCell>
                  <TableCell>{r.Plaza || '—'}</TableCell>
                  <TableCell>{r.site_id}</TableCell>
                  <TableCell>{r.video_date ? new Date(r.video_date).toLocaleDateString() : '—'}</TableCell>
                  <TableCell>
                    <Chip size="small" label={r.missing} color={missingColor(r.missing)} />
                    {!r.has_video_declared && (
                      <Tooltip title="Record declares no video, so only the image gates it">
                        <Chip size="small" label="no video declared" variant="outlined" sx={{ ml: 0.5 }} />
                      </Tooltip>
                    )}
                  </TableCell>
                  <TableCell align="right">
                    {r.media_check_count >= 96 ? (
                      <Tooltip title="Gave up after ~24h of retries — use Recheck to resume">
                        <Chip size="small" label={r.media_check_count} color="warning" />
                      </Tooltip>
                    ) : r.media_check_count}
                  </TableCell>
                  <TableCell>{r.media_checked_at ? new Date(r.media_checked_at).toLocaleString() : 'never'}</TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
          <TablePagination
            component="div"
            count={total}
            page={page}
            onPageChange={(_, newPage) => setPage(newPage)}
            rowsPerPage={PAGE_SIZE}
            rowsPerPageOptions={[PAGE_SIZE]}
          />
        </TableContainer>
      )}
    </Box>
  );
};
