import { z } from 'zod';

// Contratos canônicos de C3 — Pedidos SAR.
// Consumidos pela API (output tipado) e pela Web (TanStack Query + parse).
// ADR 0006 revogado: OrderStatus enum → situa Int (1=Pendente, 2=Aprovado, 3=Cancelado, 4=Faturado)

// ─── Situa ────────────────────────────────────────────────────────────────────

// Ciclo de vida do pedido SAR:
//   0=Orçamento → 1=Ag. Aprovação (se desconto > alçada) → 2=Transmitido
// Estados que o SAR controla: Orçamento e Transmitido (1 é o gate de desconto).
// Após Transmitido, o status passa a refletir o ERP (Emitido/Cancelado/Aguardando…)
// — espelhado quando a integração existir.
export const SituaPedidoSchema = z.union([
  z.literal(0),
  z.literal(1),
  z.literal(2),
  z.literal(3),
  z.literal(4),
]);
export type SituaPedido = z.infer<typeof SituaPedidoSchema>;

export const SITUA_LABEL: Record<number, string> = {
  0: 'Orçamento',
  1: 'Ag. Aprovação',
  2: 'Transmitido',
  3: 'Cancelado',
  4: 'Faturado',
};

// ─── PedidoItem ───────────────────────────────────────────────────────────────

export const PedidoItemSchema = z.object({
  id: z.string(), // UUID para pedidos SAR; '{idPedido}-{ordem}' para ERP
  idProduto: z.number().int(),
  codProduto: z.string().nullable(),
  descProduto: z.string().nullable(),
  ordem: z.number().int(),
  qtd: z.string(),
  precoUnitario: z.string(),
  descontoPerc: z.string(),
  total: z.string(),
  // Grupo/subgrupo do produto (vw_produtos) — edição do orçamento usa para o
  // teto de desconto. Ausente em pedidos ERP.
  codGrupo: z.number().int().nullable().optional(),
  codSubgrupo: z.number().int().nullable().optional(),
});
export type PedidoItem = z.infer<typeof PedidoItemSchema>;

// ─── HistoricoPedido ──────────────────────────────────────────────────────────

export const HistoricoPedidoSchema = z.object({
  id: z.string().uuid(),
  situaAnterior: z.number().int().nullable(),
  situaNova: z.number().int(),
  changedBy: z.number().int(),
  nota: z.string().nullable(),
  changedAt: z.iso.datetime(),
});
export type HistoricoPedido = z.infer<typeof HistoricoPedidoSchema>;

// ─── Pedido Summary (lista) ───────────────────────────────────────────────────

export const PedidoSummarySchema = z.object({
  id: z.string(), // UUID para pedidos SAR, 'erp-{id}' para histórico ERP
  numPedSar: z.string(),
  numero: z.number().int().optional(), // número do pedido no ERP
  idCliente: z.number().int(),
  nomeCliente: z.string().nullable().optional(),
  razaoCliente: z.string().nullable().optional(),
  codVendedor: z.number().int(),
  nomeVendedor: z.string().nullable().optional(),
  situa: z.number().int(),
  statusDescr: z.string().optional(), // descrição legível do status
  dtPedido: z.string(),
  total: z.string(),
  descontoPerc: z.string(),
  obs: z.string().nullable(),
  createdAt: z.iso.datetime(),
  fonte: z.enum(['sar', 'erp']).default('sar'),
});
export type PedidoSummary = z.infer<typeof PedidoSummarySchema>;

// ─── Pedido Detail ────────────────────────────────────────────────────────────

export const PedidoDetailSchema = PedidoSummarySchema.extend({
  totalProdutos: z.string(),
  totalIpi: z.string(),
  totalIcmsst: z.string(),
  descontoValor: z.string(),
  acrescimo: z.string(),
  comissao: z.string(),
  pedFlex: z.string(),
  formaPagamento: z.string().nullable().optional(),
  endEntrega: z.string().nullable().optional(),
  // Pauta/forma de pagamento do pedido SAR — edição do orçamento pré-carrega
  idPauta: z.number().int().nullable().optional(),
  codFormapag: z.number().int().nullable().optional(),
  // Peso total (kg) e cubagem (m3) — qtd x peso_liquido/vol_m3 de vw_produtos
  pesoTotal: z.string().optional(),
  m3Total: z.string().optional(),
  aprovadoPor: z.number().int().nullable(),
  aprovadoEm: z.iso.datetime().nullable(),
  motivoRecusa: z.string().nullable(),
  idempotencyKey: z.string().nullable(),
  updatedAt: z.iso.datetime(),
  itens: z.array(PedidoItemSchema),
  historico: z.array(HistoricoPedidoSchema),
});
export type PedidoDetail = z.infer<typeof PedidoDetailSchema>;

