/**
 * Violation pure decider.
 *
 * PURITY CONTRACT (enforced by _purity-check.sh violation).
 *
 * Transition table:
 *
 *   * (not BANNED) + warn_requested      → unchanged
 *     effects: [insert-admin-action(FREEZE, note=[WARNING]…), send-policy-email(WARNING)]
 *
 *   ACTIVE|VETERAN + freeze_requested    → FROZEN
 *     effects: [set-account-state(FROZEN), insert-admin-action(FREEZE), send-policy-email(FREEZE)]
 *
 *   FROZEN + unfreeze_requested          → ACTIVE
 *     effects: [set-account-state(ACTIVE), insert-admin-action(UNFREEZE)]
 *
 *   ACTIVE|VETERAN|FROZEN + ban_requested → BANNED
 *     effects: [pause-vendor-deals, set-account-state(BANNED),
 *               insert-admin-action(BAN), send-policy-email(BAN)]
 *
 *   BANNED + warn|freeze|ban|unfreeze    → rejected INVALID_STATE
 *   non-FROZEN + unfreeze_requested      → rejected NOT_FROZEN
 */

import type { ViolationEvent, VendorAccountState } from './events.js';
import type { ViolationEffect } from './effects.js';

export type ViolationState = VendorAccountState;

export interface ViolationContext {
  state: ViolationState;
  /** Vendor businessName surfaced only for the email body (decider is pure
   *  — strings get woven into effect payloads). */
  businessName: string;
}

export type DecideResult =
  | { ok: true; nextState: ViolationState; effects: ViolationEffect[] }
  | {
      ok: false;
      error: 'INVALID_STATE' | 'NOT_FROZEN' | 'ALREADY_BANNED';
      from: ViolationState;
      message: string;
    };

const ACTIVELIKE = new Set<ViolationState>(['ACTIVE', 'VETERAN']);

export function decide(ctx: ViolationContext, event: ViolationEvent): DecideResult {
  // Blanket reject when already BANNED (except no-op idempotent reads — none here)
  if (ctx.state === 'BANNED') {
    switch (event.kind) {
      case 'warn_requested':
        return {
          ok: false,
          error: 'INVALID_STATE',
          from: ctx.state,
          message: 'Vendor is already permanently banned',
        };
      case 'freeze_requested':
        return {
          ok: false,
          error: 'INVALID_STATE',
          from: ctx.state,
          message: 'Vendor is permanently banned and cannot be frozen',
        };
      case 'unfreeze_requested':
        return {
          ok: false,
          error: 'NOT_FROZEN',
          from: ctx.state,
          message: `Vendor is not frozen (current state: ${ctx.state})`,
        };
      case 'ban_requested':
        return {
          ok: false,
          error: 'ALREADY_BANNED',
          from: ctx.state,
          message: 'Vendor is already banned',
        };
    }
  }

  switch (event.kind) {
    case 'warn_requested': {
      const effects: ViolationEffect[] = [
        {
          kind: 'insert-admin-action',
          adminId: event.adminId,
          vendorId: event.vendorId,
          action: 'FREEZE',
          note: `[WARNING] ${event.note}`,
        },
        {
          kind: 'send-policy-email',
          vendorId: event.vendorId,
          action: 'WARNING',
          reason: event.note,
          nextSteps: 'אנא ציית להנחיות המדיניות שלנו כדי למנוע השעיה של חשבונך.',
        },
      ];
      return { ok: true, nextState: ctx.state, effects };
    }

    case 'freeze_requested': {
      if (!ACTIVELIKE.has(ctx.state)) {
        return {
          ok: false,
          error: 'INVALID_STATE',
          from: ctx.state,
          message: `Cannot freeze a vendor in state ${ctx.state}`,
        };
      }
      const unfreezeAt =
        event.durationDays !== null
          ? new Date(event.at.getTime() + event.durationDays * 24 * 60 * 60 * 1000)
          : null;
      const noteText =
        event.durationDays !== null
          ? `Frozen for ${event.durationDays} days (unfreeze at: ${unfreezeAt!.toISOString()}). Reason: ${event.reason}`
          : `Frozen indefinitely. Reason: ${event.reason}`;
      const nextSteps =
        event.durationDays !== null
          ? `חשבונך הושעה ל-${event.durationDays} ימים. צור קשר עם הצוות שלנו לפרטים.`
          : 'חשבונך הושעה. צור קשר עם הצוות שלנו לפרטים.';

      const effects: ViolationEffect[] = [
        { kind: 'set-account-state', vendorId: event.vendorId, nextState: 'FROZEN' },
        {
          kind: 'insert-admin-action',
          adminId: event.adminId,
          vendorId: event.vendorId,
          action: 'FREEZE',
          note: noteText,
        },
        {
          kind: 'send-policy-email',
          vendorId: event.vendorId,
          action: 'FREEZE',
          reason: event.reason,
          nextSteps,
        },
      ];
      return { ok: true, nextState: 'FROZEN', effects };
    }

    case 'unfreeze_requested': {
      if (ctx.state !== 'FROZEN') {
        return {
          ok: false,
          error: 'NOT_FROZEN',
          from: ctx.state,
          message: `Vendor is not frozen (current state: ${ctx.state})`,
        };
      }
      const effects: ViolationEffect[] = [
        { kind: 'set-account-state', vendorId: event.vendorId, nextState: 'ACTIVE' },
        {
          kind: 'insert-admin-action',
          adminId: event.adminId,
          vendorId: event.vendorId,
          action: 'UNFREEZE',
          note: 'Account unfrozen by admin',
        },
      ];
      return { ok: true, nextState: 'ACTIVE', effects };
    }

    case 'ban_requested': {
      const effects: ViolationEffect[] = [
        { kind: 'pause-vendor-deals', vendorId: event.vendorId },
        { kind: 'set-account-state', vendorId: event.vendorId, nextState: 'BANNED' },
        {
          kind: 'insert-admin-action',
          adminId: event.adminId,
          vendorId: event.vendorId,
          action: 'BAN',
          note: event.reason,
        },
        {
          kind: 'send-policy-email',
          vendorId: event.vendorId,
          action: 'BAN',
          reason: event.reason,
          nextSteps: 'חשבונך נחסם לצמיתות. אם אתה חושב שמדובר בטעות, פנה אלינו.',
        },
      ];
      return { ok: true, nextState: 'BANNED', effects };
    }

    default: {
      const _exhaustive: never = event;
      void _exhaustive;
      return {
        ok: false,
        error: 'INVALID_STATE',
        from: ctx.state,
        message: 'Unhandled event kind',
      };
    }
  }
}
