"use client";

import { useState } from "react";
import { PermissionKey } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";

const ALL_PERMISSION_KEYS = Object.values(PermissionKey);

const PERMISSION_LABELS: Record<string, string> = {
  viewPlanning: "View Planning",
  viewCosts: "View Costs",
  useAssistantAdvancedTools: "Assistant Advanced Tools",
  exportData: "Export Data",
  importData: "Import Data",
  approveVacations: "Approve Vacations",
  manageBlueprints: "Manage Blueprints",
  viewAllResources: "View All Resources",
  manageResources: "Manage Resources",
  manageProjects: "Manage Projects",
  manageAllocations: "Manage Allocations",
  manageRoles: "Manage Roles",
  manageUsers: "Manage Users",
  viewScores: "View Scores",
};

const PERMISSION_DESCRIPTIONS: Record<string, string> = {
  viewPlanning: "Read project and allocation planning views without mutation access",
  viewCosts: "Access to cost data, budget views, and financial reports",
  useAssistantAdvancedTools: "Unlocks advanced AI assistant workflows for complex cross-entity analyses",
  exportData: "Export data to Excel, CSV, or PDF formats",
  importData: "Import data from external sources (Dispo, Excel)",
  approveVacations: "Approve or reject vacation requests",
  manageBlueprints: "Create and edit blueprint field definitions",
  viewAllResources: "View all resources (not just own team)",
  manageResources: "Create, edit, and deactivate resource records",
  manageProjects: "Create, edit, and manage project records",
  manageAllocations: "Create, edit, and delete allocations",
  manageRoles: "Create and edit project roles",
  manageUsers: "Manage user accounts and permissions",
  viewScores: "View value scores and skill analytics",
};

const COLOR_OPTIONS = [
  { value: "purple", label: "Purple", class: "bg-purple-500" },
  { value: "blue", label: "Blue", class: "bg-blue-500" },
  { value: "amber", label: "Amber", class: "bg-amber-500" },
  { value: "green", label: "Green", class: "bg-green-500" },
  { value: "red", label: "Red", class: "bg-red-500" },
  { value: "gray", label: "Gray", class: "bg-gray-500" },
  { value: "indigo", label: "Indigo", class: "bg-indigo-500" },
  { value: "teal", label: "Teal", class: "bg-teal-500" },
];

const ROLE_COLOR_MAP: Record<string, string> = {
  purple: "border-purple-300 bg-purple-50 dark:border-purple-700 dark:bg-purple-900/20",
  blue: "border-blue-300 bg-blue-50 dark:border-blue-700 dark:bg-blue-900/20",
  amber: "border-amber-300 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20",
  green: "border-green-300 bg-green-50 dark:border-green-700 dark:bg-green-900/20",
  red: "border-red-300 bg-red-50 dark:border-red-700 dark:bg-red-900/20",
  gray: "border-gray-300 bg-gray-50 dark:border-gray-700 dark:bg-gray-800/50",
  indigo: "border-indigo-300 bg-indigo-50 dark:border-indigo-700 dark:bg-indigo-900/20",
  teal: "border-teal-300 bg-teal-50 dark:border-teal-700 dark:bg-teal-900/20",
};

const ROLE_BADGE_MAP: Record<string, string> = {
  purple: "bg-purple-100 text-purple-700 dark:bg-purple-900/40 dark:text-purple-400",
  blue: "bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-400",
  amber: "bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-400",
  green: "bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-400",
  red: "bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-400",
  gray: "bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400",
  indigo: "bg-indigo-100 text-indigo-700 dark:bg-indigo-900/40 dark:text-indigo-400",
  teal: "bg-teal-100 text-teal-700 dark:bg-teal-900/40 dark:text-teal-400",
};

type RoleConfig = {
  role: string;
  label: string;
  description: string | null;
  defaultPermissions: unknown;
  color: string | null;
  sortOrder: number;
};

type EditingRole = {
  role: string;
  label: string;
  description: string;
  color: string;
  permissions: Set<string>;
};

