/**
 * Opportunity Domain - Schemas
 *
 * Zod schemas for runtime validation of Opportunity data.
 * Includes cancellation form validation with deadline logic.
 */

import { z } from "zod";

// ============================================================================
// Enum Value Arrays (for Zod schemas)
// ============================================================================

/**
 * Opportunity stage values - match existing Salesforce picklist
 */
const OPPORTUNITY_STAGE_VALUES = [
  "Introduction",
  "WIKI",
  "Ready",
  "Post Processing",
  "Active",
  "△Cancelling",
  "〇Cancelled",
  "Completed",
  "Void",
  "Pending",
] as const;

/**
 * Application stage values
 */
const APPLICATION_STAGE_VALUES = ["INTRO-1", "N/A"] as const;

/**
 * Cancellation notice values
 */
const CANCELLATION_NOTICE_VALUES = ["有", "未", "不要", "移転"] as const;

/**
 * Line return status values
 */
const LINE_RETURN_STATUS_VALUES = [
  "NotYet",
  "SentKit",
  "AS/Pickup予定",
  "Returned1",
  "Returned2",
  "NTT派遣",
  "Compensated",
  "N/A",
] as const;

const OPPORTUNITY_PRODUCT_TYPE_VALUES = ["Internet", "SIM", "VPN"] as const;

/**
 * Commodity type values - existing Salesforce picklist
 */
const COMMODITY_TYPE_VALUES = [
  "Personal SonixNet Home Internet",
  "Corporate SonixNet Home Internet",
  "SIM",
  "VPN",
  "Onsite Support",
] as const;

const OPPORTUNITY_SOURCE_VALUES = [
  "Portal - Internet Eligibility Request",
  "Portal - SIM Checkout Registration",
  "Portal - Order Placement",
  "Agent Created",
] as const;

// ============================================================================
// Opportunity Record Schema
// ============================================================================

/**
 * Schema for Opportunity record returned from Salesforce
 */
export const opportunityRecordSchema = z.object({
  id: z.string(),
  name: z.string(),
  accountId: z.string(),
  stage: z.enum(OPPORTUNITY_STAGE_VALUES),
  closeDate: z.string(),
  commodityType: z.enum(COMMODITY_TYPE_VALUES).optional(),
  productType: z.enum(OPPORTUNITY_PRODUCT_TYPE_VALUES).optional(), // Derived from commodityType
  source: z.enum(OPPORTUNITY_SOURCE_VALUES).optional(),
  applicationStage: z.enum(APPLICATION_STAGE_VALUES).optional(),
  isClosed: z.boolean(),

  // Linked entities
  // Note: Cases and Orders link TO Opportunity via their OpportunityId field
  whmcsServiceId: z.number().int().optional(),

  // Cancellation fields (updated by CS when processing cancellation Case)
  cancellationNotice: z.enum(CANCELLATION_NOTICE_VALUES).optional(),
  scheduledCancellationDate: z.string().optional(),
  lineReturnStatus: z.enum(LINE_RETURN_STATUS_VALUES).optional(),
  // NOTE: alternativeContactEmail and cancellationComments are on the Cancellation Case

  // Metadata
  createdDate: z.string(),
  lastModifiedDate: z.string(),
});

export type OpportunityRecord = z.infer<typeof opportunityRecordSchema>;

// ============================================================================
// Create Opportunity Request Schema
// ============================================================================

/**
 * Schema for creating a new Opportunity
 *
 * Note: Opportunity Name is auto-generated by Salesforce workflow,
 * so we don't need to provide account name.
 */
export const createOpportunityRequestSchema = z.object({
  accountId: z.string().min(15, "Salesforce Account ID must be at least 15 characters"),
  productType: z.enum(OPPORTUNITY_PRODUCT_TYPE_VALUES),
  stage: z.enum(OPPORTUNITY_STAGE_VALUES),
  source: z.enum(OPPORTUNITY_SOURCE_VALUES),
  applicationStage: z.enum(APPLICATION_STAGE_VALUES).optional(),
  closeDate: z.string().optional(),
  // Note: Create Case separately with Case.OpportunityId = returned Opportunity ID
});

export type CreateOpportunityRequest = z.infer<typeof createOpportunityRequestSchema>;

// ============================================================================
// Update Stage Request Schema
// ============================================================================

/**
 * Schema for updating Opportunity stage
 */
export const updateOpportunityStageRequestSchema = z.object({
  opportunityId: z.string().min(15, "Salesforce Opportunity ID must be at least 15 characters"),
  stage: z.enum(OPPORTUNITY_STAGE_VALUES),
  reason: z.string().optional(),
});

export type UpdateOpportunityStageRequest = z.infer<typeof updateOpportunityStageRequestSchema>;

// ============================================================================
// Cancellation Form Schema
// ============================================================================

/**
 * Regex for YYYY-MM format
 */
