/**
 * Moderation State Machine
 * Manages moderation workflow with type-safe state transitions and lock coordination
 */

import type { SubmissionItemWithDeps } from './submissionItemsService';
import { logger } from './logger';

// State definitions using discriminated unions
export type ModerationState =
  | { status: 'idle' }
  | { status: 'claiming'; itemId: string }
  | { status: 'locked'; itemId: string; lockExpires: string }
  | { status: 'loading_data'; itemId: string; lockExpires: string }
  | { status: 'reviewing'; itemId: string; lockExpires: string; reviewData: SubmissionItemWithDeps[] }
  | { status: 'approving'; itemId: string }
  | { status: 'rejecting'; itemId: string }
  | { status: 'complete'; itemId: string; result: 'approved' | 'rejected' }
  | { status: 'error'; itemId: string; error: string }
  | { status: 'lock_expired'; itemId: string };

// Action definitions using discriminated unions
export type ModerationAction =
  | { type: 'CLAIM_ITEM'; payload: { itemId: string } }
  | { type: 'LOCK_ACQUIRED'; payload: { lockExpires: string } }
  | { type: 'LOCK_EXPIRED' }
  | { type: 'LOAD_DATA' }
  | { type: 'DATA_LOADED'; payload: { reviewData: SubmissionItemWithDeps[] } }
  | { type: 'START_APPROVAL' }
  | { type: 'START_REJECTION' }
  | { type: 'COMPLETE'; payload: { result: 'approved' | 'rejected' } }
  | { type: 'ERROR'; payload: { error: string } }
  | { type: 'RELEASE_LOCK' }
  | { type: 'RESET' };

/**
 * Moderation reducer with strict transition validation
 */
export function moderationReducer(
  state: ModerationState,
  action: ModerationAction
): ModerationState {
  switch (action.type) {
    case 'CLAIM_ITEM':
      if (state.status !== 'idle' && state.status !== 'complete' && state.status !== 'error') {
        throw new Error(`Cannot claim item from state: ${state.status}`);
      }
      return { status: 'claiming', itemId: action.payload.itemId };

    case 'LOCK_ACQUIRED':
      if (state.status !== 'claiming') {
        throw new Error(`Illegal transition: ${state.status} → locked`);
      }
      // Validate lock expiry date
      const lockDate = new Date(action.payload.lockExpires);
      if (isNaN(lockDate.getTime())) {
        throw new Error('Invalid lock expiry date');
      }
      return {
        status: 'locked',
        itemId: state.itemId,
        lockExpires: action.payload.lockExpires
      };

    case 'LOCK_EXPIRED':
      if (state.status !== 'locked' && state.status !== 'reviewing' && state.status !== 'loading_data') {
        logger.warn(`Lock expired notification in unexpected state: ${state.status}`);
        return state;
      }
      return {
        status: 'lock_expired',
        itemId: state.itemId
      };

    case 'LOAD_DATA':
      if (state.status !== 'locked') {
        throw new Error(`Illegal transition: ${state.status} → loading_data`);
      }
      return {
        status: 'loading_data',
        itemId: state.itemId,
        lockExpires: state.lockExpires
      };

    case 'DATA_LOADED':
      if (state.status !== 'loading_data') {
        throw new Error(`Illegal transition: ${state.status} → reviewing`);
      }
      return {
        status: 'reviewing',
        itemId: state.itemId,
        lockExpires: state.lockExpires,
        reviewData: action.payload.reviewData
      };

    case 'START_APPROVAL':
      if (state.status !== 'reviewing') {
        throw new Error(`Illegal transition: ${state.status} → approving`);
      }
      return {
        status: 'approving',
        itemId: state.itemId
      };

    case 'START_REJECTION':
      if (state.status !== 'reviewing') {
        throw new Error(`Illegal transition: ${state.status} → rejecting`);
      }
      return {
        status: 'rejecting',
        itemId: state.itemId
      };

    case 'COMPLETE':
      if (state.status !== 'approving' && state.status !== 'rejecting') {
        throw new Error(`Illegal transition: ${state.status} → complete`);
      }
      return {
        status: 'complete',
        itemId: state.itemId,
        result: action.payload.result
      };

    case 'ERROR':
      // Error can happen from most states
      if (state.status === 'idle' || state.status === 'complete') {
        logger.warn('Error action in terminal state');
        return state;
      }
      return {
        status: 'error',
        itemId: state.itemId,
        error: action.payload.error
      };

    case 'RELEASE_LOCK':
      // Can release lock from locked, reviewing, or error states
      if (state.status !== 'locked' && state.status !== 'reviewing' && state.status !== 'error' && state.status !== 'lock_expired' && state.status !== 'loading_data') {
        logger.warn(`Cannot release lock from state: ${state.status}`);
        return state;
      }
      return { status: 'idle' };

    case 'RESET':
      return { status: 'idle' };

    default:
      // Exhaustive check
      const _exhaustive: never = action;
      return state;
  }
}

// State transition guards
export function canClaimItem(state: ModerationState): boolean {
  return state.status === 'idle' || state.status === 'complete' || state.status === 'error';
}

export function canLoadData(state: ModerationState): boolean {
  return state.status === 'locked';
}

export function canStartReview(state: ModerationState): boolean {
  return state.status === 'loading_data';
}

export function canApprove(state: ModerationState): boolean {
  return state.status === 'reviewing';
}

export function canReject(state: ModerationState): boolean {
  return state.status === 'reviewing';
}

export function canReleaseLock(state: ModerationState): boolean {
  return state.status === 'locked' 
    || state.status === 'reviewing' 
    || state.status === 'error' 
    || state.status === 'lock_expired'
    || state.status === 'loading_data';
}

export function hasActiveLock(state: ModerationState): boolean {
  if (state.status !== 'locked' && state.status !== 'reviewing' && state.status !== 'loading_data') {
    return false;
  }
  
  const lockExpires = new Date(state.lockExpires);
  return lockExpires > new Date();
}

export function isTerminalState(state: ModerationState): boolean {
  return state.status === 'complete' || state.status === 'error';
}

export function needsLockRenewal(state: ModerationState): boolean {
  if (state.status !== 'locked' && state.status !== 'reviewing' && state.status !== 'loading_data') {
    return false;
  }
  
  const lockExpires = new Date(state.lockExpires);
  const now = new Date();
  const timeUntilExpiry = lockExpires.getTime() - now.getTime();
  
  // Renew if less than 2 minutes remaining
  return timeUntilExpiry < 120000;
}
