import { createServiceRoleClient } from '@/lib/supabase/service'
import type {
  AdminShopRow,
  AdminSubscriptionRequestRow,
  BillingSettingsRow,
  DashboardSummary,
  EffectiveEntitlementRow,
  MembershipRow,
  ProfileRow,
  RuntimeSettingsRow,
  ShopDetailPayload,
} from '@/lib/types'

const PAGE_SIZE_DEFAULT = 20
const RUNTIME_SETTINGS_KEY = 'default'

async function fetchProfilesByIds(userIds: string[]) {
  const uniqueIds = [...new Set(userIds.filter(Boolean))]
  if (uniqueIds.length === 0) {
    return new Map<string, ProfileRow>()
  }

  const supabase = createServiceRoleClient()
  const { data, error } = await supabase
    .from('profiles')
    .select('id, full_name, phone, created_at')
    .in('id', uniqueIds)

  if (error) {
    throw error
  }

  return new Map((data ?? []).map((row) => [row.id, row as ProfileRow]))
}

export async function getDashboardSummary(): Promise<DashboardSummary> {
  const supabase = createServiceRoleClient()

  const [pendingRes, approvedRes, activeRes, inactiveRes] = await Promise.all([
    supabase.from('subscription_requests').select('id', { head: true, count: 'exact' }).eq('status', 'pending'),
    supabase.from('subscription_requests').select('id', { head: true, count: 'exact' }).eq('status', 'approved'),
    supabase.from('v_shop_entitlements_effective').select('shop_id', { head: true, count: 'exact' }).eq('is_effective_active', true),
    supabase.from('v_shop_entitlements_effective').select('shop_id', { head: true, count: 'exact' }).eq('is_effective_active', false),
  ])

  for (const response of [pendingRes, approvedRes, activeRes, inactiveRes]) {
    if (response.error) throw response.error
  }

  return {
    pendingRequests: pendingRes.count ?? 0,
    approvedRequests: approvedRes.count ?? 0,
    activeShops: activeRes.count ?? 0,
    inactiveOrExpiredShops: inactiveRes.count ?? 0,
  }
}

export async function listSubscriptionRequests(params?: {
  status?: string
  search?: string
  page?: number
  pageSize?: number
}) {
  const supabase = createServiceRoleClient()
  const page = Math.max(params?.page ?? 1, 1)
  const pageSize = Math.min(Math.max(params?.pageSize ?? PAGE_SIZE_DEFAULT, 1), 100)
  const from = (page - 1) * pageSize
  const to = from + pageSize - 1

  let query = supabase
    .from('v_admin_subscription_requests')
    .select('*', { count: 'exact' })
    .order('created_at', { ascending: false })
    .range(from, to)

  if (params?.status && params.status !== 'all') {
    query = query.eq('status', params.status)
  }

  if (params?.search) {
    const q = params.search.trim()
    if (q) {
      query = query.or(`shop_name.ilike.%${q}%,payer_phone.ilike.%${q}%,note.ilike.%${q}%`)
    }
  }

  const { data, count, error } = await query

  if (error) {
    throw error
  }

  const rows = (data ?? []) as AdminSubscriptionRequestRow[]
  const profiles = await fetchProfilesByIds(rows.flatMap((row) => [row.user_id, row.decided_by ?? '']))

  return {
    rows: rows.map((row) => ({
      ...row,
      requesterProfile: profiles.get(row.user_id) ?? null,
      decidedByProfile: row.decided_by ? profiles.get(row.decided_by) ?? null : null,
    })),
    count: count ?? 0,
    page,
    pageSize,
  }
}

