import { z } from "zod"

export const BRAZILIAN_UF = [
  { value: "AC", label: "Acre" },
  { value: "AL", label: "Alagoas" },
  { value: "AP", label: "Amapá" },
  { value: "AM", label: "Amazonas" },
  { value: "BA", label: "Bahia" },
  { value: "CE", label: "Ceará" },
  { value: "DF", label: "Distrito Federal" },
  { value: "ES", label: "Espírito Santo" },
  { value: "GO", label: "Goiás" },
  { value: "MA", label: "Maranhão" },
  { value: "MT", label: "Mato Grosso" },
  { value: "MS", label: "Mato Grosso do Sul" },
  { value: "MG", label: "Minas Gerais" },
  { value: "PA", label: "Pará" },
  { value: "PB", label: "Paraíba" },
  { value: "PR", label: "Paraná" },
  { value: "PE", label: "Pernambuco" },
  { value: "PI", label: "Piauí" },
  { value: "RJ", label: "Rio de Janeiro" },
  { value: "RN", label: "Rio Grande do Norte" },
  { value: "RS", label: "Rio Grande do Sul" },
  { value: "RO", label: "Rondônia" },
  { value: "RR", label: "Roraima" },
  { value: "SC", label: "Santa Catarina" },
  { value: "SP", label: "São Paulo" },
  { value: "SE", label: "Sergipe" },
  { value: "TO", label: "Tocantins" },
] as const

export const COMPANY_STATE_REGISTRATION_TYPES = [
  { value: "standard", label: "Inscrição estadual" },
  { value: "exempt", label: "Isento" },
  { value: "simples", label: "Simples Nacional" },
] as const

export const COMPANY_CONTACT_ROLES = [
  { value: "financeiro", label: "Financeiro" },
  { value: "decisor", label: "Decisor" },
  { value: "ti", label: "TI" },
  { value: "juridico", label: "Jurídico" },
  { value: "compras", label: "Compras" },
  { value: "usuario_chave", label: "Usuário-chave" },
  { value: "outro", label: "Outro" },
] as const

export const COMPANY_CONTACT_PREFERENCES = [
  { value: "email", label: "E-mail" },
  { value: "phone", label: "Telefone" },
  { value: "whatsapp", label: "WhatsApp" },
  { value: "business_hours", label: "Horário comercial" },
] as const

export const COMPANY_LOCATION_TYPES = [
  { value: "matrix", label: "Matriz" },
  { value: "branch", label: "Filial" },
  { value: "data_center", label: "Data Center" },
  { value: "home_office", label: "Home Office" },
  { value: "other", label: "Outro" },
] as const

export const COMPANY_CONTRACT_TYPES = [
  { value: "monthly", label: "Mensalidade" },
  { value: "time_bank", label: "Banco de horas" },
  { value: "per_ticket", label: "Por chamado" },
  { value: "project", label: "Projetos" },
] as const

export const COMPANY_CONTRACT_SCOPES = [
  "suporte_m365",
  "endpoints",
  "rede",
  "servidores",
  "backup",
  "email",
  "impressoras",
  "seguranca",
] as const

export const COMPANY_CRITICALITY_LEVELS = [
  { value: "low", label: "Baixa" },
  { value: "medium", label: "Média" },
  { value: "high", label: "Alta" },
] as const

export const COMPANY_REGULATION_OPTIONS = [
  { value: "lgpd_critical", label: "LGPD crítico" },
  { value: "finance", label: "Financeiro" },
  { value: "health", label: "Saúde" },
  { value: "public", label: "Setor público" },
  { value: "education", label: "Educação" },
  { value: "custom", label: "Outro" },
] as const

export const SLA_SEVERITY_LEVELS = ["P1", "P2", "P3", "P4"] as const

