import { useState, useEffect, useMemo } from 'react';
import {
  Title, Text, Card, Stack, Group, Table, Checkbox, Button, Alert,
  Badge, Tooltip, Divider, Loader, Center,
} from '@mantine/core';
import { notifications } from '@mantine/notifications';
import { IconShieldCheck, IconRefresh, IconInfoCircle } from '@tabler/icons-react';
import { useAuthStore } from '../../stores/authStore';
import { CAPABILITY_AREAS } from '../../permissions/capabilities';
import { DEFAULT_ROLE_CAPABILITIES } from '../../permissions/default-role-capabilities';
import api from '../../services/api';

/** Roles shown as columns (homeowner hidden from UI per product decision) */
const DISPLAY_ROLES = [
  { value: 'president', label: 'President' },
  { value: 'vice_president', label: 'Vice President' },
  { value: 'treasurer', label: 'Treasurer' },
  { value: 'secretary', label: 'Secretary' },
  { value: 'member_at_large', label: 'Member at Large' },
  { value: 'manager', label: 'Property Manager' },
  { value: 'viewer', label: 'Viewer' },
];

interface PermissionOverrides {
  [role: string]: {
    grant?: string[];
    revoke?: string[];
  };
}

function buildCheckedState(overrides: PermissionOverrides): Record<string, Record<string, boolean>> {
  const state: Record<string, Record<string, boolean>> = {};
  for (const role of DISPLAY_ROLES) {
    const defaults = new Set(DEFAULT_ROLE_CAPABILITIES[role.value] || []);
    const roleOverride = overrides[role.value];

    if (roleOverride?.grant) {
      for (const cap of roleOverride.grant) defaults.add(cap);
    }
    if (roleOverride?.revoke) {
      for (const cap of roleOverride.revoke) defaults.delete(cap);
    }

    state[role.value] = {};
    for (const area of CAPABILITY_AREAS) {
      for (const cap of area.capabilities) {
        state[role.value][cap.key] = defaults.has(cap.key);
      }
    }
  }
  return state;
}

function buildOverridesFromState(checkedState: Record<string, Record<string, boolean>>): PermissionOverrides {
  const overrides: PermissionOverrides = {};
  for (const role of DISPLAY_ROLES) {
    const defaults = new Set(DEFAULT_ROLE_CAPABILITIES[role.value] || []);
    const grant: string[] = [];
    const revoke: string[] = [];

    for (const [cap, checked] of Object.entries(checkedState[role.value] || {})) {
      const isDefault = defaults.has(cap);
      if (checked && !isDefault) grant.push(cap);
      if (!checked && isDefault) revoke.push(cap);
    }

    if (grant.length > 0 || revoke.length > 0) {
      overrides[role.value] = {};
      if (grant.length > 0) overrides[role.value].grant = grant;
      if (revoke.length > 0) overrides[role.value].revoke = revoke;
    }
  }
  return overrides;
}

