import type {
  AdminCategoryRecord,
  AdminCourseRecord,
  AdminRoleRecord,
  AdminScheduleRecord,
  AdminAnnouncementRecord,
  AdminHeroSlideRecord,
  AdminLeadRecord,
  AdminMenuRecord,
  AdminCommentRecord,
  AdminFaqRecord,
  AdminGuideCardRecord,
  AdminSettingRecord,
  AdminPageRecord,
  AdminPageBlockRecord,
  AdminStoryRecord,
  AdminUserRecord,
  ApiItemResponse,
  ApiListResponse,
  AuthUser,
  PaginatedResult,
  PermissionGroup,
} from './types'

function unwrapData<T>(payload: T | ApiItemResponse<T> | ApiListResponse<T>) {
  if (payload && typeof payload === 'object' && 'data' in payload) {
    return payload.data as T
  }

  return payload as T
}

function toStringArray(value: unknown): string[] {
  if (!value) return []

  if (Array.isArray(value)) {
    return value
      .map((item) => {
        if (typeof item === 'string') return item
        if (item && typeof item === 'object' && 'name' in item) {
          return String(item.name)
        }

        return String(item)
      })
      .filter(Boolean)
  }

  return [String(value)]
}

function titleize(value: string) {
  return value
    .split(/[-_\s]+/)
    .filter(Boolean)
    .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
    .join(' ')
}

function formatPermissionGroupLabel(value: string) {
  const labels: Record<string, string> = {
    announcement: 'Duyurular',
    announcements: 'Duyurular',
    category: 'Kategoriler',
    categories: 'Kategoriler',
    comment: 'Yorumlar',
    comments: 'Yorumlar',
    course: 'Eğitimler',
    courses: 'Eğitimler',
    faq: 'SSS',
    faqs: 'SSS',
    'guide-card': 'Rehber Kartları',
    'guide-cards': 'Rehber Kartları',
    'hero-slide': 'Hero Slaytları',
    'hero-slides': 'Hero Slaytları',
    lead: 'Başvurular',
    leads: 'Başvurular',
    menu: 'Menüler',
    menus: 'Menüler',
    page: 'Sayfalar',
    pages: 'Sayfalar',
    'page-block': 'Sayfa Blokları',
    'page-blocks': 'Sayfa Blokları',
    role: 'Roller',
    roles: 'Roller',
    schedule: 'Eğitim Takvimi',
    schedules: 'Eğitim Takvimi',
    setting: 'Ayarlar',
    settings: 'Ayarlar',
    user: 'Kullanıcılar',
    users: 'Kullanıcılar',
    general: 'Genel',
  }

  return labels[value] ?? titleize(value)
}

function extractPermissionModule(permission: string) {
  const parts = permission.split('-').filter(Boolean)
  const actionTokens = new Set([
    'create',
    'view',
    'any',
    'update',
    'delete',
    'force',
    'restore',
    'reorder',
    'publish',
    'unpublish',
    'assign',
    'sync',
    'list',
  ])

  while (parts.length > 1 && actionTokens.has(parts[0])) {
    parts.shift()
  }

  return parts.join('-') || 'general'
}

function groupPermissionsByModule(permissions: string[]): PermissionGroup[] {
  const grouped = new Map<string, string[]>()

  for (const permission of permissions) {
    const groupKey = extractPermissionModule(permission)
    const current = grouped.get(groupKey) ?? []
    current.push(permission)
    grouped.set(groupKey, current)
  }

  return Array.from(grouped.entries())
    .map(([group, items]) => ({
      group: formatPermissionGroupLabel(group),
      permissions: items.sort((left, right) => left.localeCompare(right)),
    }))
    .sort((left, right) => left.group.localeCompare(right.group, 'tr'))
}

function toStringOrNull(value: unknown) {
  if (value === undefined || value === null || value === '') return null
  return String(value)
}

function toNumber(value: unknown, fallback = 0) {
  if (typeof value === 'number' && Number.isFinite(value)) return value

  if (typeof value === 'string' && value.trim() !== '') {
    const parsed = Number(value)

    if (Number.isFinite(parsed)) return parsed
  }

  return fallback
}

