import { z } from 'zod'

// Базовые типы для валидации
export type OrganizationType = 'FULFILLMENT' | 'SELLER' | 'LOGIST' | 'WHOLESALE'

// Схема валидации телефона
const phoneSchema = z
  .string()
  .min(10, 'Телефон должен содержать минимум 10 цифр')
  .max(15, 'Телефон не может содержать больше 15 цифр')
  .regex(/^\+?[1-9]\d{1,14}$/, 'Неверный формат телефона')

// Схема валидации ИНН
const innSchema = z
  .string()
  .regex(/^\d{10}$|^\d{12}$/, 'ИНН должен содержать 10 или 12 цифр')
  .refine((inn) => validateInnChecksum(inn), 'Неверная контрольная сумма ИНН')

// Схема валидации КПП
const kppSchema = z
  .string()
  .regex(/^\d{9}$/, 'КПП должен содержать 9 цифр')
  .optional()

// Схема валидации API ключей
const wbApiKeySchema = z
  .string()
  .min(10, 'API ключ Wildberries слишком короткий')
  .max(200, 'API ключ Wildberries слишком длинный')
  .optional()

const ozonApiKeySchema = z
  .string()
  .min(10, 'API ключ Ozon слишком короткий')  
  .max(200, 'API ключ Ozon слишком длинный')
  .optional()

const ozonClientIdSchema = z
  .string()
  .min(1, 'Client ID Ozon обязателен при указании API ключа')
  .max(100, 'Client ID Ozon слишком длинный')
  .optional()

// Основная схема валидации регистрации организации
export const organizationRegistrationSchema = z.object({
  // Обязательные поля
  phone: phoneSchema,
  type: z.enum(['FULFILLMENT', 'SELLER', 'LOGIST', 'WHOLESALE'], {
    errorMap: () => ({ message: 'Неподдерживаемый тип организации' }),
  }),

  // Поля для бизнес-организаций
  inn: innSchema.optional(),
  kpp: kppSchema,
  name: z.string().max(255, 'Название организации слишком длинное').optional(),
  fullName: z.string().max(500, 'Полное название организации слишком длинное').optional(),
  address: z.string().max(500, 'Адрес слишком длинный').optional(),
  addressFull: z.string().max(1000, 'Полный адрес слишком длинный').optional(),
  ogrn: z.string().regex(/^\d{13}$|^\d{15}$/, 'ОГРН должен содержать 13 или 15 цифр').optional(),
  ogrnDate: z.string().datetime('Неверный формат даты ОГРН').optional(),
  
  // Дополнительные поля
  managerName: z.string().max(255, 'Имя менеджера слишком длинное').optional(),
  managerEmail: z.string().email('Неверный формат email менеджера').optional(),
  managerPhone: phoneSchema.optional(),
  description: z.string().max(2000, 'Описание слишком длинное').optional(),
  logoUrl: z.string().url('Неверный формат URL логотипа').optional(),
  website: z.string().url('Неверный формат URL веб-сайта').optional(),
  
  // Банковские реквизиты
  bankName: z.string().max(255, 'Название банка слишком длинное').optional(),
  bik: z.string().regex(/^\d{9}$/, 'БИК должен содержать 9 цифр').optional(),
  correspondentAccount: z.string().regex(/^\d{20}$/, 'Корреспондентский счет должен содержать 20 цифр').optional(),
  currentAccount: z.string().regex(/^\d{20}$/, 'Расчетный счет должен содержать 20 цифр').optional(),
  taxSystem: z.string().max(50, 'Налоговая система слишком длинная').optional(),

  // Поля для селлеров
  wbApiKey: wbApiKeySchema,
  ozonApiKey: ozonApiKeySchema,
  ozonClientId: ozonClientIdSchema,

  // Общие поля
  referralCode: z.string().max(50, 'Реферальный код слишком длинный').optional(),
  partnerCode: z.string().max(50, 'Партнерский код слишком длинный').optional(),
})

// Специализированные схемы для каждого типа организации
export const fulfillmentRegistrationSchema = organizationRegistrationSchema
  .refine((data) => data.type === 'FULFILLMENT', {
    message: 'Неверный тип организации для фулфилмента',
  })
  .refine((data) => !!data.inn, {
    message: 'ИНН обязателен для фулфилмент организации',
    path: ['inn'],
  })

export const logistRegistrationSchema = organizationRegistrationSchema
  .refine((data) => data.type === 'LOGIST', {
    message: 'Неверный тип организации для логистики',
  })
  .refine((data) => !!data.inn, {
    message: 'ИНН обязателен для логистической организации',
    path: ['inn'],
  })

export const wholesaleRegistrationSchema = organizationRegistrationSchema
  .refine((data) => data.type === 'WHOLESALE', {
    message: 'Неверный тип организации для поставщика',
  })
  .refine((data) => !!data.inn, {
    message: 'ИНН обязателен для оптовой организации',
    path: ['inn'],
  })

export const sellerRegistrationSchema = organizationRegistrationSchema
  .refine((data) => data.type === 'SELLER', {
    message: 'Неверный тип организации для селлера',
  })
  .refine(
    (data) => !!(data.wbApiKey || (data.ozonApiKey && data.ozonClientId)),
    {
      message: 'Для селлеров обязательны API ключи маркетплейсов (Wildberries или Ozon)',
      path: ['wbApiKey'],
    },
  )
  .refine(
    (data) => {
      // Если есть Ozon API ключ, то должен быть и Client ID
      if (data.ozonApiKey && !data.ozonClientId) return false
      if (!data.ozonApiKey && data.ozonClientId) return false
      return true
    },
    {
      message: 'При указании Ozon API ключа обязателен Client ID',
      path: ['ozonClientId'],
    },
  )