const daySchema = z.enum(["mon", "tue", "wed", "thu", "fri", "sat", "sun"])
const ufSchema = z.enum(BRAZILIAN_UF.map((item) => item.value) as [string, ...string[]])
const stateRegistrationTypeSchema = z.enum(
  COMPANY_STATE_REGISTRATION_TYPES.map((item) => item.value) as [string, ...string[]]
)
const contactRoleSchema = z.enum(
  COMPANY_CONTACT_ROLES.map((item) => item.value) as [string, ...string[]]
)
const contactPreferenceSchema = z.enum(
  COMPANY_CONTACT_PREFERENCES.map((item) => item.value) as [string, ...string[]]
)
const locationTypeSchema = z.enum(
  COMPANY_LOCATION_TYPES.map((item) => item.value) as [string, ...string[]]
)
const contractTypeSchema = z.enum(
  COMPANY_CONTRACT_TYPES.map((item) => item.value) as [string, ...string[]]
)
const contractScopeSchema = z.enum(COMPANY_CONTRACT_SCOPES)
const criticalitySchema = z.enum(
  COMPANY_CRITICALITY_LEVELS.map((item) => item.value) as [string, ...string[]]
)
const regulationSchema = z.enum(
  COMPANY_REGULATION_OPTIONS.map((item) => item.value) as [string, ...string[]]
)
const severitySchema = z.enum(SLA_SEVERITY_LEVELS)

const phoneRegex = /^[0-9()+\s-]{8,20}$/
const timeRegex = /^\d{2}:\d{2}$/
const dateRegex = /^\d{4}-\d{2}-\d{2}$/
const cnpjDigitsRegex = /^\d{14}$/
const cepRegex = /^\d{5}-?\d{3}$/
const domainRegex =
  /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/i

const optionalString = z
  .string()
  .trim()
  .transform((value) => (value.length === 0 ? null : value))
  .nullable()
  .optional()

const monetarySchema = z
  .union([z.number(), z.string()])
  .transform((value) => {
    if (typeof value === "number") return value
    const normalized = value.replace(/\./g, "").replace(",", ".")
    const parsed = Number(normalized)
    return Number.isFinite(parsed) ? parsed : null
  })
  .nullable()

const servicePeriodSchema = z.object({
  days: z.array(daySchema).min(1, "Informe ao menos um dia"),
  start: z
    .string()
    .regex(timeRegex, "Use o formato HH:MM"),
  end: z
    .string()
    .regex(timeRegex, "Use o formato HH:MM"),
})

export const businessHoursSchema = z
  .object({
    mode: z.enum(["business", "twentyfour", "custom"]).default("business"),
    timezone: z.string().min(3).default("America/Sao_Paulo"),
    periods: z.array(servicePeriodSchema).default([]),
  })
  .refine(
    (value) => {
      if (value.mode === "twentyfour") return true
      return value.periods.length > 0
    },
    { message: "Defina pelo menos um período", path: ["periods"] }
  )

const addressSchema = z
  .object({
    street: z.string().min(3, "Informe a rua"),
    number: z.string().min(1, "Informe o número"),
    complement: optionalString,
    district: z.string().min(2, "Informe o bairro"),
    city: z.string().min(2, "Informe a cidade"),
    state: ufSchema,
    zip: z
      .string()
      .regex(cepRegex, "CEP inválido"),
  })
  .partial({
    complement: true,
  })

const contactSchema = z.object({
  id: z.string(),
  fullName: z.string().min(3, "Nome obrigatório"),
  email: z.string().email("E-mail inválido"),
  phone: z
    .string()
    .regex(phoneRegex, "Telefone inválido")
    .nullable()
    .optional(),
  whatsapp: z
    .string()
    .regex(phoneRegex, "WhatsApp inválido")
    .nullable()
    .optional(),
  role: contactRoleSchema,
  title: z.string().trim().nullable().optional(),
  preference: z.array(contactPreferenceSchema).default([]),
  canAuthorizeTickets: z.boolean().default(false),
  canApproveCosts: z.boolean().default(false),
  lgpdConsent: z.boolean().default(true),
  notes: z.string().trim().nullable().optional(),
})