const CANCELLATION_MONTH_REGEX = /^\d{4}-(0[1-9]|1[0-2])$/;

/**
 * Schema for cancellation form data from customer
 *
 * Validates:
 * - cancellationMonth is in YYYY-MM format
 * - Both confirmations are checked
 * - Email is valid if provided
 */
export const cancellationFormDataSchema = z
  .object({
    cancellationMonth: z
      .string()
      .regex(CANCELLATION_MONTH_REGEX, "Cancellation month must be in YYYY-MM format"),
    confirmTermsRead: z.boolean(),
    confirmMonthEndCancellation: z.boolean(),
    alternativeEmail: z.string().email().optional().or(z.literal("")),
    comments: z.string().max(2000, "Comments must be 2000 characters or less").optional(),
  })
  .refine(data => data.confirmTermsRead === true, {
    message: "You must confirm you have read the cancellation terms",
    path: ["confirmTermsRead"],
  })
  .refine(data => data.confirmMonthEndCancellation === true, {
    message: "You must confirm you understand cancellation is at month end",
    path: ["confirmMonthEndCancellation"],
  });

export type CancellationFormData = z.infer<typeof cancellationFormDataSchema>;

/**
 * Schema for cancellation data to populate on Opportunity
 */
export const cancellationOpportunityDataSchema = z.object({
  scheduledCancellationDate: z.string(),
  cancellationNotice: z.enum(CANCELLATION_NOTICE_VALUES),
  lineReturnStatus: z.enum(LINE_RETURN_STATUS_VALUES),
  alternativeEmail: z.string().email().optional(),
  comments: z.string().max(2000).optional(),
});

export type CancellationOpportunityData = z.infer<typeof cancellationOpportunityDataSchema>;

// ============================================================================
// Cancellation Eligibility Schema
// ============================================================================

/**
 * Schema for a cancellation month option
 */
export const cancellationMonthOptionSchema = z.object({
  value: z.string(),
  label: z.string(),
  serviceEndDate: z.string(),
  rentalReturnDeadline: z.string(),
  isCurrentMonth: z.boolean(),
});

export type CancellationMonthOption = z.infer<typeof cancellationMonthOptionSchema>;

/**
 * Schema for cancellation eligibility check result
 */
export const cancellationEligibilitySchema = z.object({
  canCancel: z.boolean(),
  earliestCancellationMonth: z.string(),
  availableMonths: z.array(cancellationMonthOptionSchema),
  currentMonthDeadline: z.string().nullable(),
  reason: z.string().optional(),
});

export type CancellationEligibility = z.infer<typeof cancellationEligibilitySchema>;

// ============================================================================
// Cancellation Status Schema
// ============================================================================

/**
 * Schema for cancellation status display
 */
export const cancellationStatusSchema = z.object({
  stage: z.enum(OPPORTUNITY_STAGE_VALUES),
  isPending: z.boolean(),
  isComplete: z.boolean(),
  scheduledEndDate: z.string().optional(),
  rentalReturnStatus: z.enum(LINE_RETURN_STATUS_VALUES).optional(),
  rentalReturnDeadline: z.string().optional(),
  hasRentalEquipment: z.boolean(),
});

export type CancellationStatus = z.infer<typeof cancellationStatusSchema>;

// ============================================================================
// Opportunity Lookup Schema
// ============================================================================

/**
 * Schema for Opportunity lookup criteria
 */
export const opportunityLookupCriteriaSchema = z.object({
  accountId: z.string().min(15),
  productType: z.enum(OPPORTUNITY_PRODUCT_TYPE_VALUES),
  allowedStages: z.array(z.enum(OPPORTUNITY_STAGE_VALUES)).optional(),
});

export type OpportunityLookupCriteria = z.infer<typeof opportunityLookupCriteriaSchema>;

// ============================================================================
// Opportunity Match Result Schema
// ============================================================================

/**
 * Schema for Opportunity matching result
 */
export const opportunityMatchResultSchema = z.object({
  opportunityId: z.string(),
  wasCreated: z.boolean(),
  previousStage: z.enum(OPPORTUNITY_STAGE_VALUES).optional(),
});

export type OpportunityMatchResult = z.infer<typeof opportunityMatchResultSchema>;

// ============================================================================
// API Response Schemas
// ============================================================================

/**
 * Schema for Opportunity API response
 */
export const opportunityResponseSchema = z.object({
  opportunity: opportunityRecordSchema,
});

/**
 * Schema for create Opportunity response
 */
export const createOpportunityResponseSchema = z.object({
  opportunityId: z.string(),
  stage: z.enum(OPPORTUNITY_STAGE_VALUES),
});

/**
 * Schema for cancellation preview response
 */
export const cancellationPreviewResponseSchema = z.object({
  eligibility: cancellationEligibilitySchema,
  terms: z.object({
    deadlineDay: z.number(),
    rentalReturnDeadlineDay: z.number(),
    fullMonthCharge: z.boolean(),
  }),
});
