import { useEffect, useState, useCallback } from 'react';
import { useParams, Link } from 'react-router-dom';
import { useRoleStore, type Role, type CreateRoleData, type UpdateRoleData } from '../stores/role.ts';

// Permission bitflags
const PERMS = {
  VIEW_CHANNEL: 1,
  SEND_MESSAGES: 2,
  MANAGE_MESSAGES: 4,
  KICK_MEMBERS: 8,
  BAN_MEMBERS: 16,
  MANAGE_SERVER: 32,
  MANAGE_CHANNELS: 64,
  ADMINISTRATOR: 128,
  CONNECT_VOICE: 256,
  SPEAK_VOICE: 512,
  SHARE_SCREEN: 1024,
  MUTE_MEMBERS: 2048,
  CREATE_INSTANT_INVITE: 4096,
  CHANGE_NICKNAME: 8192,
  MANAGE_NICKNAMES: 16384,
  MANAGE_ROLES: 32768,
  MANAGE_WEBHOOKS: 65536,
  EMBED_LINKS: 131072,
  ATTACH_FILES: 262144,
  ADD_REACTIONS: 524288,
  USE_EXTERNAL_EMOJIS: 1048576,
  MENTION_EVERYONE: 2097152,
} as const;

const PERM_CATEGORIES = [
  {
    name: 'General',
    perms: [
      { key: 'VIEW_CHANNEL', label: 'View Channel', flag: PERMS.VIEW_CHANNEL },
      { key: 'SEND_MESSAGES', label: 'Send Messages', flag: PERMS.SEND_MESSAGES },
      { key: 'MANAGE_MESSAGES', label: 'Manage Messages', flag: PERMS.MANAGE_MESSAGES },
      { key: 'ADD_REACTIONS', label: 'Add Reactions', flag: PERMS.ADD_REACTIONS },
      { key: 'EMBED_LINKS', label: 'Embed Links', flag: PERMS.EMBED_LINKS },
      { key: 'ATTACH_FILES', label: 'Attach Files', flag: PERMS.ATTACH_FILES },
      { key: 'MENTION_EVERYONE', label: 'Mention @everyone', flag: PERMS.MENTION_EVERYONE },
      { key: 'USE_EXTERNAL_EMOJIS', label: 'Use External Emojis', flag: PERMS.USE_EXTERNAL_EMOJIS },
    ],
  },
  {
    name: 'Moderation',
    perms: [
      { key: 'KICK_MEMBERS', label: 'Kick Members', flag: PERMS.KICK_MEMBERS },
      { key: 'BAN_MEMBERS', label: 'Ban Members', flag: PERMS.BAN_MEMBERS },
      { key: 'MUTE_MEMBERS', label: 'Mute Members', flag: PERMS.MUTE_MEMBERS },
      { key: 'MANAGE_NICKNAMES', label: 'Manage Nicknames', flag: PERMS.MANAGE_NICKNAMES },
      { key: 'CHANGE_NICKNAME', label: 'Change Nickname', flag: PERMS.CHANGE_NICKNAME },
    ],
  },
  {
    name: 'Server',
    perms: [
      { key: 'MANAGE_SERVER', label: 'Manage Server', flag: PERMS.MANAGE_SERVER },
      { key: 'MANAGE_CHANNELS', label: 'Manage Channels', flag: PERMS.MANAGE_CHANNELS },
      { key: 'MANAGE_ROLES', label: 'Manage Roles', flag: PERMS.MANAGE_ROLES },
      { key: 'MANAGE_WEBHOOKS', label: 'Manage Webhooks', flag: PERMS.MANAGE_WEBHOOKS },
      { key: 'CREATE_INSTANT_INVITE', label: 'Create Instant Invite', flag: PERMS.CREATE_INSTANT_INVITE },
      { key: 'ADMINISTRATOR', label: 'Administrator', flag: PERMS.ADMINISTRATOR },
    ],
  },
  {
    name: 'Voice',
    perms: [
      { key: 'CONNECT_VOICE', label: 'Connect Voice', flag: PERMS.CONNECT_VOICE },
      { key: 'SPEAK_VOICE', label: 'Speak Voice', flag: PERMS.SPEAK_VOICE },
      { key: 'SHARE_SCREEN', label: 'Share Screen', flag: PERMS.SHARE_SCREEN },
    ],
  },
];

const GRUVBOX_COLORS = [
  '#fb4934', '#b8bb26', '#fabd2f', '#83a598',
  '#d3869b', '#8ec07c', '#fe8019', '#ebdbb2',
  '#a89984', '#928374', '#282828',
];

function hasPerm(permissions: number, flag: number): boolean {
  return (permissions & flag) !== 0;
}

