import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import {
  Box,
  Paper,
  Typography,
  Stack,
  Button,
  IconButton,
  Tooltip,
  FormControl,
  InputLabel,
  Select,
  MenuItem,
  TextField,
  Divider,
  Chip,
  CircularProgress,
  ToggleButtonGroup,
  ToggleButton,
  Alert,
  InputAdornment,
} from "@mui/material";
import {
  ReceiptLong as LogsIcon,
  Refresh as RefreshIcon,
  DeleteOutline as DeleteIcon,
  Save as SaveIcon,
  Visibility as VisibilityIcon,
  VisibilityOff as VisibilityOffIcon,
  History as HistoryIcon,
} from "@mui/icons-material";
import { AgGridReact } from "ag-grid-react";
import { ModuleRegistry, AllCommunityModule, themeQuartz } from "ag-grid-community";
import Prism from "prismjs";
import "prismjs/components/prism-bash";
import "prismjs/themes/prism-okaidia.css";
import Editor from "react-simple-code-editor";

ModuleRegistry.registerModules([AllCommunityModule]);

const AURORA_SHELL = {
  background:
    "radial-gradient(120% 80% at 0% 0%, rgba(77, 172, 255, 0.22) 0%, rgba(4, 7, 17, 0.0) 60%)," +
    "radial-gradient(100% 80% at 100% 0%, rgba(214, 130, 255, 0.25) 0%, rgba(6, 9, 20, 0.0) 62%)," +
    "linear-gradient(135deg, rgba(3,6,15,1) 0%, rgba(8,12,25,0.97) 50%, rgba(13,7,20,0.95) 100%)",
  panel:
    "linear-gradient(135deg, rgba(10, 16, 31, 0.98) 0%, rgba(6, 10, 24, 0.95) 60%, rgba(15, 6, 26, 0.97) 100%)",
  border: "rgba(148, 163, 184, 0.28)",
  text: "#e2e8f0",
  muted: "#94a3b8",
  accent: "#7db7ff",
};

const gradientButtonSx = {
  textTransform: "none",
  fontWeight: 600,
  color: "#041125",
  borderRadius: 999,
  backgroundImage: "linear-gradient(135deg, #7dd3fc 0%, #c084fc 100%)",
  boxShadow: "0 10px 25px rgba(124, 58, 237, 0.4)",
  "&:hover": {
    backgroundImage: "linear-gradient(135deg, #8be9ff 0%, #d5a8ff 100%)",
    boxShadow: "0 14px 32px rgba(124, 58, 237, 0.45)",
  },
};

const quartzTheme = themeQuartz.withParams({
  accentColor: "#7db7ff",
  backgroundColor: "#05070f",
  foregroundColor: "#f8fafc",
  headerBackgroundColor: "#0b1527",
  browserColorScheme: "dark",
  fontFamily: { googleFont: "IBM Plex Sans" },
  headerFontSize: 14,
  borderColor: "rgba(148,163,184,0.28)",
});
const quartzThemeClass = quartzTheme.themeName || "ag-theme-quartz";
const gridFontFamily = '"IBM Plex Sans", "Helvetica Neue", Arial, sans-serif';
const gridThemeStyle = {
  width: "100%",
  height: "100%",
  "--ag-foreground-color": "#f1f5f9",
  "--ag-background-color": "#050b16",
  "--ag-header-background-color": "#0f1a2e",
  "--ag-odd-row-background-color": "rgba(255,255,255,0.02)",
  "--ag-row-hover-color": "rgba(109, 196, 255, 0.12)",
  "--ag-border-color": "rgba(148,163,184,0.28)",
  "--ag-font-family": gridFontFamily,
};

function formatBytes(bytes) {
  if (!Number.isFinite(bytes) || bytes <= 0) return "0 B";
  const units = ["B", "KB", "MB", "GB", "TB", "PB"];
  const idx = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
  const value = bytes / Math.pow(1024, idx);
  return `${value.toFixed(value >= 10 || idx === 0 ? 0 : 1)} ${units[idx]}`;
}