function toBoolean(value: unknown, fallback = false) {
  if (typeof value === 'boolean') return value
  if (typeof value === 'number') return value === 1
  if (typeof value === 'string') {
    if (['1', 'true', 'yes', 'active'].includes(value.toLowerCase())) {
      return true
    }

    if (['0', 'false', 'no', 'inactive'].includes(value.toLowerCase())) {
      return false
    }
  }

  return fallback
}

function toStringList(value: unknown) {
  return toStringArray(value).filter(Boolean)
}

function getRecord(value: unknown) {
  return value && typeof value === 'object'
    ? (value as Record<string, unknown>)
    : null
}

function extractCollection(payload: unknown): Record<string, unknown>[] {
  if (Array.isArray(payload)) {
    return payload.filter(
      (item): item is Record<string, unknown> =>
        !!item && typeof item === 'object'
    )
  }

  const raw = unwrapData(payload as Record<string, unknown>)

  if (Array.isArray(raw)) {
    return raw.filter(
      (item): item is Record<string, unknown> =>
        !!item && typeof item === 'object'
    )
  }

  if (raw && typeof raw === 'object') {
    const candidates = [
      raw.data,
      raw.items,
      raw.roles,
      raw.results,
      raw.records,
    ]

    for (const candidate of candidates) {
      if (Array.isArray(candidate)) {
        return candidate.filter(
          (item): item is Record<string, unknown> =>
            !!item && typeof item === 'object'
        )
      }
    }
  }

  return []
}

export function normalizeAuthUser(payload: unknown): AuthUser {
  const raw = unwrapData(payload as Record<string, unknown>)
  const roles = toStringArray(
    raw && typeof raw === 'object' ? (raw.roles ?? raw.role) : undefined
  )
  const permissions = toStringArray(
    raw && typeof raw === 'object' ? raw.permissions : undefined
  )

  return {
    id:
      raw && typeof raw === 'object' && 'id' in raw
        ? (raw.id as string | number)
        : 'me',
    name:
      raw && typeof raw === 'object' && 'name' in raw
        ? String(raw.name)
        : 'Yonetici',
    email:
      raw && typeof raw === 'object' && 'email' in raw ? String(raw.email) : '',
    roles,
    permissions,
  }
}

export function normalizeUser(
  payload: Record<string, unknown>
): AdminUserRecord {
  const roles = toStringArray(payload.roles ?? payload.role)
  const primaryRole = roles[0] ?? 'editor'
  const deletedAt = payload.deleted_at
  const status = deletedAt
    ? 'inactive'
    : ((payload.status as string) ?? 'active')

  return {
    id: (payload.id as number | string) ?? 'unknown-user',
    name: String(payload.name ?? 'Isimsiz Kullanici'),
    email: String(payload.email ?? ''),
    role: primaryRole,
    roles,
    status: status === 'inactive' || status === 'invited' ? status : 'active',
    createdAt: (payload.created_at as string | null) ?? null,
    updatedAt: (payload.updated_at as string | null) ?? null,
  }
}

export function normalizeRole(
  payload: Record<string, unknown>
): AdminRoleRecord {
  const permissions = toStringArray(payload.permissions)
  const name = String(payload.name ?? 'role')

  return {
    id: (payload.id as number | string) ?? name,
    name,
    permissions,
    permissionCount: permissions.length,
    isSystem: ['super-admin', 'editor'].includes(name),
  }
}

export function normalizeRolesCollection(payload: unknown): AdminRoleRecord[] {
  return extractCollection(payload).map(normalizeRole)
}

export function normalizeCategory(
  payload: Record<string, unknown>
): AdminCategoryRecord {
  return {
    id: (payload.id as number | string) ?? 'unknown-category',
    name: String(payload.name ?? payload.label ?? 'Adsiz kategori'),
    slug: String(payload.slug ?? ''),
    description: String(payload.description ?? payload.desc ?? ''),
    image: toStringOrNull(payload.image),
    icon: toStringOrNull(payload.icon),
    isActive: toBoolean(payload.is_active, true),
    sortOrder: toNumber(payload.sort_order ?? payload.order, 0),
    metaTitle: toStringOrNull(payload.meta_title),
    metaDescription: toStringOrNull(payload.meta_description),
  }
}

