import { z } from 'zod';

import { baseListQuerySchema } from '@/lib/api/list-query';
import { DOCUMENT_TYPES, DOCUMENT_STATUSES } from '@/lib/constants';

export const createDocumentSchema = z.object({
  interestId: z.string().optional(),
  clientId: z.string().optional(),
  folderId: z.string().nullable().optional(),
  documentType: z.enum(DOCUMENT_TYPES),
  title: z.string().min(1).max(200),
  notes: z.string().optional(),
});

export const updateDocumentSchema = z.object({
  title: z.string().min(1).max(200).optional(),
  notes: z.string().optional(),
  status: z.enum(DOCUMENT_STATUSES).optional(),
});

const wizardSignerSchema = z.object({
  signerName: z.string().min(1),
  signerEmail: z.string().email(),
  signerRole: z.enum(['client', 'sales', 'approver', 'developer', 'other']),
  signingOrder: z.number().int().min(1),
});

export const createDocumentWizardSchema = z
  .object({
    source: z.enum(['template', 'upload']).default('template'),
    templateId: z.string().optional(),
    uploadedFileId: z.string().optional(),

    documentType: z.enum(DOCUMENT_TYPES),
    title: z.string().min(1).max(200),
    notes: z.string().optional(),

    interestId: z.string().optional(),
    tenancyId: z.string().optional(),
    clientId: z.string().optional(),
    companyId: z.string().optional(),
    yachtId: z.string().optional(),

    signers: z.array(wizardSignerSchema).optional(),
    signingMode: z.enum(['sequential', 'parallel']).default('sequential'),
    pathway: z.enum(['documenso-template', 'inapp', 'upload']).default('documenso-template'),

    watchers: z.array(z.string()).default([]),

    reminderCadenceOverride: z.number().int().min(1).max(365).nullable().optional(),
    remindersDisabled: z.boolean().default(false),

    autoPlaceFields: z.boolean().default(true),
    sendImmediately: z.boolean().default(true),
  })
  .refine(
    (d) =>
      [d.interestId, d.tenancyId, d.clientId, d.companyId, d.yachtId].filter(Boolean).length === 1,
    { message: 'Exactly one subject (interest/tenancy/client/company/yacht) is required' },
  )
  .refine((d) => d.source !== 'template' || Boolean(d.templateId), {
    path: ['templateId'],
    message: 'templateId is required when source=template',
  })
  .refine((d) => d.source !== 'upload' || Boolean(d.uploadedFileId), {
    path: ['uploadedFileId'],
    message: 'uploadedFileId is required when source=upload',
  });

export type CreateDocumentWizardInput = z.infer<typeof createDocumentWizardSchema>;

export const documentsHubTabs = [
  'all',
  'in_progress',
  'eoi_queue',
  'awaiting_them',
  'awaiting_me',
  'completed',
  'expired',
] as const;
export type DocumentsHubTab = (typeof documentsHubTabs)[number];

export const listDocumentsSchema = baseListQuerySchema
  .extend({
    interestId: z.string().optional(),
    clientId: z.string().optional(),
    documentType: z.string().optional(),
    folderId: z
      .string()
      .nullable()
      .transform((v) => (v === '' ? null : v))
      .optional(),
    includeDescendants: z.coerce.boolean().optional(),
    status: z.string().optional(),
    /** Hub tab filter - applies tab-specific status / signer-membership constraints. */
    tab: z.enum(documentsHubTabs).optional(),
    /** Restrict to docs being watched by this user id. */
    watcherUserId: z.string().optional(),
    /** When true, only docs intended for signing (default true on hub). */
    signatureOnly: z
      .enum(['true', 'false'])
      .transform((v) => v === 'true')
      .optional(),
    sentSince: z.string().datetime().optional(),
    sentUntil: z.string().datetime().optional(),
    /** Entity-aggregated projection params - mutually exclusive with folderId. */
    entityType: z.enum(['client', 'company', 'yacht']).optional(),
    entityId: z.string().uuid().optional(),
  })
  .refine(
    (q) => !(q.folderId !== undefined && (q.entityType !== undefined || q.entityId !== undefined)),
    {
      message: 'folderId is mutually exclusive with entityType/entityId',
      path: ['folderId'],
    },
  )
  .refine((q) => Boolean(q.entityType) === Boolean(q.entityId), {
    message: 'entityType and entityId must be provided together',
    path: ['entityType'],
  });

export const uploadSignedSchema = z.object({
  documentId: z.string().min(1),
});

export type CreateDocumentInput = z.infer<typeof createDocumentSchema>;
export type UpdateDocumentInput = z.infer<typeof updateDocumentSchema>;
export type ListDocumentsInput = z.infer<typeof listDocumentsSchema>;