function formatTimestamp(ts) {
  if (!ts) return "n/a";
  try {
    const d = new Date(ts);
    if (!Number.isNaN(d.getTime())) {
      return d.toLocaleString();
    }
  } catch {
    /* noop */
  }
  return ts;
}

export default function LogManagement({ isAdmin = false }) {
  const [logs, setLogs] = useState([]);
  const [defaultRetention, setDefaultRetention] = useState(30);
  const [selectedDomain, setSelectedDomain] = useState(null);
  const [selectedFile, setSelectedFile] = useState(null);
  const [retentionDraft, setRetentionDraft] = useState("");
  const [listLoading, setListLoading] = useState(false);
  const [entryLoading, setEntryLoading] = useState(false);
  const [entries, setEntries] = useState([]);
  const [entriesMeta, setEntriesMeta] = useState(null);
  const [gridMode, setGridMode] = useState("structured");
  const [error, setError] = useState(null);
  const [actionMessage, setActionMessage] = useState(null);
  const [quickFilter, setQuickFilter] = useState("");
  const gridRef = useRef(null);

  const logMap = useMemo(() => {
    const map = new Map();
    logs.forEach((log) => map.set(log.file, log));
    return map;
  }, [logs]);

  const rawContent = useMemo(() => entries.map((entry) => entry.raw || "").join("\n"), [entries]);

  const columnDefs = useMemo(
    () => [
      { headerName: "Timestamp", field: "timestamp", minWidth: 200 },
      { headerName: "Level", field: "level", width: 110, valueFormatter: (p) => (p.value || "").toUpperCase() },
      { headerName: "Scope", field: "scope", minWidth: 120 },
      { headerName: "Service", field: "service", minWidth: 160 },
      { headerName: "Message", field: "message", flex: 1, minWidth: 300 },
    ],
    []
  );

  const defaultColDef = useMemo(
    () => ({
      sortable: true,
      filter: true,
      resizable: true,
      wrapText: false,
      cellStyle: { fontFamily: gridFontFamily, fontSize: "0.9rem", color: "#e2e8f0" },
    }),
    []
  );

  const applyQuickFilter = useCallback(
    (value) => {
      setQuickFilter(value);
      const api = gridRef.current?.api;
      if (api) api.setGridOption("quickFilterText", value);
    },
    [setQuickFilter]
  );

  const fetchLogs = useCallback(async () => {
    if (!isAdmin) return;
    setListLoading(true);
    setError(null);
    setActionMessage(null);
    try {
      const resp = await fetch("/api/server/logs", { credentials: "include" });
      if (!resp.ok) throw new Error(`Failed to load logs (HTTP ${resp.status})`);
      const data = await resp.json();
      setLogs(Array.isArray(data?.logs) ? data.logs : []);
      setDefaultRetention(Number.isFinite(data?.default_retention_days) ? data.default_retention_days : 30);
      if (Array.isArray(data?.retention_deleted) && data.retention_deleted.length > 0) {
        setActionMessage(`Removed ${data.retention_deleted.length} expired log files automatically.`);
      }
    } catch (err) {
      setError(String(err));
    } finally {
      setListLoading(false);
    }
  }, [isAdmin]);

  const fetchEntries = useCallback(
    async (file) => {
      if (!file) return;
      setEntryLoading(true);
      setError(null);
      try {
        const resp = await fetch(`/api/server/logs/${encodeURIComponent(file)}/entries?limit=1000`, {
          credentials: "include",
        });
        if (!resp.ok) throw new Error(`Failed to load log entries (HTTP ${resp.status})`);
        const data = await resp.json();
        setEntries(Array.isArray(data?.entries) ? data.entries : []);
        setEntriesMeta(data);
        applyQuickFilter("");
      } catch (err) {
        setEntries([]);
        setEntriesMeta(null);
        setError(String(err));
      } finally {
        setEntryLoading(false);
      }
    },
    [applyQuickFilter]
  );

  useEffect(() => {
    if (isAdmin) fetchLogs();
  }, [fetchLogs, isAdmin]);

  useEffect(() => {
    if (!logs.length) {
      setSelectedDomain(null);
      return;
    }
    setSelectedDomain((prev) => (prev && logMap.has(prev) ? prev : logs[0].file));
  }, [logs, logMap]);

  useEffect(() => {
    if (!selectedDomain) {
      setSelectedFile(null);
      return;
    }
    const domain = logMap.get(selectedDomain);
    if (!domain) return;
    const firstVersion = domain.versions?.[0]?.file || domain.file;
    setSelectedFile((prev) => {
      if (domain.versions?.some((v) => v.file === prev)) return prev;
      return firstVersion;
    });
    setRetentionDraft(String(domain.retention_days ?? defaultRetention));
  }, [defaultRetention, logMap, selectedDomain]);

  useEffect(() => {
    if (selectedFile) fetchEntries(selectedFile);
  }, [fetchEntries, selectedFile]);

  const selectedDomainData = selectedDomain ? logMap.get(selectedDomain) : null;

  const handleRetentionSave = useCallback(async () => {
    if (!selectedDomainData) return;
    const trimmed = String(retentionDraft || "").trim();
    const payloadValue = trimmed ? parseInt(trimmed, 10) : null;
    setActionMessage(null);
    setError(null);
    try {
      const resp = await fetch("/api/server/logs/retention", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        credentials: "include",
        body: JSON.stringify({
          retention: {
            [selectedDomainData.file]: Number.isFinite(payloadValue) ? payloadValue : null,
          },
        }),
      });
      if (!resp.ok) throw new Error(`Failed to update retention (HTTP ${resp.status})`);
      const data = await resp.json();
      setLogs(Array.isArray(data?.logs) ? data.logs : logs);
      if (Array.isArray(data?.retention_deleted) && data.retention_deleted.length > 0) {
        setActionMessage(`Retention applied. Removed ${data.retention_deleted.length} expired files.`);
      } else {
        setActionMessage("Retention policy saved.");
      }
    } catch (err) {
      setError(String(err));
    }
  }, [logs, retentionDraft, selectedDomainData]);

  const handleDelete = useCallback(
    async (scope) => {
      if (!selectedFile) return;
      const confirmMessage =
        scope === "family"
          ? "Delete this log domain and all rotated files?"
          : "Delete the currently selected log file?";
      if (!window.confirm(confirmMessage)) return;
      setActionMessage(null);
      setError(null);
      try {
        const target = scope === "family" ? selectedDomainData?.file || selectedFile : selectedFile;
        const resp = await fetch(`/api/server/logs/${encodeURIComponent(target)}?scope=${scope}`, {
          method: "DELETE",
          credentials: "include",
        });
        if (!resp.ok) throw new Error(`Failed to delete log (HTTP ${resp.status})`);
        const data = await resp.json();
        setLogs(Array.isArray(data?.logs) ? data.logs : logs);
        setEntries([]);
        setEntriesMeta(null);
        setActionMessage("Log files deleted.");
      } catch (err) {
        setError(String(err));
      }
    },
    [logs, selectedDomainData, selectedFile]
  );

  const disableRetentionSave =
    !selectedDomainData ||
    (String(selectedDomainData.retention_days ?? defaultRetention) === retentionDraft.trim() &&
      retentionDraft.trim() !== "");

  if (!isAdmin) {
    return (
      <Paper sx={{ m: 3, p: 4, bgcolor: AURORA_SHELL.panel }}>
        <Typography color="error">Administrator permissions are required to view log management.</Typography>
      </Paper>
    );
  }

  return (
    <Paper
      elevation={3}
      sx={{
        m: 0,
        p: 0,
        minHeight: "100%",
        backgroundImage: AURORA_SHELL.background,
        borderRadius: 0,
        display: "flex",
        flexDirection: "column",
      }}
    >
      <Box sx={{ p: 3, borderBottom: `1px solid ${AURORA_SHELL.border}` }}>
        <Stack direction="row" spacing={2} alignItems="center">
          <Box
            sx={{
              width: 40,
              height: 40,
              borderRadius: "12px",
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              bgcolor: "rgba(125,183,255,0.15)",
              color: AURORA_SHELL.accent,
            }}
          >
            <LogsIcon fontSize="small" />
          </Box>
          <Box>
            <Typography variant="h5" sx={{ color: AURORA_SHELL.text, fontWeight: 600 }}>
              Log Management
            </Typography>
            <Typography sx={{ color: AURORA_SHELL.muted }}>
              Analyze engine logs and adjust log retention periods for different engine services.
            </Typography>
          </Box>
          <Box sx={{ flexGrow: 1 }} />
          <Stack direction="row" spacing={1}>
            <Button
              variant="contained"
              startIcon={<RefreshIcon />}
              onClick={() => {
                fetchLogs();
                if (selectedFile) fetchEntries(selectedFile);
              }}
              sx={gradientButtonSx}
            >
              Refresh
            </Button>
          </Stack>
        </Stack>
      </Box>

      {error && (
        <Box sx={{ px: 3, pt: 2 }}>
          <Alert severity="error">{error}</Alert>
        </Box>
      )}
      {actionMessage && (
        <Box sx={{ px: 3, pt: 2 }}>
          <Alert severity="success">{actionMessage}</Alert>
        </Box>
      )}

      <Box sx={{ display: "flex", flexGrow: 1, minHeight: 0 }}>
        <Box
          sx={{
            width: 360,
            p: 3,
            borderRight: `1px solid ${AURORA_SHELL.border}`,
            bgcolor: "rgba(3,7,18,0.7)",
            display: "flex",
            flexDirection: "column",
            gap: 2,
          }}
        >
          <FormControl fullWidth variant="outlined" size="small">
            <InputLabel id="log-select-label">Log Domain</InputLabel>
            <Select
              labelId="log-select-label"
              label="Log Domain"
              value={selectedDomain || ""}
              onChange={(e) => setSelectedDomain(e.target.value)}
            >
              {logs.map((log) => (
                <MenuItem key={log.file} value={log.file}>
                  <Stack direction="row" spacing={1} alignItems="center" sx={{ width: "100%" }}>
                    <Typography sx={{ flexGrow: 1 }}>{log.display_name || log.file}</Typography>
                    <Chip
                      label={formatBytes(log.size_bytes || 0)}
                      size="small"
                      sx={{ bgcolor: "rgba(125,183,255,0.15)", color: AURORA_SHELL.text }}
                    />
                  </Stack>
                </MenuItem>
              ))}
            </Select>
          </FormControl>

          {selectedDomainData && (
            <>
              <FormControl fullWidth size="small">
                <InputLabel id="version-select-label">Log File</InputLabel>
                <Select
                  labelId="version-select-label"
                  label="Log File"
                  value={selectedFile || ""}
                  onChange={(e) => setSelectedFile(e.target.value)}
                >
                  {(selectedDomainData.versions || [{ file: selectedDomainData.file, label: "Active" }]).map(
                    (ver) => (
                      <MenuItem key={ver.file} value={ver.file}>
                        {ver.label}{" "}
                        <Typography component="span" sx={{ ml: 1, color: AURORA_SHELL.muted, fontSize: "0.8rem" }}>
                          {formatTimestamp(ver.modified)} · {formatBytes(ver.size_bytes || 0)}
                        </Typography>
                      </MenuItem>
                    )
                  )}
                </Select>
              </FormControl>

              <Box
                sx={{
                  bgcolor: "rgba(255,255,255,0.03)",
                  borderRadius: 2,
                  border: `1px solid ${AURORA_SHELL.border}`,
                  p: 2,
                }}
              >
                <Typography sx={{ color: AURORA_SHELL.muted, fontSize: "0.85rem", mb: 1 }}>Overview</Typography>
                <Stack spacing={1}>
                  <Stack direction="row" justifyContent="space-between">
                    <Typography sx={{ color: AURORA_SHELL.muted }}>Size</Typography>
                    <Typography sx={{ color: AURORA_SHELL.text, fontWeight: 600 }}>
                      {formatBytes(selectedDomainData.size_bytes || 0)}
                    </Typography>
                  </Stack>
                  <Stack direction="row" justifyContent="space-between">
                    <Typography sx={{ color: AURORA_SHELL.muted }}>Last Updated</Typography>
                    <Typography sx={{ color: AURORA_SHELL.text }}>{formatTimestamp(selectedDomainData.modified)}</Typography>
                  </Stack>
                  <Stack direction="row" justifyContent="space-between">
                    <Typography sx={{ color: AURORA_SHELL.muted }}>Rotations</Typography>
                    <Typography sx={{ color: AURORA_SHELL.text }}>{selectedDomainData.rotation_count || 0}</Typography>
                  </Stack>
                  <Stack direction="row" justifyContent="space-between">
                    <Typography sx={{ color: AURORA_SHELL.muted }}>Retention</Typography>
                    <Typography sx={{ color: AURORA_SHELL.text }}>
                      {(selectedDomainData.retention_days ?? defaultRetention) || defaultRetention} days
                    </Typography>
                  </Stack>
                </Stack>
              </Box>

              <Divider light sx={{ borderColor: AURORA_SHELL.border }} />

              <Stack spacing={1}>
                <Typography sx={{ color: AURORA_SHELL.muted, fontSize: "0.85rem" }}>Retention Policy</Typography>
                <TextField
                  label="Retention Days"
                  size="small"
                  value={retentionDraft}
                  onChange={(e) => setRetentionDraft(e.target.value)}
                  helperText={`Leave blank to inherit default (${defaultRetention} days).`}
                  InputProps={{ inputProps: { min: 0 } }}
                />
                <Button
                  variant="contained"
                  startIcon={<SaveIcon />}
                  onClick={handleRetentionSave}
                  disabled={!selectedDomainData || disableRetentionSave}
                  sx={{
                    ...gradientButtonSx,
                    opacity: !selectedDomainData || disableRetentionSave ? 0.5 : 1,
                  }}
                >
                  Save Retention
                </Button>
              </Stack>

              <Divider light sx={{ borderColor: AURORA_SHELL.border }} />

              <Stack direction="row" spacing={1}>
                <Button
                  variant="outlined"
                  startIcon={<DeleteIcon />}
                  onClick={() => handleDelete("file")}
                  sx={{
                    color: "#f97316",
                    borderColor: "rgba(249,115,22,0.6)",
                    textTransform: "none",
                    fontWeight: 600,
                  }}
                >
                  Delete File
                </Button>
                <Button
                  variant="outlined"
                  startIcon={<HistoryIcon />}
                  onClick={() => handleDelete("family")}
                  sx={{
                    color: "#f43f5e",
                    borderColor: "rgba(244,63,94,0.6)",
                    textTransform: "none",
                    fontWeight: 600,
                  }}
                >
                  Purge Domain
                </Button>
              </Stack>
            </>
          )}

          {listLoading && (
            <Stack alignItems="center" justifyContent="center" sx={{ flexGrow: 1 }}>
              <CircularProgress size={32} />
            </Stack>
          )}
        </Box>

        <Box sx={{ flexGrow: 1, display: "flex", flexDirection: "column", minWidth: 0, p: 3, gap: 2 }}>
          <Stack direction={{ xs: "column", md: "row" }} spacing={2} alignItems="center">
            <ToggleButtonGroup
              exclusive
              size="small"
              value={gridMode}
              onChange={(_, val) => val && setGridMode(val)}
              sx={{
                backgroundColor: "rgba(0,0,0,0.25)",
                borderRadius: 999,
                p: 0.2,
              }}
            >
              <ToggleButton value="structured" sx={{ color: AURORA_SHELL.text, textTransform: "none" }}>
                <VisibilityIcon fontSize="small" sx={{ mr: 1 }} /> Structured
              </ToggleButton>
              <ToggleButton value="raw" sx={{ color: AURORA_SHELL.text, textTransform: "none" }}>
                <VisibilityOffIcon fontSize="small" sx={{ mr: 1 }} /> Raw
              </ToggleButton>
            </ToggleButtonGroup>
            <TextField
              placeholder="Quick filter"
              size="small"
              value={quickFilter}
              onChange={(e) => applyQuickFilter(e.target.value)}
              sx={{
                minWidth: 220,
                flexGrow: 1,
                "& .MuiOutlinedInput-root": {
                  bgcolor: "rgba(255,255,255,0.05)",
                  borderRadius: 999,
                  color: AURORA_SHELL.text,
                },
                "& .MuiInputBase-input": {
                  color: AURORA_SHELL.text,
                },
              }}
              InputProps={{
                startAdornment: (
                  <InputAdornment position="start">
                    <LogsIcon fontSize="small" sx={{ color: AURORA_SHELL.muted }} />
                  </InputAdornment>
                ),
              }}
            />
            <Tooltip title="Reload entries">
              <span>
                <IconButton
                  onClick={() => selectedFile && fetchEntries(selectedFile)}
                  disabled={!selectedFile || entryLoading}
                  sx={{ color: AURORA_SHELL.accent }}
                >
                  <RefreshIcon />
                </IconButton>
              </span>
            </Tooltip>
          </Stack>

          {gridMode === "structured" ? (
            <Box
              sx={{
                flexGrow: 1,
                minHeight: 0,
                borderRadius: 2,
                border: `1px solid ${AURORA_SHELL.border}`,
                bgcolor: "rgba(5,7,15,0.85)",
                overflow: "hidden",
              }}
            >
              {entryLoading ? (
                <Stack alignItems="center" justifyContent="center" sx={{ height: "100%" }}>
                  <CircularProgress />
                </Stack>
              ) : (
                <div className={quartzThemeClass} style={gridThemeStyle}>
                  <AgGridReact
                    ref={gridRef}
                    rowData={entries}
                    columnDefs={columnDefs}
                    defaultColDef={defaultColDef}
                    rowHeight={42}
                    animateRows
                    pagination
                    paginationPageSize={50}
                    suppressCellFocus
                    overlayNoRowsTemplate="<span style='color:#94a3b8'>No log entries to display.</span>"
                  />
                </div>
              )}
            </Box>
          ) : (
            <Box
              sx={{
                flexGrow: 1,
                borderRadius: 2,
                border: `1px solid ${AURORA_SHELL.border}`,
                bgcolor: "#050d1f",
                overflow: "hidden",
                display: "flex",
                flexDirection: "column",
              }}
            >
              {entryLoading ? (
                <Stack alignItems="center" justifyContent="center" sx={{ height: "100%" }}>
                  <CircularProgress />
                </Stack>
              ) : (
                <Box sx={{ height: "100%", overflow: "auto" }}>
                  <Editor
                    value={rawContent}
                    onValueChange={() => {}}
                    highlight={(code) => Prism.highlight(code, Prism.languages.bash, "bash")}
                    padding={16}
                    textareaId="raw-log-viewer"
                    textareaProps={{ readOnly: true }}
                    style={{
                      fontFamily:
                        '"IBM Plex Mono", "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace',
                      fontSize: 13,
                      minHeight: "100%",
                      height: "100%",
                      color: "#e2e8f0",
                      background: "transparent",
                      overflow: "auto",
                    }}
                    readOnly
                  />
                </Box>
              )}
            </Box>
          )}

          {entriesMeta && (
            <Typography sx={{ fontSize: "0.85rem", color: AURORA_SHELL.muted }}>
              Showing {entriesMeta.returned_lines} of {entriesMeta.total_lines} lines from {entriesMeta.file}
              {entriesMeta.truncated ? " (truncated to the most recent lines)" : ""}.
            </Typography>
          )}
        </Box>
      </Box>
    </Paper>
  );
}
