import { useCallback, useEffect, useMemo, useState } from "react";
import {
  Alert,
  Box,
  Button,
  Card,
  Chip,
  CircularProgress,
  Grid,
  Stack,
  Table,
  Typography,
  type ColorPaletteProp,
} from "@mui/joy";
import {
  ArrowLeft,
  Layers3,
  PenSquare,
  Plus,
  RefreshCw,
  Trash2,
} from "lucide-react";
import { Navigate, useLocation, useNavigate, useParams } from "react-router";
import type { ProjectDto } from "@sigma/common";
import { apiClient } from "../../lib/api";
import { useAuth } from "../../context/auth-context";
import { formatNumber } from "../../components/dashboard/number-format";

type StatCard = {
  label: string;
  value: string;
  description: string;
  color?: ColorPaletteProp;
};

export function ProjectDetailPage() {
  const navigate = useNavigate();
  const location = useLocation();
  const { projectId } = useParams<{ projectId: string }>();
  const { isAuthenticated, loading: authLoading } = useAuth();

  const [project, setProject] = useState<ProjectDto | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [lastUpdated, setLastUpdated] = useState<Date | null>(null);
  const [deleteError, setDeleteError] = useState<string | null>(null);
  const [deletingFunctionId, setDeletingFunctionId] = useState<string | null>(
    null
  );
  const [projectDeleteError, setProjectDeleteError] = useState<string | null>(
    null
  );
  const [deletingProject, setDeletingProject] = useState(false);

  const fetchProject = useCallback(async () => {
    if (!projectId) {
      setError("Missing project identifier");
      setLoading(false);
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const { data } = await apiClient.get<ProjectDto>(
        `/projects/${projectId}`
      );
      setProject(data);
      setDeleteError(null);
      setProjectDeleteError(null);
      setLastUpdated(new Date());
    } catch (err) {
      setProject(null);
      setError(
        err instanceof Error ? err.message : "Unable to load project details"
      );
    } finally {
      setLoading(false);
    }
  }, [projectId]);

  useEffect(() => {
    if (!isAuthenticated) {
      return;
    }

    fetchProject();
  }, [fetchProject, isAuthenticated]);

  if (!authLoading && !isAuthenticated) {
    return (
      <Navigate
        to="/login"
        replace
        state={{ from: location.pathname ?? "/" }}
      />
    );
  }

  const handleBack = () => {
    if (window.history.length > 2) {
      navigate(-1);
    } else {
      navigate("/");
    }
  };

  const cpuUsagePercent = useMemo(() => {
    if (!project) {
      return 0;
    }

    if (!project.cpuTimeQuotaMsPerMinute) {
      return 0;
    }

    return Math.min(
      100,
      (project.cpuTimeUsedMs / project.cpuTimeQuotaMsPerMinute) * 100
    );
  }, [project]);

  const stats = useMemo<StatCard[]>(() => {
    if (!project) {
      return [];
    }

    const windowStart = new Date(project.cpuTimeWindowStartedAt);

    return [
      {
        label: "Functions",
        value: formatNumber(project.functions.length),
        description: "Deployed handlers in this project",
      },
      {
        label: "Invocations",
        value: formatNumber(project.functionsInvocationCount ?? 0),
        description: "Aggregate executions across all functions",
      },
      {
        label: "Errors",
        value: formatNumber(project.functionsErrorCount ?? 0),
        description: "Functions failed invocations count",
        color: (project.functionsErrorCount ?? 0) > 0 ? "danger" : undefined,
      },
      {
        label: "CPU quota (ms/min)",
        value: formatNumber(project.cpuTimeQuotaMsPerMinute ?? 0),
        description: "Configured execution budget",
      },
      {
        label: "CPU used",
        value: `${formatNumber(project.cpuTimeUsedMs ?? 0)} ms (${cpuUsagePercent.toFixed(1)}%)`,
        description: "Usage during the current window",
      },
      {
        label: "Window started",
        value: windowStart.toLocaleString(),
        description: "Quota refresh timestamp",
      },
    ];
  }, [project, cpuUsagePercent]);

  const sortedFunctions = useMemo(() => {
    if (!project) {
      return [];
    }

    return [...project.functions].sort(
      (a, b) => (b.invocations ?? 0) - (a.invocations ?? 0)
    );
  }, [project]);

  const handleCreateFunction = () => {
    if (!projectId) {
      return;
    }

    navigate(`/projects/${projectId}/functions/new`);
  };

  const handleDeleteProject = useCallback(async () => {
    if (!projectId || !project) {
      return;
    }

    const confirmed =
      typeof window === "undefined"
        ? true
        : window.confirm(
            `Delete project "${project.name}" and all of its functions? This cannot be undone.`
          );

    if (!confirmed) {
      return;
    }

    setDeletingProject(true);
    setProjectDeleteError(null);

    try {
      await apiClient.delete(`/projects/${projectId}`);
      navigate("/", { replace: true });
    } catch (err) {
      const message =
        err instanceof Error ? err.message : "Failed to delete project";
      setProjectDeleteError(message);
    } finally {
      setDeletingProject(false);
    }
  }, [navigate, project, projectId]);

  const handleDeleteFunction = useCallback(
    async (functionId: string, functionName?: string) => {
      if (!projectId) {
        return;
      }

      const targetLabel = functionName ? `"${functionName}"` : "this function";
      const confirmed =
        typeof window === "undefined"
          ? true
          : window.confirm(
              `Delete function ${targetLabel}? This cannot be undone.`
            );

      if (!confirmed) {
        return;
      }

      setDeleteError(null);
      setDeletingFunctionId(functionId);

      try {
        await apiClient.delete(
          `/projects/${projectId}/functions/${functionId}`
        );

        setProject((prev) => {
          if (!prev) {
            return prev;
          }

          const removed = prev.functions.find((f) => f._id === functionId);
          if (!removed) {
            return prev;
          }

          const remainingFunctions = prev.functions.filter(
            (f) => f._id !== functionId
          );

          return {
            ...prev,
            functions: remainingFunctions,
            functionsInvocationCount: Math.max(
              0,
              (prev.functionsInvocationCount ?? 0) - (removed.invocations ?? 0)
            ),
            functionsErrorCount: Math.max(
              0,
              (prev.functionsErrorCount ?? 0) - (removed.errors ?? 0)
            ),
          };
        });
      } catch (err) {
        const message =
          err instanceof Error ? err.message : "Failed to delete function";
        setDeleteError(message);
      } finally {
        setDeletingFunctionId(null);
      }
    },
    [projectId]
  );

  return (
    <Box sx={{ p: 3, display: "flex", flexDirection: "column", gap: 2 }}>
      <Button
        variant="plain"
        color="neutral"
        size="sm"
        startDecorator={<ArrowLeft size={16} />}
        onClick={handleBack}
        sx={{ alignSelf: "flex-start" }}
      >
        Back to projects
      </Button>

      {loading ? (
        <Stack alignItems="center" justifyContent="center" sx={{ py: 6 }}>
          <CircularProgress size="lg" />
          <Typography level="body-sm" textColor="neutral.500" mt={1.5}>
            Loading project insights…
          </Typography>
        </Stack>
      ) : error ? (
        <Card variant="soft" color="danger">
          <Stack direction="row" gap={1.5} alignItems="center">
            <Alert color="danger" variant="plain">
              {error}
            </Alert>
            <Button
              size="sm"
              variant="soft"
              startDecorator={<RefreshCw size={16} />}
              onClick={fetchProject}
            >
              Retry
            </Button>
          </Stack>
        </Card>
      ) : project ? (
        <Stack gap={2}>
          <Stack
            direction={{ xs: "column", md: "row" }}
            justifyContent="space-between"
            alignItems={{ xs: "flex-start", md: "center" }}
            gap={2}
          >
            <Stack gap={1}>
              <Stack direction="row" gap={1} alignItems="center">
                <Typography level="h2" fontWeight={700}>
                  {project.name}
                </Typography>
                <Chip size="sm" variant="soft" color="neutral">
                  {project.slug}
                </Chip>
              </Stack>
              {project.description ? (
                <Typography level="body-sm" textColor="neutral.500">
                  {project.description}
                </Typography>
              ) : null}
            </Stack>
            <Stack direction="row" gap={1} alignItems="center">
              {lastUpdated ? (
                <Typography
                  level="body-xs"
                  textColor="neutral.500"
                  sx={{ whiteSpace: "nowrap" }}
                >
                  Updated {lastUpdated.toLocaleTimeString()}
                </Typography>
              ) : null}
              <Button
                size="sm"
                variant="outlined"
                color="neutral"
                startDecorator={<RefreshCw size={16} />}
                onClick={fetchProject}
                disabled={loading || deletingProject}
              >
                Refresh
              </Button>
              <Button
                size="sm"
                variant="solid"
                color="danger"
                startDecorator={<Trash2 size={16} />}
                onClick={handleDeleteProject}
                loading={deletingProject}
                disabled={deletingProject}
              >
                Delete project
              </Button>
            </Stack>
          </Stack>

          {projectDeleteError ? (
            <Alert color="danger" variant="soft">
              {projectDeleteError}
            </Alert>
          ) : null}

          <Grid container spacing={2} mb={2} sx={{ mt: 1 }}>
            {stats.map((stat) => (
              <Grid key={stat.label} xs={12} sm={6} lg={4}>
                <Card
                  variant="outlined"
                  sx={{ p: 2.25, gap: 0.5 }}
                  color={stat.color}
                >
                  <Typography level="body-xs" textColor="neutral.500">
                    {stat.label}
                  </Typography>
                  <Typography level="title-md" fontWeight={600}>
                    {stat.value}
                  </Typography>
                  <Typography level="body-xs" textColor="neutral.500">
                    {stat.description}
                  </Typography>
                </Card>
              </Grid>
            ))}
          </Grid>

          <Card sx={{ p: 0 }}>
            <Stack
              direction="row"
              alignItems="center"
              justifyContent="space-between"
              sx={{
                px: 2.5,
                py: 1.75,
                borderBottom: "1px solid",
                borderColor: "divider",
              }}
            >
              <Stack direction="row" alignItems="center" gap={1.25}>
                <Layers3 size={18} />
                <Stack gap={0.25}>
                  <Typography level="title-sm" fontWeight={600}>
                    Functions
                  </Typography>
                  <Typography level="body-xs" textColor="neutral.500">
                    Invocation and error metrics per endpoint
                  </Typography>
                </Stack>
              </Stack>
              <Stack direction="row" gap={1} alignItems="center">
                <Chip size="sm" variant="soft">
                  {project.functions.length} total
                </Chip>
                <Button
                  size="sm"
                  startDecorator={<Plus size={16} />}
                  onClick={handleCreateFunction}
                >
                  Create function
                </Button>
              </Stack>
            </Stack>

            {deleteError ? (
              <Alert color="danger" variant="soft" sx={{ mx: 2.5, my: 1.5 }}>
                {deleteError}
              </Alert>
            ) : null}

            {sortedFunctions.length ? (
              <Table
                size="sm"
                stickyHeader
                sx={{
                  "--TableCell-headBackground": "transparent",
                  "--TableCell-paddingX": "20px",
                  "--TableCell-paddingY": "12px",
                }}
              >
                <thead>
                  <tr>
                    <th style={{ width: "16%" }}>Function</th>
                    <th style={{ width: "16%" }}>Methods</th>
                    <th style={{ width: "16%" }}>Invocations</th>
                    <th style={{ width: "16%" }}>Errors</th>
                    <th style={{ width: "16%" }}>Last invocation</th>
                    <th style={{ width: "16%" }}></th>
                  </tr>
                </thead>
                <tbody>
                  {sortedFunctions.map((func) => {
                    const methods: string[] = func.methods?.length
                      ? func.methods
                      : ["ANY"];

                    return (
                      <tr key={func._id}>
                        <td>
                          <Stack gap={0.25}>
                            <Typography level="body-sm" fontWeight={600}>
                              {func.name}
                            </Typography>
                            <Typography level="body-xs" textColor="neutral.500">
                              {func.path}
                            </Typography>
                          </Stack>
                        </td>
                        <td>
                          <Stack direction="row" gap={0.5} flexWrap="wrap">
                            {methods.map((method) => (
                              <Chip key={method} size="sm" variant="outlined">
                                {method}
                              </Chip>
                            ))}
                          </Stack>
                        </td>
                        <td>
                          <Typography level="body-sm" fontWeight={500}>
                            {formatNumber(func.invocations ?? 0)}
                          </Typography>
                        </td>
                        <td>
                          <Typography
                            level="body-sm"
                            fontWeight={500}
                            color={func.errors ? "danger" : undefined}
                          >
                            {formatNumber(func.errors ?? 0)}
                          </Typography>
                        </td>
                        <td>
                          <Typography
                            level="body-xs"
                            textColor={
                              func.lastInvocation ? undefined : "neutral.500"
                            }
                          >
                            {func.lastInvocation?.toLocaleString() ?? "Never"}
                          </Typography>
                        </td>
                        <td>
                          <Stack
                            direction="row"
                            gap={1}
                            justifyContent="flex-end"
                          >
                            <Button
                              size="sm"
                              variant="outlined"
                              startDecorator={<PenSquare size={14} />}
                              onClick={() =>
                                navigate(
                                  `/projects/${projectId}/functions/${func._id}`
                                )
                              }
                            >
                              Edit
                            </Button>
                            <Button
                              size="sm"
                              variant="outlined"
                              color="danger"
                              startDecorator={<Trash2 size={14} />}
                              onClick={() =>
                                handleDeleteFunction(func._id, func.name)
                              }
                              loading={deletingFunctionId === func._id}
                              disabled={deletingFunctionId === func._id}
                            >
                              Delete
                            </Button>
                          </Stack>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </Table>
            ) : (
              <Stack alignItems="center" justifyContent="center" sx={{ py: 5 }}>
                <Typography level="title-sm">No functions deployed</Typography>
                <Typography level="body-sm" textColor="neutral.500">
                  Once you add functions, their metrics will show up here.
                </Typography>
              </Stack>
            )}
          </Card>
        </Stack>
      ) : (
        <Card variant="soft">
          <Typography level="title-sm">
            We couldn’t find that project. Double-check the URL and try again.
          </Typography>
        </Card>
      )}
    </Box>
  );
}