export function normalizeCourse(
  payload: Record<string, unknown>
): AdminCourseRecord {
  const category = getRecord(payload.category)

  return {
    id: (payload.id as number | string) ?? 'unknown-course',
    categoryId:
      (payload.category_id as number | string | null) ??
      (category?.id as number | string | null) ??
      null,
    categoryName: String(
      category?.name ??
        category?.label ??
        payload.category_name ??
        'Kategori yok'
    ),
    categorySlug: String(
      category?.slug ??
        payload.category_slug ??
        ''
    ),
    slug: String(payload.slug ?? ''),
    title: String(payload.title ?? 'Adsiz egitim'),
    sub: toStringOrNull(payload.sub),
    description: String(payload.desc ?? payload.description ?? ''),
    longDescription: String(payload.long_desc ?? payload.longDescription ?? ''),
    duration: String(payload.duration ?? ''),
    students: toNumber(payload.students, 0),
    rating: toNumber(payload.rating, 0),
    badge: toStringOrNull(payload.badge),
    badgeLabel: toStringOrNull(payload.badge_label),
    image: toStringOrNull(payload.image),
    price: toStringOrNull(payload.price),
    includes: toStringList(payload.includes),
    requirements: toStringList(payload.requirements),
    metaTitle: toStringOrNull(payload.meta_title),
    metaDescription: toStringOrNull(payload.meta_description),
    scope: toStringList(payload.scope),
    standard: toStringOrNull(payload.standard),
    language: toStringOrNull(payload.language),
    location: toStringOrNull(payload.location),
  }
}

export function normalizeSchedule(
  payload: Record<string, unknown>
): AdminScheduleRecord {
  const course = getRecord(payload.course)
  const quota = toNumber(payload.quota, 0)
  const enrolledCount = toNumber(
    payload.enrolled_count ?? payload.reserved_count,
    0
  )
  const explicitAvailableSeats = payload.available_seats

  return {
    id: (payload.id as number | string) ?? 'unknown-schedule',
    courseId:
      (payload.course_id as number | string | null) ??
      (course?.id as number | string | null) ??
      null,
    courseTitle: String(
      course?.title ?? payload.course_title ?? 'Egitim secilmemis'
    ),
    startDate: toStringOrNull(payload.start_date),
    endDate: toStringOrNull(payload.end_date),
    location: String(payload.location ?? ''),
    instructor: toStringOrNull(payload.instructor),
    quota,
    enrolledCount,
    availableSeats:
      explicitAvailableSeats === undefined || explicitAvailableSeats === null
        ? Math.max(quota - enrolledCount, 0)
        : toNumber(explicitAvailableSeats, 0),
    priceOverride:
      payload.price_override === undefined || payload.price_override === null
        ? null
        : toNumber(payload.price_override, 0),
    status: String(payload.status ?? 'planned'),
    notes: toStringOrNull(payload.notes),
  }
}

export function normalizePaginated<T>(
  payload: ApiListResponse<Record<string, unknown>>,
  mapItem: (item: Record<string, unknown>) => T
): PaginatedResult<T> {
  return {
    items: (payload.data ?? []).map(mapItem),
    meta: {
      currentPage: payload.meta?.current_page ?? 1,
      lastPage: payload.meta?.last_page ?? 1,
      perPage: payload.meta?.per_page ?? payload.data?.length ?? 0,
      total: payload.meta?.total ?? payload.data?.length ?? 0,
    },
    links: payload.links ?? {},
  }
}

export function normalizePermissionGroups(payload: unknown): PermissionGroup[] {
  const data = unwrapData(payload as unknown)

  if (Array.isArray(data)) {
    if (data.every((entry) => typeof entry === 'string')) {
      return groupPermissionsByModule(data as string[])
    }

    const mapped = (data as Record<string, unknown>[])
      .map((entry) => ({
        group: titleize(
          String(entry.group ?? entry.module ?? entry.name ?? 'Genel')
        ),
        permissions: toStringArray(entry.permissions ?? entry.items),
      }))
      .filter((entry) => entry.permissions.length > 0)

    const shouldRegroup =
      mapped.length === 1 ||
      mapped.every((entry) =>
        ['all', 'genel', 'general'].includes(entry.group.toLowerCase())
      )

    if (shouldRegroup) {
      return groupPermissionsByModule(
        mapped.flatMap((entry) => entry.permissions)
      )
    }

    return mapped
  }

  if (data && typeof data === 'object') {
    const entries = Object.entries(data).map(([group, permissions]) => ({
      group: titleize(group),
      permissions: toStringArray(permissions),
    }))

    const shouldRegroup =
      entries.length === 1 ||
      entries.every((entry) =>
        ['all', 'genel', 'general'].includes(entry.group.toLowerCase())
      )

    if (shouldRegroup) {
      return groupPermissionsByModule(
        entries.flatMap((entry) => entry.permissions)
      )
    }

    return entries
  }

  return []
}

