import React, { useEffect, useState, useCallback } from 'react';
import {
  Box, Table, TableBody, TableCell, TableContainer, TableHead, TableRow,
  Paper, TextField, FormControl, InputLabel, Select, MenuItem, CircularProgress,
  Chip, TablePagination, Link, Tooltip, Button,
} from '@mui/material';
import { adminService } from '../../api/adminService';
import type { DevTicket } from '../../api/adminService';
import { useToastStore } from '../../store/toastStore';
import { RecordDetailsDialog } from './RecordDetailsDialog';

const PAGE_SIZE = 25;

const gitStatusColor = (status: DevTicket['git_status']): 'success' | 'warning' | 'error' => {
  if (status === 'success') return 'success';
  if (status === 'failed') return 'error';
  return 'warning';
};

// One unified lifecycle: a ticket is Resolved (from the UI or by closing
// the Gitea issue), or its record is still Under Review / already handled.
const statusChip = (t: DevTicket) => {
  if (t.resolved_at) {
    return (
      <Tooltip title={`Resolved by ${t.resolved_by || '—'} · ${new Date(t.resolved_at).toLocaleString()}`}>
        <Chip size="small" label="Resolved" color="success" />
      </Tooltip>
    );
  }
  switch (t.record_status) {
    case 'under_review': return <Chip size="small" label="Under Review" color="warning" />;
    case 'resolved': return <Chip size="small" label="Back in feed" color="success" variant="outlined" />;
    case 'audited': return <Chip size="small" label="Audited" color="info" />;
    case 'deleted': return <Chip size="small" label="Deleted" color="default" />;
    default:
      return (
        <Tooltip title="Record not found or its org DB is unreachable">
          <Chip size="small" label="Unknown" variant="outlined" />
        </Tooltip>
      );
  }
};

const truncate = (text: string, max = 80) => (text.length > max ? `${text.slice(0, max)}…` : text);