function permSummary(permissions: number): string {
  if (hasPerm(permissions, PERMS.ADMINISTRATOR)) return 'ADMINISTRATOR';
  const active: string[] = [];
  if (hasPerm(permissions, PERMS.MANAGE_SERVER)) active.push('MGR_SERVER');
  if (hasPerm(permissions, PERMS.MANAGE_CHANNELS)) active.push('MGR_CHAN');
  if (hasPerm(permissions, PERMS.MANAGE_ROLES)) active.push('MGR_ROLES');
  if (hasPerm(permissions, PERMS.MANAGE_MESSAGES)) active.push('MGR_MSG');
  if (hasPerm(permissions, PERMS.KICK_MEMBERS)) active.push('KICK');
  if (hasPerm(permissions, PERMS.BAN_MEMBERS)) active.push('BAN');
  if (hasPerm(permissions, PERMS.MUTE_MEMBERS)) active.push('MUTE');
  return active.length > 0 ? active.join('+') : 'BASIC';
}

interface RoleFormProps {
  serverId: string;
  role?: Role;
  onClose: () => void;
}

function RoleForm({ serverId, role, onClose }: RoleFormProps) {
  const createRole = useRoleStore((s) => s.createRole);
  const updateRole = useRoleStore((s) => s.updateRole);
  const loading = useRoleStore((s) => s.loading);

  const [name, setName] = useState(role?.name ?? '');
  const [color, setColor] = useState(role?.color ?? '#ebdbb2');
  const [position, setPosition] = useState(role?.position ?? 0);
  const [permissions, setPermissions] = useState(role?.permissions ?? 0);

  const togglePerm = useCallback((flag: number) => {
    setPermissions((prev) => prev ^ flag);
  }, []);

  const handleAdminToggle = useCallback(() => {
    setPermissions((prev) => {
      if (hasPerm(prev, PERMS.ADMINISTRATOR)) return 0;
      return 0xFFFFFFFF; // grant all
    });
  }, []);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!name.trim()) return;
    try {
      if (role) {
        const data: UpdateRoleData = { name: name.trim(), color, permissions, position };
        await updateRole(serverId, role.id, data);
      } else {
        const data: CreateRoleData = { name: name.trim(), color, permissions, position };
        await createRole(serverId, data);
      }
      onClose();
    } catch {
      // error in store
    }
  };

  return (
    <div className="fixed inset-0 bg-black/60 flex items-center justify-center z-50">
      <div className="border border-gb-bg-t bg-gb-bg p-6 max-w-lg w-full mx-4 max-h-[90vh] overflow-y-auto">
        <p className="text-gb-orange font-mono text-sm mb-4">
          {'>'} {role ? 'EDIT ROLE' : 'CREATE ROLE'}
        </p>
        <form onSubmit={handleSubmit} className="space-y-4">
          <div>
            <label className="block text-gb-fg-f mb-1 font-mono text-xs">NAME:</label>
            <input
              type="text"
              value={name}
              onChange={(e) => setName(e.target.value.slice(0, 64))}
              maxLength={64}
              className="terminal-input w-full"
              placeholder="role-name"
              autoFocus
            />
          </div>

          <div>
            <label className="block text-gb-fg-f mb-1 font-mono text-xs">COLOR:</label>
            <div className="flex flex-wrap gap-2 mb-2">
              {GRUVBOX_COLORS.map((c) => (
                <button
                  key={c}
                  type="button"
                  onClick={() => setColor(c)}
                  className={`w-7 h-7 border-2 transition-all ${
                    color === c ? 'border-gb-fg scale-110' : 'border-gb-bg-t'
                  }`}
                  style={{ backgroundColor: c }}
                  title={c}
                />
              ))}
            </div>
            <input
              type="text"
              value={color}
              onChange={(e) => setColor(e.target.value)}
              className="terminal-input w-full text-xs"
              placeholder="#ebdbb2"
            />
          </div>

          <div>
            <label className="block text-gb-fg-f mb-1 font-mono text-xs">POSITION:</label>
            <input
              type="number"
              value={position}
              onChange={(e) => setPosition(parseInt(e.target.value) || 0)}
              className="terminal-input w-24"
            />
          </div>

          <div>
            <label className="block text-gb-fg-f mb-2 font-mono text-xs">PERMISSIONS:</label>
            <div className="space-y-3">
              {/* Administrator all-or-nothing */}
              <div className="border border-gb-bg-t p-3">
                <label className="flex items-center gap-2 cursor-pointer font-mono text-xs">
                  <input
                    type="checkbox"
                    checked={hasPerm(permissions, PERMS.ADMINISTRATOR)}
                    onChange={handleAdminToggle}
                    className="accent-gb-red"
                  />
                  <span className="text-gb-red">Administrator (grants all permissions)</span>
                </label>
              </div>

              {/* Category groups */}
              {!hasPerm(permissions, PERMS.ADMINISTRATOR) &&
                PERM_CATEGORIES.filter((cat) => cat.name !== 'Server' || true).map((cat) => (
                  <div key={cat.name} className="border border-gb-bg-t p-3">
                    <p className="text-gb-aqua font-mono text-xs mb-2">[{cat.name.toUpperCase()}]</p>
                    <div className="space-y-1">
                      {cat.perms
                        .filter((p) => p.key !== 'ADMINISTRATOR')
                        .map((p) => (
                          <label
                            key={p.key}
                            className="flex items-center gap-2 cursor-pointer font-mono text-xs"
                          >
                            <input
                              type="checkbox"
                              checked={hasPerm(permissions, p.flag)}
                              onChange={() => togglePerm(p.flag)}
                              className="accent-gb-orange"
                            />
                            <span className="text-gb-fg">{p.label}</span>
                          </label>
                        ))}
                    </div>
                  </div>
                ))}
            </div>
          </div>

          <div className="flex gap-2 pt-2">
            <button type="submit" className="terminal-button" disabled={loading || !name.trim()}>
              {loading ? '[SAVING...]' : '[SAVE]'}
            </button>
            <button
              type="button"
              onClick={onClose}
              className="text-gb-fg-f hover:text-gb-aqua font-mono text-sm"
            >
              [CANCEL]
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

export function RoleManager() {
  const { serverId } = useParams<{ serverId: string }>();
  const roles = useRoleStore((s) => s.roles);
  const loading = useRoleStore((s) => s.loading);
  const error = useRoleStore((s) => s.error);
  const fetchRoles = useRoleStore((s) => s.fetchRoles);
  const deleteRole = useRoleStore((s) => s.deleteRole);

  const [showForm, setShowForm] = useState(false);
  const [editingRole, setEditingRole] = useState<Role | null>(null);

  useEffect(() => {
    if (serverId) fetchRoles(serverId);
  }, [serverId, fetchRoles]);

  const handleDelete = async (role: Role) => {
    if (!serverId) return;
    if (!window.confirm(`Delete role "${role.name}"? This cannot be undone.`)) return;
    try {
      await deleteRole(serverId, role.id);
    } catch {
      // error in store
    }
  };

  if (!serverId) {
    return (
      <div className="h-full w-full bg-gb-bg p-8 flex items-center justify-center">
        <p className="text-gb-red font-mono">ERR: no server selected</p>
      </div>
    );
  }

  return (
    <div className="h-full w-full bg-gb-bg p-4 md:p-8 overflow-y-auto">
      <div className="max-w-3xl mx-auto">
        <div className="border border-gb-bg-t p-6">
          <pre className="text-gb-orange font-mono text-center mb-6">
            {'┌──────────────────────────────────┐\n'}
            {'│      === ROLE MANAGER ===        │\n'}
            {'└──────────────────────────────────┘'}
          </pre>

          {error && (
            <p className="text-gb-red text-sm font-mono mb-4">ERR: {error}</p>
          )}

          <div className="mb-6">
            <button
              type="button"
              onClick={() => { setEditingRole(null); setShowForm(true); }}
              className="terminal-button"
            >
              [CREATE ROLE]
            </button>
          </div>

          {loading && roles.length === 0 && (
            <p className="text-gb-fg-f font-mono text-sm">[loading roles...]</p>
          )}
          {!loading && roles.length === 0 && (
            <p className="text-gb-fg-f font-mono text-sm">[no roles configured]</p>
          )}

          <div className="space-y-3">
            {roles.map((role) => (
              <div key={role.id} className="border border-gb-bg-t p-4">
                <div className="flex items-center gap-3 mb-2">
                  <span
                    className="inline-block w-4 h-4 border border-gb-bg-t shrink-0"
                    style={{ backgroundColor: role.color || '#ebdbb2' }}
                  />
                  <span
                    className="font-mono text-sm font-bold truncate"
                    style={{ color: role.color || '#ebdbb2' }}
                  >
                    {role.name}
                  </span>
                  {role.is_default && (
                    <span className="text-gb-fg-f font-mono text-xs">[DEFAULT]</span>
                  )}
                  <span className="text-gb-fg-f font-mono text-xs ml-auto shrink-0">
                    POS:{role.position}
                  </span>
                </div>
                <p className="text-gb-fg-f font-mono text-xs mb-3">
                  perms: {permSummary(role.permissions)}
                </p>
                <div className="flex gap-2">
                  <button
                    type="button"
                    onClick={() => { setEditingRole(role); setShowForm(true); }}
                    className="terminal-button text-xs"
                  >
                    [EDIT]
                  </button>
                  {!role.is_default && (
                    <button
                      type="button"
                      onClick={() => handleDelete(role)}
                      className="terminal-button text-xs hover:!text-gb-red"
                    >
                      [DELETE]
                    </button>
                  )}
                </div>
              </div>
            ))}
          </div>

          <div className="mt-6 pt-4 border-t border-gb-bg-t">
            <Link to="/" className="text-gb-fg-f hover:text-gb-aqua font-mono text-sm">
              {'<'} [BACK TO CHAT]
            </Link>
          </div>
        </div>
      </div>

      {showForm && (
        <RoleForm
          serverId={serverId}
          role={editingRole ?? undefined}
          onClose={() => { setShowForm(false); setEditingRole(null); }}
        />
      )}
    </div>
  );
}
