/**
 * Review decider — pure state machine (FDS §6.9).
 *
 * Validates each review-related event against pre-loaded context and emits
 * a deterministic effect list. NO IO, NO Date.now(), NO crypto.
 *
 *   STANDARD review:
 *     requires: purchase exists, reviewEligible=true, owned by user, no existing review
 *     emits: insert-review (STANDARD) + update-vendor-aggregate + send-vendor-push
 *
 *   TECHNICAL review:
 *     requires: purchase exists, redemptionStatus=EXPIRED, owned by user, no existing technical
 *     emits: insert-review (TECHNICAL)  (no aggregate, no push)
 *
 *   reply:
 *     requires: review exists, vendor owns it
 *     emits: update-review-reply
 *
 *   removal request:
 *     requires: review exists, vendor owns it, not already requested
 *     emits: mark-removal-requested + insert-removal-queue + enqueue-ai-prescore
 *
 * Pure module: no imports from @/server/db, do-client, outbox-producer, payments, fetch.
 */

import type {
  ReviewEvent,
  StandardReviewSubmittedEvent,
  TechnicalReviewSubmittedEvent,
  ReplyAddedEvent,
  RemovalRequestedEvent,
} from './events.js';
import type { ReviewEffect } from './effects.js';

export type ReviewErrorCode =
  | 'PURCHASE_NOT_FOUND'
  | 'NOT_REVIEW_ELIGIBLE'
  | 'ALREADY_REVIEWED'
  | 'REVIEW_NOT_FOUND'
  | 'VENDOR_NOT_OWNER'
  | 'ALREADY_REMOVAL_REQUESTED';

export interface PurchaseContext {
  id: string;
  userId: string;
  vendorId: string;
  dealId: string;
  reviewEligible: boolean;
  redemptionStatus: string;
}

export interface ReviewContext {
  id: string;
  vendorId: string;
  removalRequested: boolean;
}

export type ReviewDecisionContext =
  | {
      kind: 'submit-standard';
      purchase: PurchaseContext | null;
      existingReviewForPurchase: boolean;
    }
  | {
      kind: 'submit-technical';
      purchase: PurchaseContext | null;
      existingReviewForPurchase: boolean;
    }
  | { kind: 'reply'; review: ReviewContext | null }
  | { kind: 'removal'; review: ReviewContext | null; aiEnabled: boolean };

export type ReviewDecision =
  | { ok: true; effects: ReviewEffect[] }
  | { ok: false; error: ReviewErrorCode; message: string };

export function decide(ctx: ReviewDecisionContext, event: ReviewEvent): ReviewDecision {
  switch (event.kind) {
    case 'standard_review_submitted':
      if (ctx.kind !== 'submit-standard') {
        return { ok: false, error: 'PURCHASE_NOT_FOUND', message: 'Context kind mismatch' };
      }
      return decideStandard(ctx.purchase, ctx.existingReviewForPurchase, event);
    case 'technical_review_submitted':
      if (ctx.kind !== 'submit-technical') {
        return { ok: false, error: 'PURCHASE_NOT_FOUND', message: 'Context kind mismatch' };
      }
      return decideTechnical(ctx.purchase, ctx.existingReviewForPurchase, event);
    case 'reply_added':
      if (ctx.kind !== 'reply') {
        return { ok: false, error: 'REVIEW_NOT_FOUND', message: 'Context kind mismatch' };
      }
      return decideReply(ctx.review, event);
    case 'removal_requested':
      if (ctx.kind !== 'removal') {
        return { ok: false, error: 'REVIEW_NOT_FOUND', message: 'Context kind mismatch' };
      }
      return decideRemoval(ctx.review, ctx.aiEnabled, event);
  }
}

