import * as plugins from '../plugins.js';
import * as interfaces from '../../ts_interfaces/index.js';
import { appState } from './shared.js';
import { getActionContext } from './login.js';
import { runBackgroundRefresh } from './shared.js';

export interface ISecurityPolicyState {
  rules: interfaces.data.ISecurityBlockRule[];
  ipIntelligence: interfaces.data.IIpIntelligenceRecord[];
  compiledPolicy: interfaces.data.ISecurityCompiledPolicy | null;
  auditEvents: interfaces.data.ISecurityPolicyAuditEvent[];
  isLoading: boolean;
  error: string | null;
  lastUpdated: number;
}

export const securityPolicyStatePart = await appState.getStatePart<ISecurityPolicyState>(
  'securityPolicy',
  {
    rules: [],
    ipIntelligence: [],
    compiledPolicy: null,
    auditEvents: [],
    isLoading: false,
    error: null,
    lastUpdated: 0,
  },
  'soft',
);

function refreshSecurityIpIntelligence(identity: interfaces.data.IIdentity): void {
  runBackgroundRefresh('securityIpIntelligence', 'Security IP intelligence refresh failed:', async () => {
    const intelligenceRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
      interfaces.requests.IReq_ListIpIntelligence
    >('/typedrequest', 'listIpIntelligence');
    const intelligenceResponse = await intelligenceRequest.fire({
      identity,
      limit: 500,
    });
    securityPolicyStatePart.setState({
      ...securityPolicyStatePart.getState()!,
      ipIntelligence: intelligenceResponse.records || [],
    });
  });
}


// Security Policy Actions
// ============================================================================

export const fetchSecurityPolicyAction = securityPolicyStatePart.createAction(
  async (statePartArg): Promise<ISecurityPolicyState> => {
    const context = getActionContext();
    const currentState = statePartArg.getState()!;
    if (!context.identity) return currentState;

    try {
      const rulesRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
        interfaces.requests.IReq_ListSecurityBlockRules
      >('/typedrequest', 'listSecurityBlockRules');
      const compiledPolicyRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
        interfaces.requests.IReq_GetCompiledSecurityPolicy
      >('/typedrequest', 'getCompiledSecurityPolicy');
      const auditRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
        interfaces.requests.IReq_ListSecurityPolicyAudit
      >('/typedrequest', 'listSecurityPolicyAudit');

      const [rulesResponse, compiledPolicyResponse, auditResponse] = await Promise.all([
        rulesRequest.fire({ identity: context.identity }),
        compiledPolicyRequest.fire({ identity: context.identity }),
        auditRequest.fire({ identity: context.identity, limit: 100 }),
      ]);

      refreshSecurityIpIntelligence(context.identity);

      return {
        rules: rulesResponse.rules || [],
        ipIntelligence: currentState.ipIntelligence,
        compiledPolicy: compiledPolicyResponse.policy,
        auditEvents: auditResponse.events || [],
        isLoading: false,
        error: null,
        lastUpdated: Date.now(),
      };
    } catch (error: unknown) {
      return {
        ...currentState,
        isLoading: false,
        error: error instanceof Error ? error.message : 'Failed to fetch security policy',
      };
    }
  },
);

export const createSecurityBlockRuleAction = securityPolicyStatePart.createAction<{
  type: interfaces.data.TSecurityBlockRuleType;
  value: string;
  matchMode?: interfaces.data.TSecurityBlockRuleMatchMode;
  reason?: string;
  enabled?: boolean;
}>(async (statePartArg, dataArg, actionContext): Promise<ISecurityPolicyState> => {
  const context = getActionContext();
  const currentState = statePartArg.getState()!;
  if (!context.identity) return currentState;

  try {
    const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
      interfaces.requests.IReq_CreateSecurityBlockRule
    >('/typedrequest', 'createSecurityBlockRule');

    const response = await request.fire({
      identity: context.identity,
      type: dataArg.type,
      value: dataArg.value,
      matchMode: dataArg.matchMode,
      reason: dataArg.reason,
      enabled: dataArg.enabled,
    });

    if (!response.success) {
      return { ...currentState, error: response.message || 'Failed to create security block rule' };
    }

    return await actionContext!.dispatch(fetchSecurityPolicyAction, null);
  } catch (error: unknown) {
    return {
      ...currentState,
      error: error instanceof Error ? error.message : 'Failed to create security block rule',
    };
  }
});

export const updateSecurityBlockRuleAction = securityPolicyStatePart.createAction<{
  id: string;
  value?: string;
  matchMode?: interfaces.data.TSecurityBlockRuleMatchMode;
  reason?: string;
  enabled?: boolean;
}>(async (statePartArg, dataArg, actionContext): Promise<ISecurityPolicyState> => {
  const context = getActionContext();
  const currentState = statePartArg.getState()!;
  if (!context.identity) return currentState;

  try {
    const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
      interfaces.requests.IReq_UpdateSecurityBlockRule
    >('/typedrequest', 'updateSecurityBlockRule');

    const response = await request.fire({
      identity: context.identity,
      id: dataArg.id,
      value: dataArg.value,
      matchMode: dataArg.matchMode,
      reason: dataArg.reason,
      enabled: dataArg.enabled,
    });

    if (!response.success) {
      return { ...currentState, error: response.message || 'Failed to update security block rule' };
    }

    return await actionContext!.dispatch(fetchSecurityPolicyAction, null);
  } catch (error: unknown) {
    return {
      ...currentState,
      error: error instanceof Error ? error.message : 'Failed to update security block rule',
    };
  }
});

export const deleteSecurityBlockRuleAction = securityPolicyStatePart.createAction<string>(
  async (statePartArg, ruleId, actionContext): Promise<ISecurityPolicyState> => {
    const context = getActionContext();
    const currentState = statePartArg.getState()!;
    if (!context.identity) return currentState;

    try {
      const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
        interfaces.requests.IReq_DeleteSecurityBlockRule
      >('/typedrequest', 'deleteSecurityBlockRule');

      const response = await request.fire({ identity: context.identity, id: ruleId });
      if (!response.success) {
        return { ...currentState, error: response.message || 'Failed to delete security block rule' };
      }

      return await actionContext!.dispatch(fetchSecurityPolicyAction, null);
    } catch (error: unknown) {
      return {
        ...currentState,
        error: error instanceof Error ? error.message : 'Failed to delete security block rule',
      };
    }
  },
);

export const refreshIpIntelligenceAction = securityPolicyStatePart.createAction<string>(
  async (statePartArg, ipAddress, actionContext): Promise<ISecurityPolicyState> => {
    const context = getActionContext();
    const currentState = statePartArg.getState()!;
    if (!context.identity) return currentState;

    try {
      const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
        interfaces.requests.IReq_RefreshIpIntelligence
      >('/typedrequest', 'refreshIpIntelligence');
      const response = await request.fire({ identity: context.identity, ipAddress });
      if (!response.success) {
        return { ...currentState, error: response.message || 'Failed to refresh IP intelligence' };
      }
      const refreshedState = await actionContext!.dispatch(fetchSecurityPolicyAction, null);
      if (!response.record) return refreshedState;
      return {
        ...refreshedState,
        ipIntelligence: [
          response.record,
          ...refreshedState.ipIntelligence.filter((record) => record.ipAddress !== response.record!.ipAddress),
        ],
      };
    } catch (error: unknown) {
      return {
        ...currentState,
        error: error instanceof Error ? error.message : 'Failed to refresh IP intelligence',
      };
    }
  },
);

// ============================================================================