const locationSchema = z.object({
  id: z.string(),
  name: z.string().min(2, "Informe o nome da unidade"),
  type: locationTypeSchema,
  address: addressSchema.nullish(),
  responsibleContactId: z.string().nullable().optional(),
  serviceWindow: z
    .object({
      mode: z.enum(["inherit", "custom"]).default("inherit"),
      periods: z.array(servicePeriodSchema).default([]),
    })
    .refine(
      (value) => (value.mode === "inherit" ? true : value.periods.length > 0),
      { message: "Defina períodos personalizados", path: ["periods"] }
    ),
  notes: z.string().trim().nullable().optional(),
})

const contractSchema = z.object({
  id: z.string(),
  contractType: contractTypeSchema,
  planSku: z.string().trim().nullable().optional(),
  startDate: z
    .string()
    .regex(dateRegex, "Formato AAAA-MM-DD")
    .nullable()
    .optional(),
  endDate: z
    .string()
    .regex(dateRegex, "Formato AAAA-MM-DD")
    .nullable()
    .optional(),
  renewalDate: z
    .string()
    .regex(dateRegex, "Formato AAAA-MM-DD")
    .nullable()
    .optional(),
  scope: z.array(contractScopeSchema).default([]),
  price: monetarySchema,
  costCenter: z.string().trim().nullable().optional(),
  criticality: criticalitySchema.default("medium"),
  notes: z.string().trim().nullable().optional(),
})

const severityEntrySchema = z.object({
  level: severitySchema,
  responseMinutes: z
    .number()
    .int()
    .min(0)
    .default(60),
  resolutionMinutes: z
    .number()
    .int()
    .min(0)
    .default(240),
})

const slaSchema = z.object({
  calendar: z.enum(["24x7", "business", "custom"]).default("business"),
  validChannels: z.array(z.string().min(3)).default([]),
  holidays: z
    .array(
      z
        .string()
        .regex(dateRegex, "Formato AAAA-MM-DD")
    )
    .default([]),
  severities: z
    .array(severityEntrySchema)
    .default([
      { level: "P1", responseMinutes: 30, resolutionMinutes: 240 },
      { level: "P2", responseMinutes: 60, resolutionMinutes: 480 },
      { level: "P3", responseMinutes: 120, resolutionMinutes: 1440 },
      { level: "P4", responseMinutes: 240, resolutionMinutes: 2880 },
    ]),
  serviceWindow: z
    .object({
      timezone: z.string().default("America/Sao_Paulo"),
      periods: z.array(servicePeriodSchema).default([]),
    })
    .optional(),
})

const communicationChannelsSchema = z.object({
  supportEmails: z.array(z.string().email()).default([]),
  billingEmails: z.array(z.string().email()).default([]),
  whatsappNumbers: z.array(z.string().regex(phoneRegex, "Telefone inválido")).default([]),
  phones: z.array(z.string().regex(phoneRegex, "Telefone inválido")).default([]),
  portals: z.array(z.string().url("URL inválida")).default([]),
})

const privacyPolicySchema = z.object({
  accepted: z.boolean().default(false),
  reference: z.string().url("URL inválida").nullable().optional(),
  metadata: z.record(z.string(), z.unknown()).optional(),
})

const customFieldSchema = z.object({
  id: z.string(),
  key: z.string().min(1),
  label: z.string().min(1),
  type: z.enum(["text", "number", "boolean", "date", "url"]).default("text"),
  value: z.union([z.string(), z.number(), z.boolean(), z.null()]).nullable(),
})

const domainSchema = z
  .string()
  .trim()
  .toLowerCase()
  .regex(domainRegex, "Domínio inválido")

