import React, { useEffect, useMemo, useState } from 'react';
import { Checkbox, Modal, Spin, message } from 'antd';
import { customRequest } from '@/helpers/http';

interface Role {
  id: number;
  name: string;
  description?: string;
}

interface RolePage {
  roleId: number;
  pageId: number;
}

interface AssignRolesModalProps {
  pageId: number;
  pageName: string;
  open: boolean;
  onClose: () => void;
  onSuccess: () => void;
}

export const AssignRolesModal: React.FC<AssignRolesModalProps> = ({
  pageId,
  pageName,
  open,
  onClose,
  onSuccess,
}) => {
  const [roles, setRoles] = useState<Role[]>([]);
  const [rolePages, setRolePages] = useState<RolePage[]>([]);
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [selectedRoleIds, setSelectedRoleIds] = useState<number[]>([]);

  // Fetch all roles and rolePages when modal opens
  useEffect(() => {
    if (!open) return;

    const fetchData = async () => {
      setLoading(true);
      try {
        const [rolesRes, rolePagesRes] = await Promise.all([
          customRequest<{ data: Role[] }>('role/findMany', 'post'),
          customRequest<{ data: RolePage[] }>('rolePages/findMany', 'post'),
        ]);
        const rolesData: Role[] = Array.isArray(rolesRes?.data)
          ? rolesRes.data
          : [];
        const rolePagesData: RolePage[] = Array.isArray(rolePagesRes?.data)
          ? rolePagesRes.data
          : [];
        setRoles(rolesData);
        setRolePages(rolePagesData);
      } catch (error) {
        console.error('Failed to fetch data:', error);
        message.error('Failed to load roles data');
      }
      setLoading(false);
    };

    fetchData();
  }, [open]);

  // Role IDs that already have this page assigned
  const existingRoleIds = useMemo(() => {
    return rolePages
      .filter((rp) => rp.pageId === pageId)
      .map((rp) => rp.roleId);
  }, [rolePages, pageId]);

  // Initialize selected roles when data loads
  useEffect(() => {
    setSelectedRoleIds(existingRoleIds);
  }, [existingRoleIds]);

  // Build a map: roleId -> all pageIds for that role
  const rolePageIdsMap = useMemo(() => {
    const map: Record<number, number[]> = {};
    for (const rp of rolePages) {
      if (!map[rp.roleId]) {
        map[rp.roleId] = [];
      }
      if (!map[rp.roleId].includes(rp.pageId)) {
        map[rp.roleId].push(rp.pageId);
      }
    }
    return map;
  }, [rolePages]);

  const handleSave = async () => {
    // Find newly added role IDs (not in existingRoleIds)
    const newRoleIds = selectedRoleIds.filter(
      (id) => !existingRoleIds.includes(id),
    );

    if (newRoleIds.length === 0) {
      message.info('No new roles selected');
      onClose();
      return;
    }

    setSaving(true);
    try {
      const updatePromises = newRoleIds.map((roleId) => {
        const currentPageIds = rolePageIdsMap[roleId] || [];
        const updatedPageIds = [...currentPageIds, pageId];
        return customRequest(`role/updateUnique/${roleId}`, 'PATCH', {
          pageIds: updatedPageIds,
        });
      });

      await Promise.all(updatePromises);
      message.success(
        `Successfully assigned ${newRoleIds.length} role(s) to page "${pageName}"`,
      );
      onSuccess();
    } catch (error) {
      console.error('Failed to assign roles:', error);
      message.error('Failed to assign some roles. Please try again.');
    }
    setSaving(false);
  };

  return (
    <Modal
      title={`Assign Roles to Page: ${pageName}`}
      open={open}
      onCancel={onClose}
      onOk={handleSave}
      okText="Save"
      confirmLoading={saving}
      width={560}
    >
      <Spin spinning={loading}>
        {existingRoleIds.length > 0 && (
          <div style={{ marginBottom: 12, color: '#666' }}>
            Currently <strong>{existingRoleIds.length}</strong> role(s) can
            access this page
          </div>
        )}
        <div style={{ maxHeight: 400, overflow: 'auto' }}>
          <Checkbox.Group
            value={selectedRoleIds}
            onChange={(values) => setSelectedRoleIds(values as number[])}
            style={{ display: 'flex', flexDirection: 'column', gap: 8 }}
          >
            {[...roles]
              .sort((a, b) => {
                const aExisting = existingRoleIds.includes(a.id);
                const bExisting = existingRoleIds.includes(b.id);
                if (aExisting !== bExisting) return aExisting ? -1 : 1;
                return 0;
              })
              .map((role) => {
                const isExisting = existingRoleIds.includes(role.id);
                return (
                  <Checkbox key={role.id} value={role.id} disabled={isExisting}>
                    <span style={{ fontWeight: 500 }}>{role.name}</span>
                    {role.description && (
                      <span style={{ color: '#999', marginLeft: 8 }}>
                        {role.description}
                      </span>
                    )}
                  </Checkbox>
                );
              })}
          </Checkbox.Group>
          {!loading && roles.length === 0 && (
            <span style={{ color: '#999' }}>No roles available</span>
          )}
        </div>
      </Spin>
    </Modal>
  );
};