export async function listShops(params?: {
  search?: string
  plan?: string
  page?: number
  pageSize?: number
}) {
  const supabase = createServiceRoleClient()
  const page = Math.max(params?.page ?? 1, 1)
  const pageSize = Math.min(Math.max(params?.pageSize ?? PAGE_SIZE_DEFAULT, 1), 100)
  const from = (page - 1) * pageSize
  const to = from + pageSize - 1

  let query = supabase
    .from('v_admin_shops')
    .select('*', { count: 'exact' })
    .order('entitlement_updated_at', { ascending: false, nullsFirst: false })
    .range(from, to)

  if (params?.plan && params.plan !== 'all') {
    query = query.eq('plan', params.plan)
  }

  if (params?.search) {
    const q = params.search.trim()
    if (q) {
      query = query.or(`shop_name.ilike.%${q}%,shop_phone.ilike.%${q}%`)
    }
  }

  const { data, count, error } = await query

  if (error) {
    throw error
  }

  return {
    rows: (data ?? []) as AdminShopRow[],
    count: count ?? 0,
    page,
    pageSize,
  }
}

export async function getShopDetail(shopId: string): Promise<ShopDetailPayload> {
  const supabase = createServiceRoleClient()

  const [shopRes, effectiveRes, billingRes, membershipsRes, requestsRes] = await Promise.all([
    supabase.from('v_admin_shops').select('*').eq('shop_id', shopId).maybeSingle(),
    supabase.from('v_shop_entitlements_effective').select('*').eq('shop_id', shopId).maybeSingle(),
    supabase.from('shop_billing_settings').select('*').eq('shop_id', shopId).maybeSingle(),
    supabase.from('memberships').select('shop_id, user_id, role, created_at').eq('shop_id', shopId).order('created_at', { ascending: true }),
    supabase.from('v_admin_subscription_requests').select('*').eq('shop_id', shopId).order('created_at', { ascending: false }).limit(20),
  ])

  for (const response of [shopRes, effectiveRes, billingRes, membershipsRes, requestsRes]) {
    if (response.error) throw response.error
  }

  const membershipRows = (membershipsRes.data ?? []) as MembershipRow[]
  const requestRows = (requestsRes.data ?? []) as AdminSubscriptionRequestRow[]
  const profileIds = [
    ...membershipRows.map((row) => row.user_id),
    ...requestRows.map((row) => row.user_id),
    ...requestRows.map((row) => row.decided_by ?? ''),
  ]
  const profiles = await fetchProfilesByIds(profileIds)

  return {
    shop: (shopRes.data ?? null) as AdminShopRow | null,
    effectiveEntitlement: (effectiveRes.data ?? null) as EffectiveEntitlementRow | null,
    billingSettings: (billingRes.data ?? null) as BillingSettingsRow | null,
    memberships: membershipRows.map((row) => ({
      ...row,
      profile: profiles.get(row.user_id) ?? null,
    })),
    recentRequests: requestRows.map((row) => ({
      ...row,
      requesterProfile: profiles.get(row.user_id) ?? null,
      decidedByProfile: row.decided_by ? profiles.get(row.decided_by) ?? null : null,
    })),
  }
}

export async function getRuntimeSettings(): Promise<RuntimeSettingsRow> {
  const supabase = createServiceRoleClient()
  const { data, error } = await supabase
    .from('senkredi_runtime_settings')
    .select('*')
    .eq('key', RUNTIME_SETTINGS_KEY)
    .maybeSingle()

  if (error) {
    throw error
  }

  if (data) {
    return data as RuntimeSettingsRow
  }

  const fallback: RuntimeSettingsRow = {
    key: RUNTIME_SETTINGS_KEY,
    app_name: 'SenKredi',
    business_name: 'SenKredi',
    website_url: '',
    support_email: '',
    support_phone: '',
    support_whatsapp: '',
    wave_number: '',
    orange_money_number: '',
    subscription_price_fcfa: 10000,
    payment_instructions: '',
    updated_at: new Date().toISOString(),
  }

  const { data: created, error: insertError } = await supabase
    .from('senkredi_runtime_settings')
    .upsert(fallback, { onConflict: 'key' })
    .select('*')
    .single()

  if (insertError) {
    throw insertError
  }

  return created as RuntimeSettingsRow
}