export function normalizeAnnouncement(
  payload: Record<string, unknown>
): AdminAnnouncementRecord {
  return {
    id: (payload.id as number | string) ?? 'unknown-announcement',
    slug: String(payload.slug ?? ''),
    title: String(payload.title ?? 'Adsiz duyuru'),
    category: String(payload.category ?? 'announcement'),
    excerpt: String(payload.excerpt ?? ''),
    content: String(payload.content ?? ''),
    image: toStringOrNull(payload.image),
    isFeatured: toBoolean(payload.is_featured, false),
    metaTitle: toStringOrNull(payload.meta_title),
    metaDescription: toStringOrNull(payload.meta_description),
    publishedAt: toStringOrNull(payload.published_at),
    createdAt: toStringOrNull(payload.created_at),
    updatedAt: toStringOrNull(payload.updated_at),
  }
}

export function normalizeHeroSlide(
  payload: Record<string, unknown>
): AdminHeroSlideRecord {
  return {
    id: (payload.id as number | string) ?? 'unknown-slide',
    title: String(payload.title ?? ''),
    subtitle: toStringOrNull(payload.subtitle),
    label: toStringOrNull(payload.label),
    description: toStringOrNull(payload.description),
    buttonText: toStringOrNull(payload.button_text),
    buttonUrl: toStringOrNull(payload.button_url),
    mediaType: (payload.media_type as 'image' | 'video') ?? 'image',
    image: toStringOrNull(payload.image),
    mobileImage: toStringOrNull(payload.mobile_image),
    videoUrl: toStringOrNull(payload.video_url),
    mobileVideoUrl: toStringOrNull(payload.mobile_video_url),
    orderIndex: toNumber(payload.order_index, 0),
    isActive: toBoolean(payload.is_active, true),
    createdAt: toStringOrNull(payload.created_at),
    updatedAt: toStringOrNull(payload.updated_at),
  }
}

export function normalizeLead(
  payload: Record<string, unknown>
): AdminLeadRecord {
  return {
    id: (payload.id as number | string) ?? 'unknown-lead',
    name: String(payload.name ?? ''),
    phone: String(payload.phone ?? ''),
    email: toStringOrNull(payload.email),
    source: toStringOrNull(payload.source),
    status: String(payload.status ?? 'new'),
    targetCourse: toStringOrNull(payload.target_course),
    educationLevel: toStringOrNull(payload.education_level),
    subject: toStringOrNull(payload.subject),
    message: toStringOrNull(payload.message),
    utmSource: toStringOrNull(payload.utm_source),
    utmMedium: toStringOrNull(payload.utm_medium),
    utmCampaign: toStringOrNull(payload.utm_campaign),
    kvkkConsent: toBoolean(payload.kvkk_consent, false),
    marketingConsent: toBoolean(payload.marketing_consent, false),
    isRead: toBoolean(payload.is_read, false),
    adminNote: toStringOrNull(payload.admin_note),
    createdAt: toStringOrNull(payload.created_at),
    updatedAt: toStringOrNull(payload.updated_at),
  }
}

export function normalizeMenu(
  payload: Record<string, unknown>
): AdminMenuRecord {
  const children = Array.isArray(payload.children)
    ? (payload.children as Record<string, unknown>[]).map(normalizeMenu)
    : []

  return {
    id: (payload.id as number | string) ?? 'unknown-menu',
    label: String(payload.label ?? ''),
    url: String(payload.url ?? ''),
    location: String(payload.location ?? 'header_main'),
    type: String(payload.type ?? 'link'),
    parentId: (payload.parent_id as number | string | null) ?? null,
    orderIndex: toNumber(payload.order_index, 0),
    isActive: toBoolean(payload.is_active, true),
    children,
    createdAt: toStringOrNull(payload.created_at),
    updatedAt: toStringOrNull(payload.updated_at),
  }
}