function decideStandard(
  purchase: PurchaseContext | null,
  existingReview: boolean,
  event: StandardReviewSubmittedEvent,
): ReviewDecision {
  if (!purchase) {
    return { ok: false, error: 'PURCHASE_NOT_FOUND', message: 'Purchase not found' };
  }
  if (purchase.userId !== event.userId) {
    return { ok: false, error: 'PURCHASE_NOT_FOUND', message: 'Purchase not found' };
  }
  if (!purchase.reviewEligible) {
    return {
      ok: false,
      error: 'NOT_REVIEW_ELIGIBLE',
      message: 'Purchase is not eligible for review',
    };
  }
  if (existingReview) {
    return { ok: false, error: 'ALREADY_REVIEWED', message: 'Purchase already has a review' };
  }
  return {
    ok: true,
    effects: [
      {
        kind: 'insert-review',
        purchaseId: event.purchaseId,
        userId: event.userId,
        vendorId: purchase.vendorId,
        dealId: purchase.dealId,
        reviewType: 'STANDARD',
        rating: event.rating,
        body: event.body,
      },
      { kind: 'update-vendor-aggregate', vendorId: purchase.vendorId, rating: event.rating },
      {
        kind: 'send-vendor-push',
        vendorId: purchase.vendorId,
        rating: event.rating,
        bodyPreview: event.body.slice(0, 80),
      },
    ],
  };
}

function decideTechnical(
  purchase: PurchaseContext | null,
  existingReview: boolean,
  event: TechnicalReviewSubmittedEvent,
): ReviewDecision {
  if (!purchase) {
    return { ok: false, error: 'PURCHASE_NOT_FOUND', message: 'Purchase not found' };
  }
  if (purchase.userId !== event.userId) {
    return { ok: false, error: 'PURCHASE_NOT_FOUND', message: 'Purchase not found' };
  }
  if (purchase.redemptionStatus !== 'EXPIRED') {
    return {
      ok: false,
      error: 'NOT_REVIEW_ELIGIBLE',
      message: 'Technical reviews are only available for expired purchases',
    };
  }
  if (existingReview) {
    return {
      ok: false,
      error: 'ALREADY_REVIEWED',
      message: 'Purchase already has a technical review',
    };
  }
  return {
    ok: true,
    effects: [
      {
        kind: 'insert-review',
        purchaseId: event.purchaseId,
        userId: event.userId,
        vendorId: purchase.vendorId,
        dealId: purchase.dealId,
        reviewType: 'TECHNICAL',
        body: event.body,
      },
    ],
  };
}

function decideReply(review: ReviewContext | null, event: ReplyAddedEvent): ReviewDecision {
  if (!review) {
    return { ok: false, error: 'REVIEW_NOT_FOUND', message: 'Review not found' };
  }
  if (review.vendorId !== event.vendorId) {
    return {
      ok: false,
      error: 'VENDOR_NOT_OWNER',
      message: 'Not authorized to reply to this review',
    };
  }
  return {
    ok: true,
    effects: [{ kind: 'update-review-reply', reviewId: event.reviewId, reply: event.reply }],
  };
}

function decideRemoval(
  review: ReviewContext | null,
  aiEnabled: boolean,
  event: RemovalRequestedEvent,
): ReviewDecision {
  if (!review) {
    return { ok: false, error: 'REVIEW_NOT_FOUND', message: 'Review not found' };
  }
  if (review.vendorId !== event.vendorId) {
    return {
      ok: false,
      error: 'VENDOR_NOT_OWNER',
      message: 'Not authorized to request removal of this review',
    };
  }
  if (review.removalRequested) {
    return {
      ok: false,
      error: 'ALREADY_REMOVAL_REQUESTED',
      message: 'Removal already requested for this review',
    };
  }
  const effects: ReviewEffect[] = [
    { kind: 'mark-removal-requested', reviewId: event.reviewId, reason: event.reason },
    {
      kind: 'insert-removal-queue',
      reviewId: event.reviewId,
      submittedBy: event.vendorId,
      reason: event.reason,
    },
  ];
  if (aiEnabled) {
    effects.push({ kind: 'enqueue-ai-prescore' });
  }
  return { ok: true, effects };
}