export const DevTickets: React.FC = () => {
  const [search, setSearch] = useState('');
  const [gitStatus, setGitStatus] = useState<'' | 'pending' | 'success' | 'failed'>('');
  const [dateFrom, setDateFrom] = useState('');
  const [dateTo, setDateTo] = useState('');
  const [records, setRecords] = useState<DevTicket[]>([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(0);
  const [loading, setLoading] = useState(false);

  // dateTo is a bare date; created_at is a full timestamp, and both fields
  // are independently editable, so normalize the order and extend "to" to
  // end-of-day - see Allocation.tsx/AuditHistory.tsx for the same fix after
  // hitting this exact bug there (an inverted range silently matches zero
  // rows instead of erroring).
  const [effectiveDateFrom, effectiveDateTo] = (() => {
    if (!dateFrom || !dateTo) return [dateFrom || undefined, dateTo ? `${dateTo}T23:59:59` : undefined];
    return dateFrom <= dateTo
      ? [dateFrom, `${dateTo}T23:59:59`]
      : [dateTo, `${dateFrom}T23:59:59`];
  })();

  // Live Gitea issue state (open/closed) - git_status only ever records
  // whether we succeeded in *filing* the issue, never what happened to it
  // afterward, so this is fetched separately from the main list.
  const [issueStates, setIssueStates] = useState<Record<number, 'open' | 'closed' | null>>({});
  const [issueStatesLoading, setIssueStatesLoading] = useState(false);
  const [resolvingId, setResolvingId] = useState<number | null>(null);
  const [detailsTicket, setDetailsTicket] = useState<DevTicket | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const result = await adminService.getDevTickets({
        search: search || undefined,
        gitStatus: gitStatus || undefined,
        dateFrom: effectiveDateFrom,
        dateTo: effectiveDateTo,
        limit: PAGE_SIZE,
        offset: page * PAGE_SIZE,
      });
      setRecords(result.records);
      setTotal(result.total);
    } catch (err) {
      useToastStore.getState().showToast('Failed to load dev tickets.', 'error');
    } finally {
      setLoading(false);
    }
  }, [search, gitStatus, effectiveDateFrom, effectiveDateTo, page]);

  useEffect(() => {
    const timeout = setTimeout(load, 300);
    return () => clearTimeout(timeout);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [search, gitStatus, effectiveDateFrom, effectiveDateTo, page]);

  useEffect(() => {
    setPage(0);
  }, [search, gitStatus, effectiveDateFrom, effectiveDateTo]);

  useEffect(() => {
    // Keyed by ticket id, not issue number - the backend resolves each
    // ticket's own stored git_issue_url, so this stays correct even for
    // tickets filed before a repo migration.
    const ticketIds = records
      .filter((t) => t.git_status === 'success' && t.git_issue_number != null)
      .map((t) => t.id);

    if (ticketIds.length === 0) {
      setIssueStates({});
      return;
    }

    setIssueStatesLoading(true);
    adminService.getIssueStates(ticketIds)
      .then(setIssueStates)
      .catch(() => useToastStore.getState().showToast('Failed to check live Gitea issue status.', 'error'))
      .finally(() => setIssueStatesLoading(false));
  }, [records]);

  const handleResolve = async (t: DevTicket) => {
    setResolvingId(t.id);
    try {
      const res = await adminService.resolveTicket(t.id);
      useToastStore.getState().showToast(
        res.recordReleased
          ? `Resolved — record #${t.anomaly_id} returned to the feed${res.issueClosed ? ', git issue closed' : ''}.`
          : `Resolved — record was already handled${res.issueClosed ? '; git issue closed' : ''}.`,
        'success'
      );
      load();
    } catch (err: any) {
      useToastStore.getState().showToast(err?.response?.data?.message || 'Failed to resolve ticket.', 'error');
    } finally {
      setResolvingId(null);
    }
  };

  return (
    <Box>
      <Box sx={{ display: 'flex', gap: 2, mb: 3, flexWrap: 'wrap', alignItems: 'center' }}>
        <TextField
          label="Search (dev, reporter, message, anomaly ID)"
          size="small"
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          sx={{ minWidth: 300 }}
        />
        <FormControl size="small" sx={{ minWidth: 160 }}>
          <InputLabel>Git status</InputLabel>
          <Select label="Git status" value={gitStatus} onChange={(e) => setGitStatus(e.target.value as any)}>
            <MenuItem value="">All</MenuItem>
            <MenuItem value="pending">Pending</MenuItem>
            <MenuItem value="success">Success</MenuItem>
            <MenuItem value="failed">Failed</MenuItem>
          </Select>
        </FormControl>
        <TextField
          label="Created from"
          type="date"
          size="small"
          value={dateFrom}
          onChange={(e) => setDateFrom(e.target.value)}
          slotProps={{ inputLabel: { shrink: true } }}
        />
        <TextField
          label="Created to"
          type="date"
          size="small"
          value={dateTo}
          onChange={(e) => setDateTo(e.target.value)}
          slotProps={{ inputLabel: { shrink: true } }}
        />
      </Box>

      {loading ? (
        <Box sx={{ display: 'flex', justifyContent: 'center', p: 4 }}><CircularProgress /></Box>
      ) : (
        <TableContainer component={Paper}>
          <Table size="small">
            <TableHead>
              <TableRow>
                <TableCell>Anomaly ID</TableCell>
                <TableCell>Org</TableCell>
                <TableCell>Asset / Plaza</TableCell>
                <TableCell>Dev</TableCell>
                <TableCell>Reporter</TableCell>
                <TableCell>Message</TableCell>
                <TableCell>RocketChat</TableCell>
                <TableCell>Git</TableCell>
                <TableCell>Issue status</TableCell>
                <TableCell>Status</TableCell>
                <TableCell>Created</TableCell>
                <TableCell align="right">Action</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {records.length === 0 && (
                <TableRow>
                  <TableCell colSpan={12} align="center" sx={{ color: 'text.secondary' }}>
                    No dev tickets found.
                  </TableCell>
                </TableRow>
              )}
              {records.map((t) => {
                const liveState = t.git_status === 'success' && t.git_issue_number != null ? issueStates[t.id] : undefined;
                return (
                  <TableRow
                    key={t.id}
                    hover
                    onClick={() => setDetailsTicket(t)}
                    sx={{ cursor: 'pointer' }}
                  >
                    <TableCell>{t.anomaly_id}</TableCell>
                    <TableCell>{t.org_db_name || '—'}</TableCell>
                    <TableCell>{[t.asset, t.plaza].filter(Boolean).join(' / ') || '—'}</TableCell>
                    <TableCell>@{t.dev_handle}</TableCell>
                    <TableCell>{t.reporter || '—'}</TableCell>
                    <TableCell>
                      <Tooltip title={t.message_text}>
                        <span>{truncate(t.message_text)}</span>
                      </Tooltip>
                      {t.duplicate_of_id && (
                        <Chip size="small" label={`dup of #${t.duplicate_of_id}`} sx={{ ml: 1 }} variant="outlined" />
                      )}
                    </TableCell>
                    <TableCell>
                      {t.rocketchat_sent ? (
                        <Chip size="small" label="Sent" color="success" />
                      ) : (
                        <Tooltip title={t.rocketchat_error || 'Not sent'}>
                          <Chip size="small" label="Failed" color="error" />
                        </Tooltip>
                      )}
                    </TableCell>
                    <TableCell onClick={(e) => e.stopPropagation()}>
                      {t.git_issue_url ? (
                        <Link href={t.git_issue_url} target="_blank" rel="noopener noreferrer">
                          <Chip size="small" label={`#${t.git_issue_number}`} color={gitStatusColor(t.git_status)} clickable />
                        </Link>
                      ) : (
                        <Tooltip title={t.git_error || ''}>
                          <Chip size="small" label={t.git_status} color={gitStatusColor(t.git_status)} />
                        </Tooltip>
                      )}
                      {t.retry_count > 0 && (
                        <Chip size="small" label={`retries: ${t.retry_count}`} sx={{ ml: 1 }} variant="outlined" />
                      )}
                    </TableCell>
                    <TableCell>
                      {t.git_status !== 'success' ? (
                        '—'
                      ) : issueStatesLoading && liveState === undefined ? (
                        <CircularProgress size={14} />
                      ) : liveState === 'closed' ? (
                        <Chip size="small" label="Closed" color="default" />
                      ) : liveState === 'open' ? (
                        <Chip size="small" label="Open" color="info" />
                      ) : (
                        <Tooltip title="Could not reach Gitea to check">
                          <Chip size="small" label="Unknown" variant="outlined" />
                        </Tooltip>
                      )}
                    </TableCell>
                    <TableCell>{statusChip(t)}</TableCell>
                    <TableCell>{new Date(t.created_at).toLocaleString()}</TableCell>
                    <TableCell align="right" onClick={(e) => e.stopPropagation()}>
                      <Button
                        size="small"
                        variant="outlined"
                        disabled={!!t.resolved_at || t.record_status !== 'under_review' || resolvingId === t.id}
                        onClick={() => handleResolve(t)}
                      >
                        {resolvingId === t.id ? <CircularProgress size={16} /> : 'Resolve'}
                      </Button>
                    </TableCell>
                  </TableRow>
                );
              })}
            </TableBody>
          </Table>
          <TablePagination
            component="div"
            count={total}
            page={page}
            onPageChange={(_, newPage) => setPage(newPage)}
            rowsPerPage={PAGE_SIZE}
            rowsPerPageOptions={[PAGE_SIZE]}
          />
        </TableContainer>
      )}

      <RecordDetailsDialog
        ticket={detailsTicket}
        liveIssueState={detailsTicket ? issueStates[detailsTicket.id] : undefined}
        onClose={() => setDetailsTicket(null)}
      />
    </Box>
  );
};
