import { useEffect, useMemo, useState } from "react";
import { useSearchParams } from "react-router-dom";
import { History, ShieldCheck, SlidersHorizontal } from "lucide-react";
import { toast } from "sonner";

import {
  getWorkspaceLogDetail,
  listWorkspaceLogs,
  type WorkspaceLogDetail,
  type WorkspaceLogItem,
} from "../api/logs";
import { fetchWorkspaceMemberships, type WorkspaceMembership } from "../api/workspaces";
import { LogDetailsPanel } from "../components/logs/LogDetailsPanel";
import { LogsFeed } from "../components/logs/LogsFeed";
import { LogsFilterBar, type LogsFilterDraft } from "../components/logs/LogsFilterBar";
import { useWorkspace } from "../context/WorkspaceContext";
import { useTranslation } from "../hooks/useTranslation";
import { readStringParam, updateQueryParams } from "../lib/queryParams";
import { canWorkspace, WORKSPACE_LOGS_VIEW } from "../lib/permissions";

const DEFAULT_FILTERS: LogsFilterDraft = {
  search: "",
  section: "",
  event: "",
  actor: "",
  from: "",
  to: "",
  ordering: "-timestamp",
};

const DEFAULT_QUERY_FILTERS: Record<string, string> = {
  search: DEFAULT_FILTERS.search,
  section: DEFAULT_FILTERS.section,
  event: DEFAULT_FILTERS.event,
  actor: DEFAULT_FILTERS.actor,
  from: DEFAULT_FILTERS.from,
  to: DEFAULT_FILTERS.to,
  ordering: DEFAULT_FILTERS.ordering,
};

const PAGE_SIZE = 20;