export function normalizeComment(
  payload: Record<string, unknown>
): AdminCommentRecord {
  return {
    id: (payload.id as number | string) ?? 'unknown-comment',
    commentableType: String(payload.commentable_type ?? ''),
    commentableId: (payload.commentable_id as number | string) ?? 0,
    authorName: String(payload.author_name ?? ''),
    content: String(payload.content ?? ''),
    rating:
      payload.rating !== null && payload.rating !== undefined
        ? toNumber(payload.rating, 0)
        : null,
    isApproved: toBoolean(payload.is_approved, false),
    adminReply: toStringOrNull(payload.admin_reply),
    createdAt: toStringOrNull(payload.created_at),
    updatedAt: toStringOrNull(payload.updated_at),
  }
}

export function normalizeFaq(payload: Record<string, unknown>): AdminFaqRecord {
  return {
    id: (payload.id as number | string) ?? 'unknown-faq',
    question: String(payload.question ?? ''),
    answer: String(payload.answer ?? ''),
    category: String(payload.category ?? 'egitimler'),
    orderIndex: toNumber(payload.order_index, 0),
    isActive: toBoolean(payload.is_active, true),
    createdAt: toStringOrNull(payload.created_at),
    updatedAt: toStringOrNull(payload.updated_at),
  }
}

export function normalizeGuideCard(
  payload: Record<string, unknown>
): AdminGuideCardRecord {
  return {
    id: (payload.id as number | string) ?? 'unknown-guide-card',
    title: String(payload.title ?? ''),
    description: String(payload.description ?? ''),
    icon: String(payload.icon ?? 'compass'),
    orderIndex: toNumber(payload.order_index, 0),
    isActive: toBoolean(payload.is_active, true),
    createdAt: toStringOrNull(payload.created_at),
    updatedAt: toStringOrNull(payload.updated_at),
  }
}

export function normalizeSetting(
  payload: Record<string, unknown>
): AdminSettingRecord {
  return {
    id: (payload.id as number | string) ?? 'unknown-setting',
    key: String(payload.key ?? ''),
    value: toStringOrNull(payload.value),
    group: String(payload.group ?? 'general'),
    type: String(payload.type ?? 'text'),
    label: toStringOrNull(payload.label),
    orderIndex: toNumber(payload.order_index, 0),
  }
}

export function normalizePageBlock(
  payload: Record<string, unknown>
): AdminPageBlockRecord {
  const content = payload.content
  return {
    id: (payload.id as number | string) ?? 'unknown-block',
    type: String(payload.type ?? 'text'),
    content:
      content && typeof content === 'object'
        ? (content as Record<string, unknown>)
        : null,
    orderIndex: toNumber(payload.order_index, 0),
  }
}

export function normalizePage(
  payload: Record<string, unknown>
): AdminPageRecord {
  const rawBlocks = payload.blocks
  const blocks =
    rawBlocks != null && Array.isArray(rawBlocks)
      ? (rawBlocks as Record<string, unknown>[]).map(normalizePageBlock)
      : []

  return {
    id: (payload.id as number | string) ?? 'unknown-page',
    slug: String(payload.slug ?? ''),
    title: String(payload.title ?? ''),
    content: toStringOrNull(payload.content),
    metaTitle: toStringOrNull(payload.meta_title),
    metaDescription: toStringOrNull(payload.meta_description),
    isActive: toBoolean(payload.is_active, true),
    blocks,
    createdAt: toStringOrNull(payload.created_at),
    updatedAt: toStringOrNull(payload.updated_at),
  }
}

export function normalizeStory(
  payload: Record<string, unknown>
): AdminStoryRecord {
  return {
    id: (payload.id as number | string) ?? 'unknown-story',
    title: String(payload.title ?? ''),
    badge: toStringOrNull(payload.badge),
    content: String(payload.content ?? ''),
    image: toStringOrNull(payload.image),
    ctaText: toStringOrNull(payload.cta_text),
    ctaUrl: toStringOrNull(payload.cta_url),
    orderIndex: toNumber(payload.order_index, 0),
    isActive: toBoolean(payload.is_active, true),
    createdAt: toStringOrNull(payload.created_at),
    updatedAt: toStringOrNull(payload.updated_at),
  }
}
