import AddIcon from "@mui/icons-material/Add";
import CloseIcon from "@mui/icons-material/Close";
import InventoryIcon from "@mui/icons-material/Inventory";
import ShowChartIcon from "@mui/icons-material/ShowChart";
import SortIcon from "@mui/icons-material/Sort";
import VisibilityIcon from "@mui/icons-material/Visibility";
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
import {
  Alert,
  Box,
  Button,
  Chip,
  CircularProgress,
  Dialog,
  DialogContent,
  DialogTitle,
  FormControl,
  IconButton,
  MenuItem,
  Select,
  Stack,
  Tooltip,
  Typography,
} from "@mui/material";
import { useQueryClient } from "@tanstack/react-query";
import React, { useState, useEffect, useMemo, useCallback, useRef } from "react";
import { Navigate, useNavigate } from "react-router-dom";

import { ArthurLogo } from "./common/ArthurLogo";
import { SearchBar } from "./common/SearchBar";
import { CreateTaskForm } from "./CreateTaskForm";
import { TaskCard } from "./TaskCard";

import { SettingsMenuButton } from "@/components/settings/SettingsMenuButton";
import { useAuth } from "@/contexts/AuthContext";
import { useDemoMode } from "@/contexts/EngineConfigContext";
import { useDebouncedValue } from "@/hooks/useDebouncedValue";
import { useActiveTasksQuery, useArchivedTasksQuery } from "@/hooks/useTasksList";
import { queryKeys } from "@/lib/queryKeys";
import { type InactiveDays, type SortBy, useTaskListStore } from "@/stores/task-list.store";

// Records that a single-task demo tenant has already been auto-navigated into
// their task this browser session. Scoped to sessionStorage so the redirect
// fires once on entry, then leaves the dashboard reachable; a fresh login or new
// tab starts a new session and re-enters.
const DEMO_AUTONAV_SESSION_KEY = "arthur:demo-single-task-autonav";

function hasConsumedDemoAutoNav(): boolean {
  try {
    return typeof window !== "undefined" && window.sessionStorage.getItem(DEMO_AUTONAV_SESSION_KEY) === "1";
  } catch {
    return false;
  }
}

function markDemoAutoNavConsumed(): void {
  try {
    window.sessionStorage.setItem(DEMO_AUTONAV_SESSION_KEY, "1");
  } catch {
    // sessionStorage may be unavailable (private mode, tests). Auto-nav is
    // best-effort, so failing to record it is non-fatal.
  }
}