export default function Logs() {
  const { t, lang } = useTranslation();
  const { activeWorkspace } = useWorkspace();
  const [searchParams, setSearchParams] = useSearchParams();
  const [memberships, setMemberships] = useState<WorkspaceMembership[]>([]);
  const [logs, setLogs] = useState<WorkspaceLogItem[]>([]);
  const [totalLogs, setTotalLogs] = useState(0);
  const [isLoading, setIsLoading] = useState(false);
  const [isLoadingUsers, setIsLoadingUsers] = useState(false);
  const [isLoadingMore, setIsLoadingMore] = useState(false);
  const [selectedLogId, setSelectedLogId] = useState<number | null>(null);
  const [selectedLog, setSelectedLog] = useState<WorkspaceLogDetail | null>(null);
  const [isLoadingDetail, setIsLoadingDetail] = useState(false);

  const workspaceRole = activeWorkspace?.my_role;
  const canViewLogs = canWorkspace(workspaceRole, WORKSPACE_LOGS_VIEW);
  const isWorkspaceRoleResolved = Boolean(workspaceRole);
  const filters = useMemo<LogsFilterDraft>(
    () => ({
      search: readStringParam(searchParams, "search", DEFAULT_FILTERS.search),
      section: readStringParam(searchParams, "section", DEFAULT_FILTERS.section) as LogsFilterDraft["section"],
      event: readStringParam(searchParams, "event", DEFAULT_FILTERS.event) as LogsFilterDraft["event"],
      actor: readStringParam(searchParams, "actor", DEFAULT_FILTERS.actor),
      from: readStringParam(searchParams, "from", DEFAULT_FILTERS.from),
      to: readStringParam(searchParams, "to", DEFAULT_FILTERS.to),
      ordering: readStringParam(searchParams, "ordering", DEFAULT_FILTERS.ordering) as LogsFilterDraft["ordering"],
    }),
    [searchParams],
  );

  useEffect(() => {
    setLogs([]);
    setTotalLogs(0);
    setSelectedLogId(null);
    setSelectedLog(null);
  }, [activeWorkspace?.id]);

  useEffect(() => {
    if (!activeWorkspace?.id || !isWorkspaceRoleResolved || !canViewLogs) {
      setMemberships([]);
      setIsLoadingUsers(false);
      return;
    }

    const loadUsers = async () => {
      setIsLoadingUsers(true);
      try {
        const response = await fetchWorkspaceMemberships({
          workspace: activeWorkspace.id,
          limit: 200,
          offset: 0,
        });
        setMemberships(response.results || []);
      } catch {
        setMemberships([]);
        toast.error(t.logs?.loadFiltersError || "Failed to load log filters.");
      } finally {
        setIsLoadingUsers(false);
      }
    };

    void loadUsers();
  }, [activeWorkspace?.id, canViewLogs, isWorkspaceRoleResolved, t.logs?.loadFiltersError]);

  useEffect(() => {
    if (!activeWorkspace?.id || !isWorkspaceRoleResolved || !canViewLogs) {
      setLogs([]);
      setTotalLogs(0);
      setIsLoading(false);
      return;
    }

    const loadLogs = async () => {
      setIsLoading(true);
      try {
        const response = await listWorkspaceLogs(
          {
            workspace: activeWorkspace.id,
            search: filters.search || undefined,
            section: filters.section || undefined,
            actor: filters.actor || undefined,
            event: filters.event || undefined,
            from: filters.from || undefined,
            to: filters.to || undefined,
            ordering: filters.ordering,
          },
          { limit: PAGE_SIZE, offset: 0 },
        );
        setLogs(response.results || []);
        setTotalLogs(response.count || 0);
        if (selectedLogId && !(response.results || []).some((item) => item.id === selectedLogId)) {
          setSelectedLogId(null);
          setSelectedLog(null);
        }
      } catch {
        setLogs([]);
        setTotalLogs(0);
        toast.error(t.logs?.loadError || "Failed to load logs.");
      } finally {
        setIsLoading(false);
      }
    };

    void loadLogs();
  }, [
    activeWorkspace?.id,
    canViewLogs,
    filters.actor,
    filters.event,
    filters.from,
    filters.ordering,
    filters.search,
    filters.section,
    filters.to,
    isWorkspaceRoleResolved,
    t.logs?.loadError,
  ]);

  const handleLoadMore = async () => {
    if (!activeWorkspace?.id || isLoadingMore || logs.length >= totalLogs) return;

    setIsLoadingMore(true);
    try {
      const response = await listWorkspaceLogs(
        {
          workspace: activeWorkspace.id,
          search: filters.search || undefined,
          section: filters.section || undefined,
          actor: filters.actor || undefined,
          event: filters.event || undefined,
          from: filters.from || undefined,
          to: filters.to || undefined,
          ordering: filters.ordering,
        },
        { limit: PAGE_SIZE, offset: logs.length },
      );
      setLogs((current) => [...current, ...(response.results || [])]);
      setTotalLogs(response.count || 0);
    } catch {
      toast.error(t.logs?.loadError || "Failed to load logs.");
    } finally {
      setIsLoadingMore(false);
    }
  };

  const handleOpenLog = async (id: number) => {
    setSelectedLogId(id);
    setIsLoadingDetail(true);
    try {
      const detail = await getWorkspaceLogDetail(id);
      setSelectedLog(detail);
    } catch {
      toast.error(t.logs?.loadDetailsError || "Failed to load log details.");
      setSelectedLog(null);
      setSelectedLogId(null);
    } finally {
      setIsLoadingDetail(false);
    }
  };

  const activeFiltersCount = useMemo(
    () => [filters.search, filters.section, filters.event, filters.actor, filters.from, filters.to].filter(Boolean).length,
    [filters.actor, filters.event, filters.from, filters.search, filters.section, filters.to],
  );

  const latestActivityLabel = useMemo(() => {
    if (!logs[0]?.timestamp) return "-";
    return new Intl.DateTimeFormat(lang === "fa" ? "fa-IR-u-ca-persian" : "en-US", {
      year: "numeric",
      month: "short",
      day: "numeric",
      hour: "2-digit",
      minute: "2-digit",
    }).format(new Date(logs[0].timestamp));
  }, [lang, logs]);

  const formatNumber = (value: number) =>
    new Intl.NumberFormat(lang === "fa" ? "fa-IR" : "en-US").format(value);

  if (!activeWorkspace) {
    return (
      <div className="p-6">
        <div className="rounded-3xl border border-slate-200 bg-white p-6 text-slate-600 shadow-sm dark:border-slate-800 dark:bg-slate-900 dark:text-slate-300">
          {t.logs?.selectWorkspace || "Please select a workspace first."}
        </div>
      </div>
    );
  }

  if (!isWorkspaceRoleResolved) {
    return (
      <div className="p-6">
        <div className="rounded-3xl border border-slate-200 bg-white p-6 text-slate-600 shadow-sm dark:border-slate-800 dark:bg-slate-900 dark:text-slate-300">
          {t.loading || "Loading..."}
        </div>
      </div>
    );
  }

  if (!canViewLogs) {
    return (
      <div className="mx-auto max-w-4xl p-4 sm:p-6">
        <div className="rounded-3xl border border-slate-200 bg-white p-8 shadow-sm dark:border-slate-800 dark:bg-slate-900">
          <div className="mb-4 flex h-14 w-14 items-center justify-center rounded-2xl bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300">
            <ShieldCheck className="h-6 w-6" />
          </div>
          <h1 className="text-2xl font-bold text-slate-900 dark:text-white">
            {t.logs?.title || "Activity logs"}
          </h1>
          <p className="mt-2 text-sm text-slate-500 dark:text-slate-400">
            {t.logs?.unauthorized || "Only owners and admins can access workspace activity logs."}
          </p>
        </div>
      </div>
    );
  }

  return (
    <div className="mx-auto max-w-7xl space-y-5 p-4 md:p-6">
      <section className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm dark:border-slate-800 dark:bg-slate-900 sm:p-6">
        <div className="flex flex-col gap-5 lg:flex-row lg:items-start lg:justify-between">
          <div>
            <h1 className="text-2xl font-bold text-slate-900 dark:text-white">
              {t.logs?.title || "Activity logs"}
            </h1>
            <p className="mt-1 text-sm text-slate-500 dark:text-slate-400">
              {t.logs?.description?.(activeWorkspace.name) || `Review what has happened inside ${activeWorkspace.name}.`}
            </p>
          </div>

          <div className="grid gap-3 sm:grid-cols-3">
            <div className="rounded-2xl border border-slate-200 bg-slate-50 p-4 dark:border-slate-800 dark:bg-slate-950">
              <div className="flex items-center justify-between text-slate-500 dark:text-slate-400">
                <span className="text-xs font-semibold uppercase tracking-[0.16em]">
                  {t.logs?.totalLogs || "Total logs"}
                </span>
                <History className="h-4 w-4" />
              </div>
              <p className="mt-3 text-2xl font-bold text-slate-900 dark:text-white">{formatNumber(totalLogs)}</p>
            </div>
            <div className="rounded-2xl border border-slate-200 bg-slate-50 p-4 dark:border-slate-800 dark:bg-slate-950">
              <div className="flex items-center justify-between text-slate-500 dark:text-slate-400">
                <span className="text-xs font-semibold uppercase tracking-[0.16em]">
                  {t.logs?.activeFilters || "Active filters"}
                </span>
                <SlidersHorizontal className="h-4 w-4" />
              </div>
              <p className="mt-3 text-2xl font-bold text-slate-900 dark:text-white">{formatNumber(activeFiltersCount)}</p>
            </div>
            <div className="rounded-2xl border border-slate-200 bg-slate-50 p-4 dark:border-slate-800 dark:bg-slate-950">
              <div className="flex items-center justify-between text-slate-500 dark:text-slate-400">
                <span className="text-xs font-semibold uppercase tracking-[0.16em]">
                  {t.logs?.latestActivity || "Latest activity"}
                </span>
                <ShieldCheck className="h-4 w-4" />
              </div>
              <p className="mt-3 text-sm font-semibold text-slate-900 dark:text-white">{latestActivityLabel}</p>
            </div>
          </div>
        </div>
      </section>

      <LogsFilterBar
        value={filters}
        users={memberships}
        isLoadingUsers={isLoadingUsers}
        canSelectUsers={canViewLogs}
        onApply={(nextFilters) =>
          setSearchParams(
            (current) =>
              updateQueryParams(
                current,
                {
                  search: nextFilters.search,
                  section: nextFilters.section,
                  event: nextFilters.event,
                  actor: nextFilters.actor,
                  from: nextFilters.from,
                  to: nextFilters.to,
                  ordering: nextFilters.ordering,
                },
                DEFAULT_QUERY_FILTERS,
              ),
            { replace: true },
          )
        }
      />

      <LogsFeed
        items={logs}
        total={totalLogs}
        hasMore={logs.length < totalLogs}
        isLoading={isLoading}
        isLoadingMore={isLoadingMore}
        selectedId={selectedLogId}
        onOpen={(id) => void handleOpenLog(id)}
        onLoadMore={() => void handleLoadMore()}
      />

      <LogDetailsPanel
        open={selectedLogId !== null}
        log={selectedLog}
        isLoading={isLoadingDetail}
        onClose={() => {
          setSelectedLogId(null);
          setSelectedLog(null);
        }}
      />
    </div>
  );
}
