/* eslint-disable no-redeclare */
/**
 * Survey types — in-app surveys with conditional logic
 * @module surveys/types
 */

import { z } from 'zod';

// Re-export from broadcasts for targeting
import type { BroadcastTarget } from '../broadcasts/types.js';
export type { BroadcastTarget };

// =============================================================================
// Enums & Constants
// =============================================================================

export const SurveyStatus = {
  DRAFT: 'draft',
  ACTIVE: 'active',
  PAUSED: 'paused',
  CLOSED: 'closed',
} as const;

export type SurveyStatus = (typeof SurveyStatus)[keyof typeof SurveyStatus];

export const QuestionType = {
  SINGLE_CHOICE: 'single_choice',
  MULTIPLE_CHOICE: 'multiple_choice',
  RATING: 'rating',
  NPS: 'nps',
  TEXT_SHORT: 'text_short',
  TEXT_LONG: 'text_long',
  DROPDOWN: 'dropdown',
  SCALE: 'scale',
  RANKING: 'ranking',
} as const;

export type QuestionType = (typeof QuestionType)[keyof typeof QuestionType];

// =============================================================================
// Conditional Logic
// =============================================================================

export type ShowIfCondition =
  | { and: ShowIfCondition[] }
  | { or: ShowIfCondition[] }
  | {
      questionId: string;
      operator: 'equals' | 'not_equals' | 'contains' | 'greater_than' | 'less_than' | 'in';
      value: string | string[] | number;
    };

// =============================================================================
// Question Types
// =============================================================================

export interface QuestionOption {
  id: string;
  text: string;
  emoji?: string;
}

export interface Question {
  id: string;
  type: QuestionType;
  text: string;
  description?: string;
  required: boolean;

  // For choice types
  options?: QuestionOption[];

  // Conditional logic
  showIf?: ShowIfCondition;

  // Validation
  minLength?: number;
  maxLength?: number;
  minValue?: number;
  maxValue?: number;
}

// =============================================================================
// Survey Definition
// =============================================================================

export type SurveyTrigger =
  | { type: 'immediate' }
  | { type: 'delay_seconds'; seconds: number }
  | { type: 'event'; eventName: string }
  | { type: 'page_view'; pagePattern: string };

export interface Survey {
  id: string;
  productId: string;
  title: string;
  description?: string;

  // Questions
  questions: Question[];

  // Targeting (same as BroadcastTarget)
  target: BroadcastTarget;

  // Scheduling
  status: SurveyStatus;
  startsAt?: string;
  endsAt?: string;

  // Display settings
  displayTrigger: SurveyTrigger;

  // Incentives
  incentive?: {
    type: 'pro_days' | 'credits';
    amount: number;
  };

  // Metrics (stored, computed on read)
  metrics: SurveyMetrics;

  createdAt: string;
  updatedAt: string;
  createdBy: string;
}

export interface SurveyMetrics {
  impressions: number;
  starts: number;
  completions: number;
  avgTimeSeconds: number;
  incentiveClaims: number;
}

// =============================================================================
// Survey Response
// =============================================================================

export type QuestionAnswer =
  | { type: 'single_choice'; optionId: string }
  | { type: 'multiple_choice'; optionIds: string[] }
  | { type: 'rating'; value: number }
  | { type: 'nps'; value: number }
  | { type: 'text'; value: string }
  | { type: 'ranking'; rankedOptionIds: string[] };

export interface SurveyResponse {
  id: string;
  surveyId: string;
  productId: string;
  userId: string;
  deviceId?: string;

  // Answers keyed by question ID
  answers: Record<string, QuestionAnswer>;

  // Progress tracking
  currentQuestionIndex: number;

  // Metadata
  startedAt: string;
  completedAt?: string;
  isComplete: boolean;

  // Incentive
  incentiveClaimed: boolean;
  incentiveClaimedAt?: string;

  createdAt: string;
  updatedAt: string;
}

// =============================================================================
// User Survey State (per-user tracking)
// =============================================================================

export interface UserSurveyState {
  id: string; // composite: `${surveyId}:${userId}`
  surveyId: string;
  userId: string;
  productId: string;

  // Display state
  status: 'eligible' | 'shown' | 'started' | 'completed' | 'dismissed';

  // Timestamps
  firstShownAt?: string;
  startedAt?: string;
  completedAt?: string;
  dismissedAt?: string;

  // For throttling (don't show too often)
  showCount: number;
  lastShownAt?: string;

  createdAt: string;
  updatedAt: string;
}

// =============================================================================
// Zod Schemas
// =============================================================================

const ShowIfConditionSchema: z.ZodType<ShowIfCondition> = z.lazy(() =>
  z.union([
    z.object({ and: z.array(ShowIfConditionSchema) }),
    z.object({ or: z.array(ShowIfConditionSchema) }),
    z.object({
      questionId: z.string(),
      operator: z.enum(['equals', 'not_equals', 'contains', 'greater_than', 'less_than', 'in']),
      value: z.union([z.string(), z.array(z.string()), z.number()]),
    }),
  ])
);