export const companyFormSchema = z.object({
  tenantId: z.string(),
  name: z.string().min(2, "Nome obrigatório"),
  slug: z
    .string()
    .min(2, "Informe um apelido")
    .regex(/^[a-z0-9-]+$/, "Use apenas letras minúsculas, números ou hífen"),
  legalName: z.string().trim().nullable().optional(),
  tradeName: z.string().trim().nullable().optional(),
  cnpj: z
    .string()
    .regex(cnpjDigitsRegex, "CNPJ deve ter 14 dígitos")
    .nullable()
    .optional(),
  stateRegistration: z.string().trim().nullable().optional(),
  stateRegistrationType: stateRegistrationTypeSchema.nullish(),
  primaryCnae: z.string().trim().nullable().optional(),
  description: z.string().trim().nullable().optional(),
  domain: domainSchema.nullable().optional(),
  phone: z
    .string()
    .regex(phoneRegex, "Telefone inválido")
    .nullable()
    .optional(),
  address: z.string().trim().nullable().optional(),
  contractedHoursPerMonth: z
    .number()
    .min(0)
    .nullable()
    .optional(),
  businessHours: businessHoursSchema.nullish(),
  communicationChannels: communicationChannelsSchema.default({
    supportEmails: [],
    billingEmails: [],
    whatsappNumbers: [],
    phones: [],
    portals: [],
  }),
  supportEmail: z.string().email().nullable().optional(),
  billingEmail: z.string().email().nullable().optional(),
  contactPreferences: z
    .object({
      defaultChannel: contactPreferenceSchema.nullable().optional(),
      escalationNotes: z.string().trim().nullable().optional(),
    })
    .optional(),
  clientDomains: z.array(domainSchema).default([]),
  fiscalAddress: addressSchema.nullish(),
  hasBranches: z.boolean().default(false),
  regulatedEnvironments: z.array(regulationSchema).default([]),
  privacyPolicy: privacyPolicySchema.default({
    accepted: false,
    reference: null,
  }),
  contacts: z.array(contactSchema).default([]),
  locations: z.array(locationSchema).default([]),
  contracts: z.array(contractSchema).default([]),
  sla: slaSchema.nullish(),
  tags: z.array(z.string().trim().min(1)).default([]),
  customFields: z.array(customFieldSchema).default([]),
  notes: z.string().trim().nullable().optional(),
  isAvulso: z.boolean().default(false),
})

export type CompanyFormValues = z.infer<typeof companyFormSchema>
export type CompanyContact = z.infer<typeof contactSchema>
export type CompanyLocation = z.infer<typeof locationSchema>
export type CompanyContract = z.infer<typeof contractSchema>
export type CompanySla = z.infer<typeof slaSchema>
export type CompanyBusinessHours = z.infer<typeof businessHoursSchema>
export type CompanyCommunicationChannels = z.infer<typeof communicationChannelsSchema>
export type CompanyStateRegistrationTypeOption =
  (typeof COMPANY_STATE_REGISTRATION_TYPES)[number]["value"]

export const defaultBusinessHours: CompanyBusinessHours = {
  mode: "business",
  timezone: "America/Sao_Paulo",
  periods: [
    {
      days: ["mon", "tue", "wed", "thu", "fri"],
      start: "09:00",
      end: "18:00",
    },
  ],
}

export const defaultSla: CompanySla = {
  calendar: "business",
  validChannels: [],
  holidays: [],
  severities: [
    { level: "P1", responseMinutes: 30, resolutionMinutes: 240 },
    { level: "P2", responseMinutes: 60, resolutionMinutes: 480 },
    { level: "P3", responseMinutes: 120, resolutionMinutes: 1440 },
    { level: "P4", responseMinutes: 240, resolutionMinutes: 2880 },
  ],
  serviceWindow: {
    timezone: "America/Sao_Paulo",
    periods: [
      {
        days: ["mon", "tue", "wed", "thu", "fri"],
        start: "09:00",
        end: "18:00",
      },
    ],
  },
}

export type CompanyFormPayload = CompanyFormValues

export const companyInputSchema = companyFormSchema.extend({
  tenantId: companyFormSchema.shape.tenantId.optional(),
})

export type CompanyInputPayload = z.infer<typeof companyInputSchema>