// Типы для TypeScript
export type OrganizationRegistrationInput = z.infer<typeof organizationRegistrationSchema>
export type FulfillmentRegistrationInput = z.infer<typeof fulfillmentRegistrationSchema>
export type LogistRegistrationInput = z.infer<typeof logistRegistrationSchema>
export type WholesaleRegistrationInput = z.infer<typeof wholesaleRegistrationSchema>
export type SellerRegistrationInput = z.infer<typeof sellerRegistrationSchema>

// Функция валидации ИНН (контрольная сумма)
function validateInnChecksum(inn: string): boolean {
  const digits = inn.replace(/\D/g, '')

  if (digits.length !== 10 && digits.length !== 12) {
    return false
  }

  // Проверяем контрольную сумму для 10-значного ИНН (юридические лица)
  if (digits.length === 10) {
    const checksum = calculateInn10Checksum(digits)
    return checksum === parseInt(digits[9])
  }

  // Проверяем контрольную сумму для 12-значного ИНН (ИП)
  if (digits.length === 12) {
    const checksum1 = calculateInn12Checksum1(digits)
    const checksum2 = calculateInn12Checksum2(digits)
    return checksum1 === parseInt(digits[10]) && checksum2 === parseInt(digits[11])
  }

  return false
}

function calculateInn10Checksum(inn: string): number {
  const weights = [2, 4, 10, 3, 5, 9, 4, 6, 8]
  let sum = 0

  for (let i = 0; i < 9; i++) {
    sum += parseInt(inn[i]) * weights[i]
  }

  return (sum % 11) % 10
}

function calculateInn12Checksum1(inn: string): number {
  const weights = [7, 2, 4, 10, 3, 5, 9, 4, 6, 8]
  let sum = 0

  for (let i = 0; i < 10; i++) {
    sum += parseInt(inn[i]) * weights[i]
  }

  return (sum % 11) % 10
}

function calculateInn12Checksum2(inn: string): number {
  const weights = [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8]
  let sum = 0

  for (let i = 0; i < 11; i++) {
    sum += parseInt(inn[i]) * weights[i]
  }

  return (sum % 11) % 10
}

// Функция выбора правильной схемы валидации по типу организации
export function getValidationSchemaByType(type: OrganizationType) {
  switch (type) {
    case 'FULFILLMENT':
      return fulfillmentRegistrationSchema
    case 'LOGIST':
      return logistRegistrationSchema
    case 'WHOLESALE':
      return wholesaleRegistrationSchema
    case 'SELLER':
      return sellerRegistrationSchema
    default:
      throw new Error(`Неподдерживаемый тип организации: ${type}`)
  }
}

// Функция валидации с подробными сообщениями об ошибках
export function validateOrganizationRegistration(
  input: unknown,
  type?: OrganizationType,
): { success: true; data: OrganizationRegistrationInput } | { success: false; errors: string[] } {
  try {
    // Используем подходящую схему в зависимости от типа
    const schema = type ? getValidationSchemaByType(type) : organizationRegistrationSchema
    const validData = schema.parse(input)

    return {
      success: true,
      data: validData,
    }
  } catch (error) {
    if (error instanceof z.ZodError) {
      const errors = error.errors.map((err) => {
        const path = err.path.length > 0 ? `${err.path.join('.')}: ` : ''
        return `${path}${err.message}`
      })

      return {
        success: false,
        errors,
      }
    }

    return {
      success: false,
      errors: ['Неожиданная ошибка валидации'],
    }
  }
}

// Бизнес-правила валидации
export const businessRules = {
  // Обязательные поля для каждого типа организации
  requiredFieldsByType: {
    FULFILLMENT: ['phone', 'type', 'inn'] as const,
    LOGIST: ['phone', 'type', 'inn'] as const,
    WHOLESALE: ['phone', 'type', 'inn'] as const,
    SELLER: ['phone', 'type'] as const, // API ключи валидируются отдельно
  },

  // API ключи требуются для селлеров
  sellerApiKeyRequirements: {
    atLeastOne: ['wbApiKey', 'ozonApiKey'] as const,
    ozonRequiresBoth: ['ozonApiKey', 'ozonClientId'] as const,
  },

  // Ограничения по длине полей
  fieldLengthLimits: {
    phone: { min: 10, max: 15 },
    inn: { exact: [10, 12] },
    kpp: { exact: [9] },
    ogrn: { exact: [13, 15] },
    bik: { exact: [9] },
    correspondentAccount: { exact: [20] },
    currentAccount: { exact: [20] },
    name: { max: 255 },
    fullName: { max: 500 },
    address: { max: 500 },
    addressFull: { max: 1000 },
    description: { max: 2000 },
  } as const,
} as const

// Экспорт всех схем для использования в других частях приложения
export {
  organizationRegistrationSchema as default,
  phoneSchema,
  innSchema,
  kppSchema,
  wbApiKeySchema,
  ozonApiKeySchema,
  ozonClientIdSchema,
}