export const QuestionSchema = z.object({
  id: z.string().min(1),
  type: z.nativeEnum(QuestionType),
  text: z.string().min(1).max(500),
  description: z.string().max(1000).optional(),
  required: z.boolean(),
  options: z
    .array(
      z.object({
        id: z.string(),
        text: z.string(),
        emoji: z.string().optional(),
      })
    )
    .optional(),
  showIf: ShowIfConditionSchema.optional(),
  minLength: z.number().min(0).optional(),
  maxLength: z.number().min(1).optional(),
  minValue: z.number().optional(),
  maxValue: z.number().optional(),
});

export const SurveyTriggerSchema = z.union([
  z.object({ type: z.literal('immediate') }),
  z.object({ type: z.literal('delay_seconds'), seconds: z.number().min(1).max(3600) }),
  z.object({ type: z.literal('event'), eventName: z.string() }),
  z.object({ type: z.literal('page_view'), pagePattern: z.string() }),
]);

export const CreateSurveySchema = z.object({
  title: z.string().min(1).max(200),
  description: z.string().max(2000).optional(),
  questions: z.array(QuestionSchema).min(1).max(50),
  startsAt: z.string().datetime().optional(),
  endsAt: z.string().datetime().optional(),
  displayTrigger: SurveyTriggerSchema,
  incentive: z
    .object({
      type: z.enum(['pro_days', 'credits']),
      amount: z.number().min(1),
    })
    .optional(),
});

export const UpdateSurveySchema = z.object({
  title: z.string().min(1).max(200).optional(),
  description: z.string().max(2000).optional(),
  status: z.nativeEnum(SurveyStatus).optional(),
  startsAt: z.string().datetime().optional(),
  endsAt: z.string().datetime().optional(),
  displayTrigger: SurveyTriggerSchema.optional(),
});

export const SubmitAnswerSchema = z.object({
  questionId: z.string(),
  answer: z.union([
    z.object({ type: z.literal('single_choice'), optionId: z.string() }),
    z.object({ type: z.literal('multiple_choice'), optionIds: z.array(z.string()) }),
    z.object({ type: z.literal('rating'), value: z.number().min(1).max(10) }),
    z.object({ type: z.literal('nps'), value: z.number().min(0).max(10) }),
    z.object({ type: z.literal('text'), value: z.string() }),
    z.object({ type: z.literal('ranking'), rankedOptionIds: z.array(z.string()) }),
  ]),
});

// =============================================================================
// Helper Functions
// =============================================================================

export function computeCompletionRate(metrics: SurveyMetrics): number {
  return metrics.starts > 0 ? metrics.completions / metrics.starts : 0;
}

export function validateAnswerType(
  question: Question,
  answer: QuestionAnswer
): { valid: boolean; error?: string } {
  if (question.type === 'single_choice' && answer.type !== 'single_choice') {
    return { valid: false, error: `Expected single_choice, got ${answer.type}` };
  }
  if (question.type === 'multiple_choice' && answer.type !== 'multiple_choice') {
    return { valid: false, error: `Expected multiple_choice, got ${answer.type}` };
  }
  if (question.type === 'rating' && answer.type !== 'rating') {
    return { valid: false, error: `Expected rating, got ${answer.type}` };
  }
  if (question.type === 'nps' && answer.type !== 'nps') {
    return { valid: false, error: `Expected nps, got ${answer.type}` };
  }
  if ((question.type === 'text_short' || question.type === 'text_long') && answer.type !== 'text') {
    return { valid: false, error: `Expected text, got ${answer.type}` };
  }
  if (question.type === 'dropdown' && answer.type !== 'single_choice') {
    return { valid: false, error: `Expected single_choice for dropdown, got ${answer.type}` };
  }
  if (question.type === 'scale' && answer.type !== 'rating') {
    return { valid: false, error: `Expected rating for scale, got ${answer.type}` };
  }
  if (question.type === 'ranking' && answer.type !== 'ranking') {
    return { valid: false, error: `Expected ranking, got ${answer.type}` };
  }

  // Validate value ranges
  if (answer.type === 'rating') {
    if (question.minValue !== undefined && answer.value < question.minValue) {
      return { valid: false, error: `Rating below minimum ${question.minValue}` };
    }
    if (question.maxValue !== undefined && answer.value > question.maxValue) {
      return { valid: false, error: `Rating above maximum ${question.maxValue}` };
    }
  }

  if (answer.type === 'text') {
    if (question.minLength !== undefined && answer.value.length < question.minLength) {
      return { valid: false, error: `Text too short (min ${question.minLength})` };
    }
    if (question.maxLength !== undefined && answer.value.length > question.maxLength) {
      return { valid: false, error: `Text too long (max ${question.maxLength})` };
    }
  }

  return { valid: true };
}