export const AllTasks: React.FC = () => {
  const navigate = useNavigate();
  const { demoMode } = useDemoMode();
  const { isTenant } = useAuth();
  const queryClient = useQueryClient();
  const [archivedDialogOpen, setArchivedDialogOpen] = useState(false);
  const [showCreateForm, setShowCreateForm] = useState(false);
  const [searchQuery, setSearchQuery] = useState("");
  const debouncedSearchQuery = useDebouncedValue(searchQuery, 300);
  const { hideSystemTasks, sortBy, inactiveDays, setHideSystemTasks, setSortBy, setInactiveDays } = useTaskListStore();

  const { tasks, totalCount, isLoading, isError, isFetchingNextPage, hasNextPage, fetchNextPage } = useActiveTasksQuery({
    search: debouncedSearchQuery,
  });

  const {
    tasks: archivedTasks,
    totalCount: archivedTotalCount,
    isLoading: isLoadingArchived,
    isError: archivedIsError,
    isFetchingNextPage: archivedIsFetchingNextPage,
    hasNextPage: archivedHasNextPage,
    fetchNextPage: archivedFetchNextPage,
  } = useArchivedTasksQuery({ enabled: archivedDialogOpen });

  const sentinelRef = useRef<HTMLDivElement>(null);
  const archivedSentinelRef = useRef<HTMLDivElement>(null);
  const archivedScrollRef = useRef<HTMLDivElement>(null);
  const isSearching = debouncedSearchQuery.trim().length > 0;

  const filteredTasks = useMemo(() => {
    let result = [...tasks];

    if (hideSystemTasks) {
      result = result.filter((t) => !t.is_system_task);
    }

    if (inactiveDays !== "archived" && inactiveDays > 0) {
      const cutoff = Date.now() - inactiveDays * 24 * 60 * 60 * 1000;
      result = result.filter((t) => t.updated_at >= cutoff);
    }

    result.sort((a, b) => {
      const field = sortBy === "updated" ? "updated_at" : "created_at";
      return b[field] - a[field];
    });

    return result;
  }, [tasks, hideSystemTasks, sortBy, inactiveDays]);

  const filteredArchivedTasks = useMemo(() => {
    let result = [...archivedTasks];

    if (hideSystemTasks) {
      result = result.filter((t) => !t.is_system_task);
    }

    result.sort((a, b) => {
      const field = sortBy === "updated" ? "updated_at" : "created_at";
      return b[field] - a[field];
    });

    return result;
  }, [archivedTasks, hideSystemTasks, sortBy]);

  const invalidateTaskQueries = useCallback(() => {
    queryClient.invalidateQueries({ queryKey: queryKeys.tasks.all() });
  }, [queryClient]);

  useEffect(() => {
    const sentinel = sentinelRef.current;
    if (!sentinel) return;

    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting && hasNextPage && !isFetchingNextPage && !isLoading && !isError) {
          fetchNextPage();
        }
      },
      { threshold: 0.1 }
    );

    observer.observe(sentinel);
    return () => observer.disconnect();
  }, [hasNextPage, isFetchingNextPage, isLoading, isError, fetchNextPage]);

  useEffect(() => {
    if (!archivedDialogOpen) return;
    const sentinel = archivedSentinelRef.current;
    const root = archivedScrollRef.current;
    if (!sentinel || !root) return;

    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting && archivedHasNextPage && !archivedIsFetchingNextPage && !isLoadingArchived && !archivedIsError) {
          archivedFetchNextPage();
        }
      },
      { root, threshold: 0.1 }
    );

    observer.observe(sentinel);
    return () => observer.disconnect();
  }, [archivedDialogOpen, archivedHasNextPage, archivedIsFetchingNextPage, isLoadingArchived, archivedIsError, archivedFetchNextPage]);

  const handleTaskCreated = (taskId: string) => {
    invalidateTaskQueries();
    navigate(`/tasks/${taskId}/overview`);
  };

  const filterToolbar = (
    <Stack direction="row" spacing={1.5} alignItems="center">
      <Stack direction="row" spacing={0.5} alignItems="center">
        <SortIcon sx={{ fontSize: 18, color: "text.disabled" }} />
        <FormControl size="small" variant="standard">
          <Select
            value={sortBy}
            onChange={(e) => setSortBy(e.target.value as SortBy)}
            disableUnderline
            sx={{ fontSize: "0.875rem", color: "text.secondary" }}
          >
            <MenuItem value="updated">Recently updated</MenuItem>
            <MenuItem value="created">Recently created</MenuItem>
          </Select>
        </FormControl>

        <FormControl size="small" variant="standard">
          <Select
            value={inactiveDays}
            onChange={(e) => setInactiveDays(e.target.value as InactiveDays)}
            disableUnderline
            sx={{ fontSize: "0.875rem", color: "text.secondary" }}
          >
            <MenuItem value={0}>All time</MenuItem>
            <MenuItem value={7}>Active in last 7 days</MenuItem>
            <MenuItem value={14}>Active in last 14 days</MenuItem>
            <MenuItem value={30}>Active in last 30 days</MenuItem>
          </Select>
        </FormControl>
      </Stack>

      <Tooltip title={hideSystemTasks ? "Show system tasks" : "Hide system tasks"}>
        <Stack
          direction="row"
          spacing={0.5}
          alignItems="center"
          onClick={() => setHideSystemTasks(!hideSystemTasks)}
          sx={{ cursor: "pointer", "&:hover": { opacity: 0.7 } }}
        >
          {hideSystemTasks ? (
            <VisibilityOffIcon sx={{ fontSize: 16, color: "text.disabled" }} />
          ) : (
            <VisibilityIcon sx={{ fontSize: 16, color: "text.disabled" }} />
          )}
          <Typography variant="body2" color="text.secondary">
            {hideSystemTasks ? "System tasks hidden" : "System tasks visible"}
          </Typography>
        </Stack>
      </Tooltip>
    </Stack>
  );

  const hasNoResults = !isLoading && tasks.length === 0;

  // Demo experience: a demo tenant is provisioned with a single task, so on their
  // first arrival this session we skip the dashboard and drop them straight into
  // it. Guard on a settled, unfiltered list (loaded, no error, not searching) with
  // exactly one task. Captured once per mount so the value is stable across the
  // redirect, and recorded in sessionStorage (below) so an explicit "Back to All
  // Tasks" — or any later visit to "/" — shows the dashboard instead of bouncing
  // back in. `replace` keeps "/" out of history.
  const onlyTask = !isLoading && !isError && !isSearching && tasks.length === 1 ? tasks[0] : null;
  const [autoNavConsumed] = useState(hasConsumedDemoAutoNav);
  const shouldAutoEnterTask = demoMode && isTenant && onlyTask !== null && !autoNavConsumed;

  useEffect(() => {
    if (shouldAutoEnterTask) markDemoAutoNavConsumed();
  }, [shouldAutoEnterTask]);

  if (shouldAutoEnterTask && onlyTask) {
    return <Navigate to={`/tasks/${onlyTask.id}/traces`} replace />;
  }

  return (
    <>
      <div className="min-h-screen bg-gray-50 dark:bg-gray-950">
        {/* Header */}
        <header className="bg-white dark:bg-gray-900 shadow">
          <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
            <div className="flex justify-between items-center py-3">
              <div className="flex flex-col items-start">
                <ArthurLogo className="size-6 text-black dark:text-white" />
              </div>
              <Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
                <SettingsMenuButton />
              </Box>
            </div>
          </div>
        </header>

        {/* Main Content */}
        <main className="max-w-7xl mx-auto py-3 sm:px-6 lg:px-8">
          <div className="px-4 py-3 sm:px-0">
            {isLoading ? (
              <Box sx={{ display: "flex", justifyContent: "center", alignItems: "center", height: 256 }}>
                <CircularProgress />
              </Box>
            ) : isError ? (
              <Alert severity="error">Failed to load tasks. Please check your authentication.</Alert>
            ) : hasNoResults && !isSearching ? (
              <Box sx={{ textAlign: "center", py: 6 }}>
                <Typography variant="h6" color="text.secondary">
                  No tasks found
                </Typography>
                <Typography variant="body2" color="text.disabled" sx={{ mb: 4 }}>
                  Get started by creating your first agent task.
                </Typography>
                <CreateTaskForm embedded={true} onTaskCreated={handleTaskCreated} onCancel={() => {}} />
              </Box>
            ) : (
              <>
                {/* Title + CTA */}
                <Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", mb: 2 }}>
                  <Box>
                    <Typography variant="h6">Tasks ({totalCount})</Typography>
                    <Typography variant="body2" sx={{ color: "text.secondary", mt: 0.5 }}>
                      {filteredTasks.length < tasks.length
                        ? `Showing ${filteredTasks.length} of ${tasks.length} loaded`
                        : "Click on any task to open the toolkit"}
                    </Typography>
                  </Box>
                  {!isTenant && (
                    <Button variant="contained" onClick={() => setShowCreateForm(true)} startIcon={<AddIcon />}>
                      Task
                    </Button>
                  )}
                </Box>

                {/* Search */}
                <Box sx={{ mb: 2, maxWidth: 400 }}>
                  <SearchBar value={searchQuery} onChange={setSearchQuery} onClear={() => setSearchQuery("")} placeholder="Search tasks by name..." />
                </Box>

                {/* Filter toolbar */}
                <Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between", mb: 3 }}>
                  {filterToolbar}
                  <Stack direction="row" spacing={1.5} alignItems="center">
                    <Stack direction="row" spacing={0.5} alignItems="center">
                      <ShowChartIcon sx={{ fontSize: 16, color: "text.disabled" }} />
                      <Typography variant="body2" color="text.secondary">
                        Metrics from last 7 days
                      </Typography>
                    </Stack>
                    <Tooltip title="View archived tasks">
                      <IconButton size="small" onClick={() => setArchivedDialogOpen(true)} sx={{ color: "text.disabled" }}>
                        <InventoryIcon sx={{ fontSize: 16 }} />
                      </IconButton>
                    </Tooltip>
                  </Stack>
                </Box>

                {/* Active task grid */}
                {hasNoResults && isSearching ? (
                  <Box sx={{ textAlign: "center", py: 6 }}>
                    <Typography variant="h6" color="text.secondary">
                      No tasks match &quot;{debouncedSearchQuery}&quot;
                    </Typography>
                    <Typography variant="body2" color="text.disabled">
                      Try a different search term.
                    </Typography>
                  </Box>
                ) : filteredTasks.length === 0 ? (
                  <Box sx={{ textAlign: "center", py: 6 }}>
                    <Typography variant="h6" color="text.secondary">
                      {inactiveDays === 0
                        ? "No tasks found"
                        : inactiveDays === "archived"
                          ? "No archived tasks found"
                          : `No tasks active in the last ${inactiveDays} days`}
                    </Typography>
                    {inactiveDays !== 0 && inactiveDays !== "archived" && (
                      <Typography variant="body2" color="text.disabled">
                        Try expanding the time range or selecting &quot;All time&quot;.
                      </Typography>
                    )}
                  </Box>
                ) : (
                  <Box
                    sx={{
                      display: "grid",
                      gap: 2,
                      gridTemplateColumns: { xs: "minmax(0, 1fr)", sm: "repeat(2, minmax(0, 1fr))", lg: "repeat(3, minmax(0, 1fr))" },
                    }}
                  >
                    {filteredTasks.map((task) => (
                      <TaskCard key={task.id} task={task} onArchiveToggle={invalidateTaskQueries} />
                    ))}
                  </Box>
                )}

                {/* Infinite scroll sentinel */}
                <Box ref={sentinelRef} sx={{ height: 1 }} />

                {/* Load-more feedback */}
                {isFetchingNextPage && (
                  <Box sx={{ display: "flex", justifyContent: "center", py: 3 }}>
                    <CircularProgress size={24} />
                  </Box>
                )}
                {!hasNextPage && tasks.length > 0 && (
                  <Box sx={{ textAlign: "center", py: 2 }}>
                    <Typography variant="caption" color="text.disabled">
                      All {totalCount} tasks loaded
                    </Typography>
                  </Box>
                )}
              </>
            )}
          </div>
        </main>

        {/* Archived Tasks Dialog */}
        <Dialog open={archivedDialogOpen} onClose={() => setArchivedDialogOpen(false)} maxWidth="lg" fullWidth>
          <DialogTitle sx={{ pb: 1 }}>
            <Stack direction="row" justifyContent="space-between" alignItems="flex-start">
              <Box>
                <Stack direction="row" spacing={1} alignItems="center">
                  <InventoryIcon sx={{ fontSize: 20, color: "text.secondary" }} />
                  <Typography variant="h6">Archived Tasks</Typography>
                  {!isLoadingArchived && archivedTasks.length > 0 && (
                    <Chip
                      label={
                        filteredArchivedTasks.length === archivedTotalCount
                          ? archivedTotalCount
                          : `${filteredArchivedTasks.length} of ${archivedTotalCount}`
                      }
                      size="small"
                      variant="outlined"
                    />
                  )}
                </Stack>
                <Typography variant="body2" color="text.secondary" sx={{ mt: 0.5 }}>
                  Unarchive a task to restore it to your active list
                </Typography>
              </Box>
              <IconButton onClick={() => setArchivedDialogOpen(false)} size="small" sx={{ mt: -0.5 }}>
                <CloseIcon />
              </IconButton>
            </Stack>
          </DialogTitle>
          <DialogContent dividers ref={archivedScrollRef}>
            {isLoadingArchived ? (
              <Box sx={{ display: "flex", justifyContent: "center", alignItems: "center", height: 200 }}>
                <CircularProgress />
              </Box>
            ) : archivedIsError ? (
              <Alert severity="error">Failed to load archived tasks. Please check your authentication.</Alert>
            ) : filteredArchivedTasks.length === 0 ? (
              <Box sx={{ textAlign: "center", py: 6 }}>
                <InventoryIcon sx={{ fontSize: 40, color: "text.disabled", mb: 1 }} />
                <Typography variant="h6" color="text.secondary">
                  No archived tasks
                </Typography>
                <Typography variant="body2" color="text.disabled">
                  Tasks you archive will appear here. Unarchive any task to restore it.
                </Typography>
              </Box>
            ) : (
              <>
                <Box sx={{ display: "grid", gap: 2, gridTemplateColumns: { xs: "1fr", sm: "repeat(2, 1fr)", lg: "repeat(3, 1fr)" }, pb: 1 }}>
                  {filteredArchivedTasks.map((task) => (
                    <TaskCard key={task.id} task={task} onArchiveToggle={invalidateTaskQueries} />
                  ))}
                </Box>
                <Box ref={archivedSentinelRef} sx={{ height: 1 }} />
                {archivedIsFetchingNextPage && (
                  <Box sx={{ display: "flex", justifyContent: "center", py: 3 }}>
                    <CircularProgress size={24} />
                  </Box>
                )}
                {!archivedHasNextPage && archivedTasks.length > 0 && (
                  <Box sx={{ textAlign: "center", py: 2 }}>
                    <Typography variant="caption" color="text.disabled">
                      All {archivedTotalCount} archived tasks loaded
                    </Typography>
                  </Box>
                )}
              </>
            )}
          </DialogContent>
        </Dialog>

        {/* Create Task Modal */}
        <CreateTaskForm
          open={showCreateForm}
          onTaskCreated={(taskId) => {
            setShowCreateForm(false);
            handleTaskCreated(taskId);
          }}
          onCancel={() => setShowCreateForm(false)}
        />
      </div>
    </>
  );
};