// ─── List query + response ────────────────────────────────────────────────────

// Datas de filtro sempre YYYY-MM-DD — interpoladas em SQL no servidor, o formato
// fechado é parte da defesa contra injection, não só validação de UX.
export const DateOnlySchema = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Data deve ser YYYY-MM-DD');

export const PedidoListQuerySchema = z.object({
  idCliente: z.coerce.number().int().optional(),
  situa: z.coerce.number().int().optional(),
  numPedSar: z.string().optional(),
  from: DateOnlySchema.optional(),
  to: DateOnlySchema.optional(),
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().min(1).max(200).default(50),
});
export type PedidoListQuery = z.infer<typeof PedidoListQuerySchema>;

export const PedidoListResponseSchema = z.object({
  data: z.array(PedidoSummarySchema),
  total: z.number().int().nonnegative(),
  page: z.number().int().positive(),
  limit: z.number().int().positive(),
});
export type PedidoListResponse = z.infer<typeof PedidoListResponseSchema>;

// ─── Mutações ─────────────────────────────────────────────────────────────────

export const CreatePedidoItemSchema = z.object({
  idProduto: z.number().int().positive(),
  codProduto: z.string().optional(),
  descProduto: z.string().min(1),
  ordem: z.number().int().min(1),
  qtd: z.number().positive(),
  precoUnitario: z.number().nonnegative(),
  descontoPerc: z.number().min(0).max(100).default(0),
});
export type CreatePedidoItem = z.infer<typeof CreatePedidoItemSchema>;

export const CreatePedidoSchema = z.object({
  idCliente: z.number().int().positive(),
  descontoPerc: z.number().min(0).max(100).default(0),
  idPauta: z.number().int().optional(),
  codFormapag: z.number().int().optional(),
  obs: z.string().optional(),
  endEntrega: z.string().optional(),
  idempotencyKey: z.string().optional(),
  itens: z.array(CreatePedidoItemSchema).min(1),
});
export type CreatePedido = z.infer<typeof CreatePedidoSchema>;

// Edição de orçamento (situa 0): mesmo shape da criação, sem idempotencyKey
export const UpdatePedidoSchema = CreatePedidoSchema.omit({ idempotencyKey: true });
export type UpdatePedido = z.infer<typeof UpdatePedidoSchema>;

// Cancelamento com motivo obrigatório + descrição livre opcional
export const CancelPedidoSchema = z.object({
  motivo: z.string().min(1).max(60),
  descricao: z.string().max(500).optional(),
});
export type CancelPedido = z.infer<typeof CancelPedidoSchema>;

export const AprovarPedidoSchema = z.object({
  descontoPerc: z.number().min(0).max(100).optional(),
  nota: z.string().optional(),
});
export type AprovarPedido = z.infer<typeof AprovarPedidoSchema>;

export const RecusarPedidoSchema = z.object({
  motivo: z.string().min(1),
});
export type RecusarPedido = z.infer<typeof RecusarPedidoSchema>;

// ─── ERP Consulta ─────────────────────────────────────────────────────────────

export const PedidoErpConsultaItemSchema = z.object({
  numeroPedido: z.number().int(),
  data: z.string(),
  dtPrevent: z.string().nullable(),
  dataEmissao: z.string().nullable(),
  situa: z.number().int(),
  statusDescr: z.string().nullable(),
  idCliente: z.number().int(),
  nomeCliente: z.string().nullable(),
  razaoCliente: z.string().nullable(),
  codVendedor: z.number().int(),
  formaPagamento: z.string().nullable(),
  total: z.string(),
  obs: z.string().nullable(),
  tipo: z.enum(['P', 'E']),
  numPedSar: z.string().nullable(),
  numeroEntrega: z.number().int().nullable(),
  numeroNf: z.number().int().nullable(),
  chaveAcessoNfe: z.string().nullable(),
  sitPed: z.number().int().nullable(),
  idPedido: z.number().int().nullable(),
});
export type PedidoErpConsultaItem = z.infer<typeof PedidoErpConsultaItemSchema>;

export const PedidoErpConsultaQuerySchema = z.object({
  search: z.string().optional(),
  from: DateOnlySchema.optional(),
  to: DateOnlySchema.optional(),
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().min(1).max(200).default(50),
});
export type PedidoErpConsultaQuery = z.infer<typeof PedidoErpConsultaQuerySchema>;

export const PedidoErpConsultaResponseSchema = z.object({
  data: z.array(PedidoErpConsultaItemSchema),
  total: z.number().int().nonnegative(),
  page: z.number().int().positive(),
  limit: z.number().int().positive(),
});
export type PedidoErpConsultaResponse = z.infer<typeof PedidoErpConsultaResponseSchema>;
