import { useEffect, useState } from "react";
import { isAxiosError } from "axios";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@edr/ui-common";

import { api } from "@/auth/http";

interface LocaleText {
  en?: string;
  am?: string;
}

interface PermissionRecord {
  id: string;
  key: string;
  name?: LocaleText;
  applicationId?: string | null;
}

interface ApplicationRecord {
  id: string;
  key: string;
  name?: LocaleText;
}

interface ListResponse<T> {
  count?: number;
  items?: T[];
  data?: T[];
}

const PAGE_SIZE = 2000;
const ALL_APPLICATIONS_VALUE = "all";
const SYSTEM_APPLICATION_VALUE = "system";

const getLocaleLabel = (value?: LocaleText | null, fallback = "Unnamed") =>
  value?.en ?? value?.am ?? fallback;

const getItems = <T,>(payload: ListResponse<T> | T[] | undefined | null) => {
  if (!payload) {
    return [] as T[];
  }

  if (Array.isArray(payload)) {
    return payload;
  }

  return payload.items ?? payload.data ?? [];
};

const sortPermissions = (items: PermissionRecord[]) =>
  [...items].sort((left, right) =>
    getLocaleLabel(left.name, left.key).localeCompare(
      getLocaleLabel(right.name, right.key),
    ),
  );