export async function updateRuntimeSettings(input: Partial<RuntimeSettingsRow>) {
  const supabase = createServiceRoleClient()
  const payload = {
    key: RUNTIME_SETTINGS_KEY,
    app_name: input.app_name ?? 'SenKredi',
    business_name: input.business_name ?? 'SenKredi',
    website_url: input.website_url ?? '',
    support_email: input.support_email ?? '',
    support_phone: input.support_phone ?? '',
    support_whatsapp: input.support_whatsapp ?? '',
    wave_number: input.wave_number ?? '',
    orange_money_number: input.orange_money_number ?? '',
    subscription_price_fcfa: input.subscription_price_fcfa ?? 10000,
    payment_instructions: input.payment_instructions ?? '',
    updated_at: new Date().toISOString(),
  }

  const { data, error } = await supabase
    .from('senkredi_runtime_settings')
    .upsert(payload, { onConflict: 'key' })
    .select('*')
    .single()

  if (error) {
    throw error
  }

  return data as RuntimeSettingsRow
}

export async function applyRuntimeSettingsToShops(runtime: RuntimeSettingsRow, shopIds?: string[]) {
  const supabase = createServiceRoleClient()

  let shopsQuery = supabase.from('shops').select('id')
  if (shopIds && shopIds.length > 0) {
    shopsQuery = shopsQuery.in('id', shopIds)
  }

  const { data: shops, error: shopsError } = await shopsQuery
  if (shopsError) throw shopsError

  const payload = (shops ?? []).map((shop) => ({
    shop_id: shop.id,
    price_fcfa: runtime.subscription_price_fcfa,
    wave_number: runtime.wave_number,
    orange_money_number: runtime.orange_money_number,
    support_phone: runtime.support_phone,
    support_whatsapp: runtime.support_whatsapp,
    updated_at: new Date().toISOString(),
  }))

  if (payload.length === 0) {
    return { updated: 0 }
  }

  const { error } = await supabase
    .from('shop_billing_settings')
    .upsert(payload, { onConflict: 'shop_id' })

  if (error) throw error

  return { updated: payload.length }
}

export async function updateShopBillingSettings(
  shopId: string,
  input: Partial<BillingSettingsRow>,
): Promise<BillingSettingsRow> {
  const supabase = createServiceRoleClient()
  const payload = {
    shop_id: shopId,
    price_fcfa: input.price_fcfa ?? 10000,
    wave_number: input.wave_number ?? '',
    orange_money_number: input.orange_money_number ?? '',
    support_phone: input.support_phone ?? '',
    support_whatsapp: input.support_whatsapp ?? '',
    updated_at: new Date().toISOString(),
  }

  const { data, error } = await supabase
    .from('shop_billing_settings')
    .upsert(payload, { onConflict: 'shop_id' })
    .select('*')
    .single()

  if (error) throw error
  return data as BillingSettingsRow
}

export async function getRevenueStats() {
  const supabase = createServiceRoleClient()

  const now = new Date()
  const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate())
  const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)

  const [today, month, total] = await Promise.all([
    supabase
      .from('subscription_requests')
      .select('amount_fcfa', { count: 'exact' })
      .eq('status', 'approved')
      .gte('created_at', startOfDay.toISOString()),

    supabase
      .from('subscription_requests')
      .select('amount_fcfa', { count: 'exact' })
      .eq('status', 'approved')
      .gte('created_at', startOfMonth.toISOString()),

    supabase
      .from('subscription_requests')
      .select('amount_fcfa', { count: 'exact' })
      .eq('status', 'approved'),
  ])

  const sum = (rows: any[] | null) =>
    (rows ?? []).reduce((s, r) => s + (r.amount_fcfa || 0), 0)

  return {
    today: sum(today.data),
    month: sum(month.data),
    total: sum(total.data),
    countToday: today.count ?? 0,
    countMonth: month.count ?? 0,
    countTotal: total.count ?? 0,
  }
}