export function PermissionSettingsPage() {
  const { currentOrg, setOrgSettings } = useAuthStore();
  const [saving, setSaving] = useState(false);
  const [loaded, setLoaded] = useState(false);

  const existingOverrides: PermissionOverrides = useMemo(
    () => currentOrg?.settings?.permissionOverrides || {},
    [currentOrg?.settings?.permissionOverrides],
  );

  const [checkedState, setCheckedState] = useState<Record<string, Record<string, boolean>>>(() =>
    buildCheckedState(existingOverrides),
  );

  useEffect(() => {
    setCheckedState(buildCheckedState(existingOverrides));
    setLoaded(true);
  }, [existingOverrides]);

  const currentOverrides = useMemo(() => buildOverridesFromState(checkedState), [checkedState]);
  const hasChanges = JSON.stringify(currentOverrides) !== JSON.stringify(existingOverrides);

  const toggleCapability = (role: string, cap: string) => {
    setCheckedState((prev) => ({
      ...prev,
      [role]: {
        ...prev[role],
        [cap]: !prev[role]?.[cap],
      },
    }));
  };

  const resetRole = (roleValue: string) => {
    const defaults = new Set(DEFAULT_ROLE_CAPABILITIES[roleValue] || []);
    const newRoleState: Record<string, boolean> = {};
    for (const area of CAPABILITY_AREAS) {
      for (const cap of area.capabilities) {
        newRoleState[cap.key] = defaults.has(cap.key);
      }
    }
    setCheckedState((prev) => ({ ...prev, [roleValue]: newRoleState }));
  };

  const handleSave = async () => {
    setSaving(true);
    try {
      const overrides = buildOverridesFromState(checkedState);
      const res = await api.patch('/organizations/settings', { permissionOverrides: overrides });
      setOrgSettings(res.data);
      notifications.show({ title: 'Saved', message: 'Permission settings updated. Members will see changes on next login or page refresh.', color: 'green' });
    } catch (err: any) {
      notifications.show({ title: 'Error', message: err.response?.data?.message || 'Failed to save', color: 'red' });
    } finally {
      setSaving(false);
    }
  };

  const isOverridden = (role: string, cap: string) => {
    const isDefault = (DEFAULT_ROLE_CAPABILITIES[role] || []).includes(cap);
    const isChecked = checkedState[role]?.[cap] ?? false;
    return isChecked !== isDefault;
  };

  if (!loaded) {
    return <Center mt="xl"><Loader /></Center>;
  }

  return (
    <Stack gap="md">
      <Group justify="space-between" align="center">
        <Group gap="xs">
          <IconShieldCheck size={28} />
          <Title order={2}>Role Permissions</Title>
        </Group>
        <Group>
          <Button
            variant="default"
            leftSection={<IconRefresh size={16} />}
            onClick={() => setCheckedState(buildCheckedState(existingOverrides))}
            disabled={!hasChanges}
          >
            Discard Changes
          </Button>
          <Button
            onClick={handleSave}
            loading={saving}
            disabled={!hasChanges}
          >
            Save Changes
          </Button>
        </Group>
      </Group>

      <Alert icon={<IconInfoCircle size={16} />} color="blue" variant="light">
        Customize which capabilities each role has in your organization.
        Highlighted cells differ from the system defaults. Use "Reset" to revert a role to defaults.
        The <strong>Viewer</strong> role is always read-only regardless of settings.
      </Alert>

      <Card withBorder p={0} style={{ overflow: 'auto' }}>
        <Table striped highlightOnHover withColumnBorders style={{ minWidth: 900 }}>
          <Table.Thead>
            <Table.Tr>
              <Table.Th style={{ position: 'sticky', left: 0, background: 'var(--mantine-color-body)', zIndex: 1, minWidth: 200 }}>
                Capability
              </Table.Th>
              {DISPLAY_ROLES.map((role) => (
                <Table.Th key={role.value} style={{ textAlign: 'center', minWidth: 110 }}>
                  <Stack gap={4} align="center">
                    <Text size="xs" fw={600}>{role.label}</Text>
                    <Tooltip label={`Reset ${role.label} to defaults`}>
                      <Button
                        variant="subtle"
                        size="compact-xs"
                        onClick={() => resetRole(role.value)}
                      >
                        Reset
                      </Button>
                    </Tooltip>
                  </Stack>
                </Table.Th>
              ))}
            </Table.Tr>
          </Table.Thead>
          <Table.Tbody>
            {CAPABILITY_AREAS.map((area) => (
              <>
                <Table.Tr key={`area-${area.label}`}>
                  <Table.Td
                    colSpan={DISPLAY_ROLES.length + 1}
                    style={{ background: 'var(--mantine-color-gray-1)', fontWeight: 700 }}
                  >
                    <Text size="sm" fw={700} tt="uppercase">{area.label}</Text>
                  </Table.Td>
                </Table.Tr>
                {area.capabilities.map((cap) => (
                  <Table.Tr key={cap.key}>
                    <Table.Td style={{ position: 'sticky', left: 0, background: 'var(--mantine-color-body)', zIndex: 1 }}>
                      <Text size="sm">{cap.label}</Text>
                    </Table.Td>
                    {DISPLAY_ROLES.map((role) => {
                      const checked = checkedState[role.value]?.[cap.key] ?? false;
                      const overridden = isOverridden(role.value, cap.key);
                      return (
                        <Table.Td
                          key={role.value}
                          style={{
                            textAlign: 'center',
                            background: overridden ? 'var(--mantine-color-yellow-0)' : undefined,
                          }}
                        >
                          <Checkbox
                            checked={checked}
                            onChange={() => toggleCapability(role.value, cap.key)}
                            styles={{ input: { cursor: 'pointer' } }}
                          />
                        </Table.Td>
                      );
                    })}
                  </Table.Tr>
                ))}
              </>
            ))}
          </Table.Tbody>
        </Table>
      </Card>

      {hasChanges && (
        <Alert color="yellow" variant="light">
          You have unsaved changes. Click "Save Changes" to apply.
        </Alert>
      )}
    </Stack>
  );
}