export function SystemRolesClient() {
  const [editingRole, setEditingRole] = useState<EditingRole | null>(null);
  const [actionError, setActionError] = useState<string | null>(null);
  const [successMessage, setSuccessMessage] = useState<string | null>(null);

  const utils = trpc.useUtils();
  const { data: roleConfigs, isLoading } = trpc.systemRoleConfig.list.useQuery(undefined, {
    staleTime: 10_000,
  });

  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore TS2589: tRPC infers union type too deeply for the role config update payload
  const updateMutation = trpc.systemRoleConfig.update.useMutation({
    onSuccess: async () => {
      await utils.systemRoleConfig.list.invalidate();
      setEditingRole(null);
      setActionError(null);
      setSuccessMessage("Role permissions updated successfully");
      setTimeout(() => setSuccessMessage(null), 3000);
    },
    onError: (err) => setActionError(err.message),
  });

  function openEdit(config: RoleConfig) {
    setEditingRole({
      role: config.role,
      label: config.label,
      description: config.description ?? "",
      color: config.color ?? "gray",
      permissions: new Set(config.defaultPermissions as string[]),
    });
    setActionError(null);
    setSuccessMessage(null);
  }

  function togglePermission(key: string) {
    if (!editingRole) return;
    const next = new Set(editingRole.permissions);
    if (next.has(key)) {
      next.delete(key);
    } else {
      next.add(key);
    }
    setEditingRole({ ...editingRole, permissions: next });
  }

  function selectAll() {
    if (!editingRole) return;
    setEditingRole({ ...editingRole, permissions: new Set(ALL_PERMISSION_KEYS) });
  }

  function selectNone() {
    if (!editingRole) return;
    setEditingRole({ ...editingRole, permissions: new Set() });
  }

  async function handleSave() {
    if (!editingRole) return;
    setActionError(null);
    await updateMutation.mutateAsync({
      role: editingRole.role,
      label: editingRole.label,
      description: editingRole.description || null,
      color: editingRole.color,
      defaultPermissions: Array.from(editingRole.permissions),
    });
  }

  const configs = (roleConfigs ?? []) as unknown as RoleConfig[];

  return (
    <div className="p-6 max-w-4xl mx-auto">
      <div className="mb-6">
        <h1 className="text-2xl font-bold text-gray-900 dark:text-gray-50">System Role Management</h1>
        <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">
          Configure default permissions for each system role. Changes apply to all users with that role.
        </p>
      </div>

      {successMessage && (
        <div className="mb-4 rounded-lg bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-700 px-4 py-3 text-sm text-green-700 dark:text-green-400">
          {successMessage}
        </div>
      )}

      {isLoading && (
        <div className="space-y-3">
          {[...Array(5)].map((_, i) => (
            <div key={i} className="h-24 shimmer-skeleton rounded-xl animate-row-enter" style={{ animationDelay: `${i * 50}ms` }} />
          ))}
        </div>
      )}

      {/* Role Cards */}
      <div className="space-y-3">
        {configs.map((config) => {
          const perms = config.defaultPermissions as string[];
          const color = config.color ?? "gray";
          return (
            <div
              key={config.role}
              className={`rounded-xl border-2 p-4 transition-colors ${ROLE_COLOR_MAP[color] ?? ROLE_COLOR_MAP.gray}`}
            >
              <div className="flex items-start justify-between">
                <div className="flex-1">
                  <div className="flex items-center gap-3 mb-1">
                    <span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-semibold ${ROLE_BADGE_MAP[color] ?? ROLE_BADGE_MAP.gray}`}>
                      {config.label}
                    </span>
                    <span className="text-xs text-gray-400 dark:text-gray-500 font-mono">
                      {config.role}
                    </span>
                  </div>
                  {config.description && (
                    <p className="text-sm text-gray-600 dark:text-gray-400 mt-1">
                      {config.description}
                    </p>
                  )}
                  <div className="flex flex-wrap gap-1 mt-2">
                    {perms.length === 0 ? (
                      <span className="text-xs text-gray-400 dark:text-gray-500 italic">No default permissions</span>
                    ) : (
                      perms.map((p) => (
                        <span
                          key={p}
                          className="inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-white/60 dark:bg-white/10 text-gray-700 dark:text-gray-300"
                        >
                          {PERMISSION_LABELS[p] ?? p}
                        </span>
                      ))
                    )}
                  </div>
                </div>
                <button
                  type="button"
                  onClick={() => openEdit(config)}
                  className="flex-shrink-0 ml-4 px-3 py-1.5 text-xs font-medium rounded-lg border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-white/50 dark:hover:bg-gray-800/50 transition-colors"
                >
                  Configure
                </button>
              </div>
            </div>
          );
        })}
      </div>

      {/* Permission Matrix Overview */}
      {configs.length > 0 && (
        <div className="mt-8">
          <h2 className="text-lg font-semibold text-gray-900 dark:text-gray-50 mb-3 flex items-center">
            Permission Matrix <InfoTooltip content="Overview of which permissions each role has by default." />
          </h2>
          <div className="bg-white dark:bg-gray-900 rounded-xl border border-gray-200 dark:border-gray-700 overflow-x-auto">
            <table className="w-full text-xs">
              <thead>
                <tr className="border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50">
                  <th className="px-3 py-2 text-left font-medium text-gray-600 dark:text-gray-400 sticky left-0 bg-gray-50 dark:bg-gray-800/50">Permission</th>
                  {configs.map((c) => (
                    <th key={c.role} className="px-3 py-2 text-center font-medium text-gray-600 dark:text-gray-400 min-w-[80px]">
                      {c.label}
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {ALL_PERMISSION_KEYS.map((key) => (
                  <tr key={key} className="border-b border-gray-100 dark:border-gray-800">
                    <td className="px-3 py-1.5 text-gray-700 dark:text-gray-300 font-medium sticky left-0 bg-white dark:bg-gray-900">
                      {PERMISSION_LABELS[key] ?? key}
                    </td>
                    {configs.map((c) => {
                      const perms = c.defaultPermissions as string[];
                      const has = perms.includes(key);
                      return (
                        <td key={c.role} className="px-3 py-1.5 text-center">
                          {has ? (
                            <span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-100 dark:bg-green-900/40 text-green-600 dark:text-green-400">
                              <svg className="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
                                <path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
                              </svg>
                            </span>
                          ) : (
                            <span className="inline-flex items-center justify-center w-5 h-5 rounded-full text-gray-300 dark:text-gray-600">
                              &mdash;
                            </span>
                          )}
                        </td>
                      );
                    })}
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {/* Edit Modal */}
      {editingRole && (
        <div className="fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4">
          <div className="bg-white dark:bg-gray-900 rounded-xl shadow-2xl w-full max-w-lg mx-4 flex flex-col max-h-[90vh]">
            <div className="flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700">
              <div>
                <h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">
                  Configure Role
                </h2>
                <p className="text-sm text-gray-500 dark:text-gray-400 mt-0.5">
                  {editingRole.role}
                </p>
              </div>
              <button
                type="button"
                onClick={() => { setEditingRole(null); setActionError(null); }}
                className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-2xl leading-none"
              >
                &times;
              </button>
            </div>

            <div className="overflow-y-auto flex-1 px-6 py-5 space-y-5">
              {actionError && (
                <div className="rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-700 px-3 py-2 text-sm text-red-700 dark:text-red-400">
                  {actionError}
                </div>
              )}

              {/* Label */}
              <div>
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
                  Display Name
                </label>
                <input
                  type="text"
                  value={editingRole.label}
                  onChange={(e) => setEditingRole({ ...editingRole, label: e.target.value })}
                  className="border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-2 text-sm w-full bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-brand-400"
                />
              </div>

              {/* Description */}
              <div>
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
                  Description
                </label>
                <input
                  type="text"
                  value={editingRole.description}
                  onChange={(e) => setEditingRole({ ...editingRole, description: e.target.value })}
                  placeholder="Brief description of this role..."
                  className="border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-2 text-sm w-full bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-brand-400"
                />
              </div>

              {/* Color */}
              <div>
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
                  Badge Color
                </label>
                <div className="flex gap-2">
                  {COLOR_OPTIONS.map((opt) => (
                    <button
                      key={opt.value}
                      type="button"
                      onClick={() => setEditingRole({ ...editingRole, color: opt.value })}
                      className={`w-7 h-7 rounded-full ${opt.class} transition-all ${
                        editingRole.color === opt.value
                          ? "ring-2 ring-offset-2 ring-brand-500 dark:ring-offset-gray-900 scale-110"
                          : "opacity-60 hover:opacity-100"
                      }`}
                      title={opt.label}
                    />
                  ))}
                </div>
              </div>

              {/* Permissions */}
              <div>
                <div className="flex items-center justify-between mb-2">
                  <label className="text-sm font-medium text-gray-700 dark:text-gray-300">
                    Default Permissions ({editingRole.permissions.size}/{ALL_PERMISSION_KEYS.length})
                  </label>
                  <div className="flex gap-2">
                    <button
                      type="button"
                      onClick={selectAll}
                      className="text-[11px] text-brand-600 hover:text-brand-800 font-medium"
                    >
                      Select all
                    </button>
                    <button
                      type="button"
                      onClick={selectNone}
                      className="text-[11px] text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 font-medium"
                    >
                      Clear all
                    </button>
                  </div>
                </div>
                <div className="space-y-1">
                  {ALL_PERMISSION_KEYS.map((key) => {
                    const isActive = editingRole.permissions.has(key);
                    return (
                      <button
                        key={key}
                        type="button"
                        onClick={() => togglePermission(key)}
                        className={`flex items-center gap-2.5 w-full px-3 py-2 rounded-lg border text-sm text-left transition-colors ${
                          isActive
                            ? "bg-green-50 border-green-200 dark:bg-green-900/20 dark:border-green-800"
                            : "bg-gray-50 border-gray-200 dark:bg-gray-800/50 dark:border-gray-700 hover:bg-gray-100 dark:hover:bg-gray-800"
                        }`}
                      >
                        <span className={`flex-shrink-0 w-4 h-4 rounded border flex items-center justify-center ${
                          isActive
                            ? "text-green-600 border-green-300 bg-green-100 dark:bg-green-900/40"
                            : "border-gray-300 dark:border-gray-600"
                        }`}>
                          {isActive && (
                            <svg className="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
                              <path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
                            </svg>
                          )}
                        </span>
                        <div className="flex-1 min-w-0">
                          <span className={isActive ? "text-gray-900 dark:text-gray-100 font-medium" : "text-gray-500 dark:text-gray-400"}>
                            {PERMISSION_LABELS[key] ?? key}
                          </span>
                          <p className="text-[11px] text-gray-400 dark:text-gray-500 mt-0.5 truncate">
                            {PERMISSION_DESCRIPTIONS[key] ?? ""}
                          </p>
                        </div>
                      </button>
                    );
                  })}
                </div>
              </div>
            </div>

            <div className="flex items-center justify-end gap-3 px-6 py-4 border-t border-gray-200 dark:border-gray-700">
              <button
                type="button"
                onClick={() => { setEditingRole(null); setActionError(null); }}
                className="px-4 py-2 text-sm text-gray-600 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200"
              >
                Cancel
              </button>
              <button
                type="button"
                onClick={() => void handleSave()}
                disabled={updateMutation.isPending || !editingRole.label.trim()}
                className="px-4 py-2 bg-brand-600 text-white rounded-lg hover:bg-brand-700 text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed"
              >
                {updateMutation.isPending ? "Saving..." : "Save Changes"}
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