const PermissionsPage = () => {
  const [permissions, setPermissions] = useState<PermissionRecord[]>([]);
  const [applications, setApplications] = useState<ApplicationRecord[]>([]);
  const [selectedApplication, setSelectedApplication] = useState(ALL_APPLICATIONS_VALUE);
  const [count, setCount] = useState(0);
  const [loading, setLoading] = useState(true);
  const [loadingMore, setLoadingMore] = useState(false);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);

  useEffect(() => {
    let isMounted = true;

    const loadPageData = async () => {
      setLoading(true);
      setErrorMessage(null);

      try {
        const [permissionsResponse, applicationsResponse] = await Promise.all([
          api.get<ListResponse<PermissionRecord>>("/permissions", {
            params: {
              skip: 0,
              take: PAGE_SIZE,
            },
          }),
          api.get<ListResponse<ApplicationRecord>>("/applications"),
        ]);

        if (!isMounted) {
          return;
        }

        const items = sortPermissions(getItems(permissionsResponse.data));
        const applicationItems = [...getItems(applicationsResponse.data)].sort((left, right) =>
          getLocaleLabel(left.name, left.key).localeCompare(
            getLocaleLabel(right.name, right.key),
          ),
        );

        setPermissions(items);
        setApplications(applicationItems);
        setCount(permissionsResponse.data.count ?? items.length);
      } catch (error) {
        if (!isMounted) {
          return;
        }

        setErrorMessage(
          isAxiosError(error)
            ? error.response?.data?.message ?? "Unable to load permissions."
            : "Unable to load permissions.",
        );
      } finally {
        if (isMounted) {
          setLoading(false);
        }
      }
    };

    void loadPageData();

    return () => {
      isMounted = false;
    };
  }, []);

  const hasMore = count > permissions.length;
  const filteredPermissions = permissions.filter((permission) => {
    if (selectedApplication === ALL_APPLICATIONS_VALUE) {
      return true;
    }

    if (selectedApplication === SYSTEM_APPLICATION_VALUE) {
      return !permission.applicationId;
    }

    return permission.applicationId === selectedApplication;
  });

  const handleLoadMore = async () => {
    setLoadingMore(true);
    setErrorMessage(null);

    try {
      const response = await api.get<ListResponse<PermissionRecord>>("/permissions", {
        params: {
          skip: permissions.length,
          take: PAGE_SIZE,
        },
      });

      const nextItems = sortPermissions(getItems(response.data));

      setPermissions((current) => [...current, ...nextItems]);
      setCount(response.data.count ?? permissions.length + nextItems.length);
    } catch (error) {
      setErrorMessage(
        isAxiosError(error)
          ? error.response?.data?.message ?? "Unable to load more permissions."
          : "Unable to load more permissions.",
      );
    } finally {
      setLoadingMore(false);
    }
  };

  return (
    <section className="p-6">
      <div className="space-y-6 rounded-2xl border border-border bg-card p-8 shadow-sm">
        <div className="space-y-3">
          <p className="text-sm font-medium uppercase tracking-[0.2em] text-muted-foreground">
            User Management
          </p>
          <div className="flex items-start justify-between gap-4">
            <div>
              <h1 className="text-3xl font-semibold text-foreground">Permissions</h1>
              <p className="mt-3 max-w-2xl text-sm text-muted-foreground">
                Browse the full IAM permission catalog for the freight backoffice environment.
              </p>
            </div>
            <div className="rounded-full border border-border bg-muted px-3 py-1 text-sm font-medium text-muted-foreground">
              {filteredPermissions.length} permissions
            </div>
          </div>
        </div>

        <div className="grid gap-3 rounded-2xl border border-border bg-background/60 p-4 md:grid-cols-[minmax(0,260px)_1fr] md:items-end">
          <div className="space-y-2">
            <p className="text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
              Application
            </p>
            <Select value={selectedApplication} onValueChange={setSelectedApplication}>
              <SelectTrigger className="w-full rounded-xl bg-background">
                <SelectValue placeholder="Select application" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value={ALL_APPLICATIONS_VALUE}>All applications</SelectItem>
                <SelectItem value={SYSTEM_APPLICATION_VALUE}>System permissions</SelectItem>
                {applications.map((application) => (
                  <SelectItem key={application.id} value={application.id}>
                    {getLocaleLabel(application.name, application.key)}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <p className="text-sm text-muted-foreground">
            Filter the IAM permission catalog by application, or view the shared system permissions that do not belong to any application.
          </p>
        </div>

        {loading ? (
          <div className="rounded-2xl border border-dashed border-border bg-muted px-4 py-8 text-center text-sm text-muted-foreground">
            Loading permissions...
          </div>
        ) : errorMessage ? (
          <div className="rounded-2xl border border-red-200 bg-red-50 px-4 py-8 text-center text-sm text-red-700 dark:border-red-950 dark:bg-red-950/30 dark:text-red-300">
            {errorMessage}
          </div>
        ) : filteredPermissions.length ? (
          <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
            {filteredPermissions.map((permission) => (
              <article
                key={permission.id}
                className="rounded-2xl border border-border/70 bg-background/80 p-4 shadow-sm transition hover:border-border hover:bg-accent/20"
              >
                <div className="min-w-0 space-y-1">
                  <p className="truncate text-sm font-semibold leading-5 text-foreground">
                    {getLocaleLabel(permission.name, permission.key)}
                  </p>
                  <p className="truncate font-mono text-xs text-muted-foreground/90">
                    {permission.key}
                  </p>
                </div>
              </article>
            ))}
          </div>
        ) : (
          <div className="rounded-2xl border border-dashed border-border bg-muted px-4 py-8 text-center text-sm text-muted-foreground">
            No permissions match the selected application.
          </div>
        )}

        {hasMore ? (
          <div className="flex items-center justify-between gap-4 rounded-2xl border border-border bg-background px-4 py-3">
            <p className="text-sm text-muted-foreground">
              Showing {permissions.length} of {count} permissions.
            </p>
            <button
              type="button"
              onClick={() => void handleLoadMore()}
              disabled={loadingMore}
              className="inline-flex items-center justify-center rounded-xl bg-emerald-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-emerald-700 disabled:cursor-not-allowed disabled:opacity-60"
            >
              {loadingMore ? "Loading..." : "Load more"}
            </button>
          </div>
        ) : null}
      </div>
    </section>
  );
};

export default PermissionsPage;
