'use client'

import { useState, useEffect, useCallback } from 'react'
import type { ImChannel } from '@/lib/types'
import { readArrayResponse } from '@/lib/auth/client-redirect'

/** Drizzle 返回的 im_channels 行（camelCase 字段名） */
interface DbImChannel {
  id: string
  name: string
  type: string
  enabled: number
  status: string
  credentials: string
  defaultWorkspaceId: string
  defaultModel: string
  dmPolicy: string
  groupPolicy: string
  triggerMode: string
  groupWhitelist: string
  senderWhitelist: string
  ownerUserId: string
  createdAt: string
  updatedAt: string
}

function mapChannel(row: DbImChannel): ImChannel {
  let credentials: Record<string, string> = {}
  let groupWhitelist: string[] = []
  let senderWhitelist: string[] = []
  try { credentials = JSON.parse(row.credentials) } catch { /* empty */ }
  try { groupWhitelist = JSON.parse(row.groupWhitelist) } catch { /* empty */ }
  try { senderWhitelist = JSON.parse(row.senderWhitelist) } catch { /* empty */ }

  return {
    id: row.id,
    name: row.name,
    type: row.type as ImChannel['type'],
    enabled: row.enabled === 1,
    status: row.status as ImChannel['status'],
    credentials,
    defaultWorkspaceId: row.defaultWorkspaceId || '',
    defaultModel: row.defaultModel || '',
    dmPolicy: row.dmPolicy as ImChannel['dmPolicy'],
    groupPolicy: row.groupPolicy as ImChannel['groupPolicy'],
    triggerMode: row.triggerMode as ImChannel['triggerMode'],
    groupWhitelist,
    senderWhitelist,
    createdAt: row.createdAt,
    updatedAt: row.updatedAt,
  }
}

export function useImChannels(workspaceId?: string) {
  const [channels, setChannels] = useState<ImChannel[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)

  const fetchChannels = useCallback(async () => {
    try {
      const qs = workspaceId ? `?workspace_id=${encodeURIComponent(workspaceId)}` : ''
      const res = await fetch(`/api/im-channels${qs}`)
      if (!res.ok) throw new Error(`Failed to load channels: ${res.status}`)
      const data = await readArrayResponse<DbImChannel>(res)
      setChannels(data.map(mapChannel))
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load channels')
    } finally {
      setLoading(false)
    }
  }, [workspaceId])

  useEffect(() => { fetchChannels() }, [fetchChannels])

  const updateChannel = useCallback(async (id: string, updates: Record<string, unknown>): Promise<ImChannel> => {
    const res = await fetch(`/api/im-channels/${id}`, {
      method: 'PATCH',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(updates),
    })
    if (!res.ok) {
      let msg = `Failed to update channel (${res.status})`
      try { const data = await res.json(); if (data?.error) msg = data.error } catch { /* ignore */ }
      throw new Error(msg)
    }
    const updatedRow = await res.json() as DbImChannel
    const updated = mapChannel(updatedRow)
    setChannels((prev) => prev.map((c) => (c.id === id ? updated : c)))
    return updated
  }, [])

  const createChannel = useCallback(async (type: ImChannel['type'], name?: string): Promise<ImChannel> => {
    const res = await fetch('/api/im-channels', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ type, name }),
    })
    if (!res.ok) {
      let msg = `Failed to create channel (${res.status})`
      try { const data = await res.json(); if (data?.error) msg = data.error } catch { /* ignore */ }
      throw new Error(msg)
    }
    const createdRow = await res.json() as DbImChannel
    const created = mapChannel(createdRow)
    setChannels((prev) => [...prev, created])
    return created
  }, [])

  const deleteChannel = useCallback(async (id: string) => {
    const res = await fetch(`/api/im-channels/${id}`, { method: 'DELETE' })
    if (!res.ok) {
      let msg = `Failed to delete channel (${res.status})`
      try { const data = await res.json(); if (data?.error) msg = data.error } catch { /* ignore */ }
      throw new Error(msg)
    }
    setChannels((prev) => prev.filter((c) => c.id !== id))
  }, [])

  return { channels, loading, error, updateChannel, createChannel, deleteChannel, refreshChannels: fetchChannels }
}