"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { rolePermissionsQueryKey } from "@/hooks/use-dashboard-access";

// --------------------------------------
// TYPES
// --------------------------------------

type Role = {
  id: string;
  code: string;
  name: string;
  description?: string | null;
};

type Permission = {
  id: string;
  key: string;
  name: string;
  module: string;
  description?: string | null;
};

type RolePermissionResponse = {
  role: {
    id: string;
    code: string;
    name: string;
  };
  permissions: string[];
};

const API_URL = process.env.NEXT_PUBLIC_API_URL?.replace(/\/+$/, "");

// --------------------------------------
// MAIN COMPONENT
// --------------------------------------

export default function RolePermissionsPage() {
  const queryClient = useQueryClient();
  const [roles, setRoles] = useState<Role[]>([]);
  const [permissions, setPermissions] = useState<Permission[]>([]);
  const [selectedRole, setSelectedRole] = useState("ADMIN");

  const [selectedPermissions, setSelectedPermissions] = useState<string[]>([]);
  const [originalPermissions, setOriginalPermissions] = useState<string[]>([]);

  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState("");
  const [success, setSuccess] = useState("");

  const isSuperAdmin = selectedRole === "SUPER_ADMIN";

  // --------------------------------------
  // API REQUEST
  // --------------------------------------

  const apiRequest = useCallback(
    async (endpoint: string, options: RequestInit = {}) => {
      if (!API_URL) {
        throw new Error("NEXT_PUBLIC_API_URL is not configured.");
      }

      const response = await fetch(`${API_URL}/api/v1${endpoint}`, {
        ...options,
        credentials: "include",
        headers: {
          "Content-Type": "application/json",
          ...options.headers,
        },
      });

      const data = await response.json().catch(() => null);

      if (!response.ok) {
        const message =
          typeof data?.message === "string"
            ? data.message
            : Array.isArray(data?.message)
              ? data.message.join(", ")
              : `Request failed (${response.status})`;

        throw new Error(message);
      }

      return data;
    },
    [],
  );

  // --------------------------------------
  // LOAD ROLES AND PERMISSIONS
  // --------------------------------------

  useEffect(() => {
    let cancelled = false;

    async function loadInitialData() {
      try {
        setLoading(true);
        setError("");

        const [rolesData, permissionsData] = await Promise.all([
          apiRequest("/roles"),
          apiRequest("/permissions"),
        ]);

        if (cancelled) return;

        setRoles(rolesData);
        setPermissions(permissionsData);

        const defaultRole = rolesData.some(
          (role: Role) => role.code === "ADMIN",
        )
          ? "ADMIN"
          : rolesData[0]?.code;

        if (defaultRole) {
          setSelectedRole(defaultRole);
        }
      } catch (err) {
        if (!cancelled) {
          setError(
            err instanceof Error
              ? err.message
              : "Unable to load permission data.",
          );
        }
      } finally {
        if (!cancelled) setLoading(false);
      }
    }

    loadInitialData();

    return () => {
      cancelled = true;
    };
  }, [apiRequest]);

  // --------------------------------------
  // LOAD SELECTED ROLE PERMISSIONS
  // --------------------------------------

  useEffect(() => {
    if (!selectedRole) return;

    let cancelled = false;

    async function loadRolePermissions() {
      try {
        setLoading(true);
        setError("");
        setSuccess("");

        const data: RolePermissionResponse = await apiRequest(
          `/roles/${encodeURIComponent(selectedRole)}/permissions`,
        );

        if (cancelled) return;

        setSelectedPermissions(data.permissions);
        setOriginalPermissions(data.permissions);
      } catch (err) {
        if (!cancelled) {
          setError(
            err instanceof Error
              ? err.message
              : "Unable to load role permissions.",
          );
        }
      } finally {
        if (!cancelled) setLoading(false);
      }
    }

    loadRolePermissions();

    return () => {
      cancelled = true;
    };
  }, [selectedRole, apiRequest]);

  // --------------------------------------
  // GROUP PERMISSIONS BY MODULE
  // --------------------------------------

  const groupedPermissions = useMemo(() => {
    return permissions.reduce<Record<string, Permission[]>>(
      (groups, permission) => {
        if (!groups[permission.module]) {
          groups[permission.module] = [];
        }

        groups[permission.module].push(permission);

        return groups;
      },
      {},
    );
  }, [permissions]);

  const modules = Object.keys(groupedPermissions).sort();

  // --------------------------------------
  // CHECK PERMISSION
  // --------------------------------------

  const hasPermission = (key: string) =>
    selectedPermissions.includes(key);

  // --------------------------------------
  // TOGGLE PERMISSION
  // --------------------------------------

  const togglePermission = (key: string) => {
    if (isSuperAdmin || loading || saving) return;

    setSelectedPermissions((current) =>
      current.includes(key)
        ? current.filter((item) => item !== key)
        : [...current, key],
    );

    setSuccess("");
    setError("");
  };

  // --------------------------------------
  // TOGGLE MODULE
  // --------------------------------------

  const toggleModule = (module: string) => {
    if (isSuperAdmin || loading || saving) return;

    const moduleKeys = groupedPermissions[module].map(
      (permission) => permission.key,
    );

    const allSelected = moduleKeys.every((key) =>
      selectedPermissions.includes(key),
    );

    setSelectedPermissions((current) =>
      allSelected
        ? current.filter((key) => !moduleKeys.includes(key))
        : [...new Set([...current, ...moduleKeys])],
    );

    setSuccess("");
    setError("");
  };

  // --------------------------------------
  // SAVE PERMISSIONS
  // --------------------------------------

  const savePermissions = async () => {
    try {
      setSaving(true);
      setError("");
      setSuccess("");

      await apiRequest(
        `/roles/${encodeURIComponent(selectedRole)}/permissions`,
        {
          method: "PUT",
          body: JSON.stringify({
            permissions: selectedPermissions,
          }),
        },
      );

      await queryClient.invalidateQueries({
        queryKey: rolePermissionsQueryKey(selectedRole),
      });

      setOriginalPermissions(selectedPermissions);

      setSuccess(
        `${selectedRole} permissions updated successfully.`,
      );
    } catch (err) {
      setError(
        err instanceof Error
          ? err.message
          : "Unable to save permissions.",
      );
    } finally {
      setSaving(false);
    }
  };

  // --------------------------------------
  // RESET UNSAVED CHANGES
  // --------------------------------------

  const resetChanges = () => {
    setSelectedPermissions(originalPermissions);
    setError("");
    setSuccess("");
  };

  const hasChanges =
    selectedPermissions.length !== originalPermissions.length ||
    selectedPermissions.some(
      (key) => !originalPermissions.includes(key),
    );

  // --------------------------------------
  // UI
  // --------------------------------------

  if (loading && roles.length === 0) {
    return (
      <div className="flex min-h-[400px] items-center justify-center">
        <div className="flex flex-col items-center gap-3">
          <div className="h-8 w-8 animate-spin rounded-full border-2 border-orange-600 border-t-transparent" />
          <p className="text-sm text-gray-500">
            Loading permission management...
          </p>
        </div>
      </div>
    );
  }

  return (
    <div className="min-h-screen bg-gray-50">
      <div className="mx-auto max-w-7xl space-y-6 p-4 md:p-6 lg:p-8">

        {/* HEADER */}
        <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
          <div>
            <h1 className="text-2xl font-bold text-gray-900">
              Role Permissions
            </h1>
            <p className="mt-1 text-sm text-gray-500">
              Manage role-based access to your SQ Group dashboard.
            </p>
          </div>

          <div className="flex gap-2">
            <button
              type="button"
              onClick={resetChanges}
              disabled={!hasChanges || saving || loading}
              className="rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 disabled:opacity-40"
            >
              Reset
            </button>

            <button
              type="button"
              onClick={savePermissions}
              disabled={!hasChanges || saving || loading || isSuperAdmin}
              className="rounded-lg bg-orange-600 px-5 py-2 text-sm font-semibold text-white shadow-sm transition-colors hover:bg-orange-700 disabled:cursor-not-allowed disabled:opacity-50"
            >
              {saving ? "Saving..." : "Save Changes"}
            </button>
          </div>
        </div>

        {/* ALERTS */}
        {error && (
          <div
            role="alert"
            className="flex items-start gap-3 rounded-xl border border-red-200 bg-red-50 p-4 text-sm text-red-700"
          >
            <svg
              className="mt-0.5 h-5 w-5 flex-shrink-0"
              fill="currentColor"
              viewBox="0 0 20 20"
            >
              <path
                fillRule="evenodd"
                d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
                clipRule="evenodd"
              />
            </svg>
            <span>{error}</span>
          </div>
        )}

        {success && (
          <div
            role="status"
            className="flex items-start gap-3 rounded-xl border border-green-200 bg-green-50 p-4 text-sm text-green-700"
          >
            <svg
              className="mt-0.5 h-5 w-5 flex-shrink-0"
              fill="currentColor"
              viewBox="0 0 20 20"
            >
              <path
                fillRule="evenodd"
                d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
                clipRule="evenodd"
              />
            </svg>
            <span>{success}</span>
          </div>
        )}

        {/* ROLE SELECTOR */}
        <div className="rounded-xl border border-gray-200 bg-white p-5 shadow-sm">
          <label
            htmlFor="role"
            className="mb-2 block text-sm font-semibold text-gray-900"
          >
            Select Role
          </label>

          <select
            id="role"
            value={selectedRole}
            onChange={(event) => setSelectedRole(event.target.value)}
            disabled={saving || loading}
            className="w-full max-w-md rounded-lg border border-gray-300 bg-white px-4 py-3 text-sm text-gray-900 outline-none transition-colors focus:border-orange-500 focus:ring-2 focus:ring-orange-500/20 disabled:opacity-50"
          >
            {roles.map((role) => (
              <option key={role.id} value={role.code}>
                {role.name} ({role.code})
              </option>
            ))}
          </select>

          <p className="mt-2 text-xs text-gray-500">
            Selected role: <span className="font-medium">{selectedRole}</span>
          </p>

          {isSuperAdmin && (
            <div className="mt-3 flex items-start gap-2 rounded-lg bg-amber-50 p-3 text-sm text-amber-700">
              <svg
                className="mt-0.5 h-4 w-4 flex-shrink-0"
                fill="currentColor"
                viewBox="0 0 20 20"
              >
                <path
                  fillRule="evenodd"
                  d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z"
                  clipRule="evenodd"
                />
              </svg>
              <span>
                SUPER_ADMIN has unrestricted access. Its permissions
                cannot be changed from this page.
              </span>
            </div>
          )}
        </div>

        {/* SUMMARY CARDS */}
        <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
          <div className="rounded-xl border border-gray-200 bg-white p-5 shadow-sm">
            <div className="flex items-center gap-3">
              <div className="rounded-lg bg-blue-100 p-2.5 text-blue-600">
                <svg className="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
                </svg>
              </div>
              <div>
                <p className="text-sm text-gray-500">Total Permissions</p>
                <h2 className="text-2xl font-bold text-gray-900">
                  {permissions.length}
                </h2>
              </div>
            </div>
          </div>

          <div className="rounded-xl border border-gray-200 bg-white p-5 shadow-sm">
            <div className="flex items-center gap-3">
              <div className="rounded-lg bg-green-100 p-2.5 text-green-600">
                <svg className="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
                </svg>
              </div>
              <div>
                <p className="text-sm text-gray-500">Assigned Permissions</p>
                <h2 className="text-2xl font-bold text-green-600">
                  {isSuperAdmin ? "ALL" : selectedPermissions.length}
                </h2>
              </div>
            </div>
          </div>

          <div className="rounded-xl border border-gray-200 bg-white p-5 shadow-sm">
            <div className="flex items-center gap-3">
              <div className="rounded-lg bg-purple-100 p-2.5 text-purple-600">
                <svg className="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" />
                </svg>
              </div>
              <div>
                <p className="text-sm text-gray-500">Permission Modules</p>
                <h2 className="text-2xl font-bold text-gray-900">
                  {modules.length}
                </h2>
              </div>
            </div>
          </div>
        </div>

        {/* PERMISSION GROUPS */}
        <div className="space-y-4">
          <div>
            <h2 className="text-lg font-bold text-gray-900">
              Available Permissions
            </h2>
            <p className="mt-1 text-sm text-gray-500">
              Select the permissions this role is allowed to use.
            </p>
          </div>

          {loading ? (
            <div className="rounded-xl border border-gray-200 bg-white p-8 text-center">
              <div className="flex flex-col items-center gap-3">
                <div className="h-6 w-6 animate-spin rounded-full border-2 border-orange-600 border-t-transparent" />
                <p className="text-sm text-gray-500">
                  Loading role permissions...
                </p>
              </div>
            </div>
          ) : (
            <div className="grid grid-cols-1 gap-4 xl:grid-cols-2">
              {modules.map((module) => {
                const moduleItems = groupedPermissions[module];

                const selectedCount = moduleItems.filter((permission) =>
                  hasPermission(permission.key),
                ).length;

                const allSelected = selectedCount === moduleItems.length;

                return (
                  <section
                    key={module}
                    className="overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm"
                  >
                    {/* MODULE HEADER */}
                    <div className="flex items-center justify-between border-b border-gray-200 bg-gray-50 px-5 py-4">
                      <div>
                        <div className="flex items-center gap-2">
                          <h3 className="font-semibold text-gray-900">
                            {module}
                          </h3>
                          <span className="rounded-full bg-gray-200 px-2 py-0.5 text-xs font-medium text-gray-600">
                            {moduleItems.length}
                          </span>
                        </div>
                        <p className="mt-1 text-xs text-gray-500">
                          {selectedCount} of {moduleItems.length} selected
                        </p>
                      </div>

                      <button
                        type="button"
                        disabled={isSuperAdmin || saving}
                        onClick={() => toggleModule(module)}
                        className={`rounded-lg px-3 py-1.5 text-sm font-semibold transition-colors disabled:opacity-40 ${
                          allSelected
                            ? "bg-orange-100 text-orange-700 hover:bg-orange-200"
                            : "bg-orange-600 text-white hover:bg-orange-700"
                        }`}
                      >
                        {allSelected ? "Deselect All" : "Select All"}
                      </button>
                    </div>

                    {/* PERMISSION LIST */}
                    <div className="divide-y divide-gray-100">
                      {moduleItems.map((permission) => {
                        const isChecked = hasPermission(permission.key);

                        return (
                          <label
                            key={permission.id}
                            className={`flex cursor-pointer items-start gap-3 px-5 py-4 transition-colors ${
                              isSuperAdmin || saving
                                ? "cursor-not-allowed opacity-60"
                                : "hover:bg-gray-50"
                            }`}
                          >
                            <div className="relative flex items-center pt-0.5">
                              <input
                                type="checkbox"
                                checked={isChecked}
                                disabled={isSuperAdmin || saving}
                                onChange={() => togglePermission(permission.key)}
                                className="peer h-5 w-5 cursor-pointer appearance-none rounded border-2 border-gray-300 bg-white transition-colors checked:border-orange-600 checked:bg-orange-600 disabled:cursor-not-allowed"
                              />
                              <svg
                                className="pointer-events-none absolute left-0.5 top-0.5 h-4 w-4 text-white opacity-0 peer-checked:opacity-100"
                                fill="none"
                                stroke="currentColor"
                                viewBox="0 0 24 24"
                              >
                                <path
                                  strokeLinecap="round"
                                  strokeLinejoin="round"
                                  strokeWidth={3}
                                  d="M5 13l4 4L19 7"
                                />
                              </svg>
                            </div>

                            <span className="min-w-0 flex-1">
                              <span
                                className={`block text-sm font-medium ${
                                  isChecked ? "text-gray-900" : "text-gray-700"
                                }`}
                              >
                                {permission.name}
                              </span>

                              <span className="mt-1 block font-mono text-xs text-gray-400">
                                {permission.key}
                              </span>

                              {permission.description && (
                                <span className="mt-1 block text-xs text-gray-400">
                                  {permission.description}
                                </span>
                              )}
                            </span>

                            {isChecked && (
                              <span className="ml-auto flex-shrink-0 rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-700">
                                Granted
                              </span>
                            )}
                          </label>
                        );
                      })}
                    </div>
                  </section>
                );
              })}
            </div>
          )}
        </div>

        {/* BOTTOM SAVE BAR */}
        <div className="sticky bottom-4 z-10 flex flex-col justify-between gap-3 rounded-xl border border-gray-200 bg-white p-5 shadow-lg sm:flex-row sm:items-center">
          <div>
            <p className="font-semibold text-gray-900">
              {selectedPermissions.length} permissions selected
            </p>

            <p className="text-xs text-gray-500">
              {hasChanges
                ? "You have unsaved changes."
                : "Changes are not active until you save them."}
            </p>
          </div>

          <div className="flex gap-2">
            <button
              type="button"
              onClick={resetChanges}
              disabled={!hasChanges || saving || loading}
              className="rounded-lg border border-gray-300 bg-white px-4 py-2.5 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 disabled:opacity-40"
            >
              Reset
            </button>

            <button
              type="button"
              onClick={savePermissions}
              disabled={!hasChanges || saving || loading || isSuperAdmin}
              className="rounded-lg bg-orange-600 px-6 py-2.5 text-sm font-semibold text-white shadow-sm transition-colors hover:bg-orange-700 disabled:opacity-50"
            >
              {saving ? (
                <span className="flex items-center gap-2">
                  <span className="h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent" />
                  Saving...
                </span>
              ) : (
                "Save Permissions"
              )}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}