import { getAccessToken } from '@/components/apis/authApiClients'
import { BACKEND_URL } from '@/config/backend'

export interface DatabaseTemplate {
  id: string
  type: string
  title: string
  description: string
  icon: string | null
  category: string
  gradient: string | null
  border: string | null
  text: string | null
  subtext: string | null
  is_active: boolean
  created_at: string
  updated_at: string
  feature_count?: number
  avg_rating?: number
  is_custom?: boolean  // Add this field to identify custom templates
  created_by_user?: string  // Add this field for user-created templates
}

export interface TemplateFeature {
  id: string
  template_id: string
  feature_id: string
  name: string
  description: string
  feature_type: 'essential' | 'suggested' | 'custom'
  complexity: 'low' | 'medium' | 'high'
  display_order: number
  usage_count: number
  user_rating: number
  is_default: boolean
  created_by_user: boolean
  created_at: string
  updated_at: string
}

export type CreateFeaturePayload = Partial<TemplateFeature> & {
  logic_rules?: string[]
  business_rules?: Array<{ requirement: string; rules: string[] }>
}

export interface TemplateWithFeatures extends DatabaseTemplate {
  features: TemplateFeature[]
}

export interface TemplatesByCategory {
  [category: string]: DatabaseTemplate[]
}



class TemplateService {
  private async makeRequest<T>(endpoint: string, requireAuth: boolean = false): Promise<T> {
    try {
      const headers: Record<string, string> = {
        'Content-Type': 'application/json',
      }

      // Add authentication header if required and token exists
      if (requireAuth) {
        const token = getAccessToken()
        if (token) {
          headers['Authorization'] = `Bearer ${token}`
        }
      }

      const response = await fetch(`${BACKEND_URL}${endpoint}`, {
        method: 'GET',
        headers,
      })

      if (!response.ok) {
        // Handle authentication errors gracefully
        if (response.status === 401) {
          throw new Error('Authentication required. Please sign in to continue.')
        }
        if (response.status === 403) {
          throw new Error('Access denied. You do not have permission to view this resource.')
        }
        throw new Error(`HTTP error! status: ${response.status}`)
      }

      const data = await response.json()
      
      if (!data.success) {
        throw new Error(data.message || 'API request failed')
      }

      return data.data
    } catch (error) {
      console.error('Template service error:', error)
      throw error
    }
  }

  async getTemplatesByCategory(): Promise<TemplatesByCategory> {
    return this.makeRequest<TemplatesByCategory>('/api/templates', false)
  }

  async getTemplateById(id: string): Promise<TemplateWithFeatures> {
    return this.makeRequest<TemplateWithFeatures>(`/api/templates/${id}`, false)
  }

  async getTemplateByType(type: string): Promise<TemplateWithFeatures> {
    return this.makeRequest<TemplateWithFeatures>(`/api/templates/type/${type}`, false)
  }

  async getCombinedTemplates(params?: {
    userId?: string
    status?: string
    limit?: number
    offset?: number
    category?: string | null
    search?: string | null
    includeOthers?: boolean
  }): Promise<{ data: DatabaseTemplate[]; count?: number; pagination?: { total?: number; limit?: number; offset?: number; hasMore?: boolean } }> {
    const limit = params?.limit ?? 3
    const offset = params?.offset ?? 0
    const qp: string[] = [
      `limit=${encodeURIComponent(String(limit))}`,
      `offset=${encodeURIComponent(String(offset))}`,
    ]
    
    // Use the /merged endpoint for templates
    const endpoint = '/api/templates/merged'
    
    if (params?.category && params.category !== 'all') {
      qp.push(`category=${encodeURIComponent(params.category)}`)
    }
    
    if (params?.search && params.search.trim()) {
      qp.push(`search=${encodeURIComponent(params.search.trim())}`)
    }
    
    if (params?.userId) {
      qp.push(`userId=${encodeURIComponent(params.userId)}`)
    } else if (params?.includeOthers === true) {
      qp.push(`includeOthers=true`)
    }
    
    const url = `${BACKEND_URL}${endpoint}?${qp.join('&')}`
    console.log('[templateService.getCombinedTemplates] Making request to URL:', url)
    console.log('[templateService.getCombinedTemplates] Request params:', params)
    console.log('🆔 [templateService] User ID being sent:', params?.userId || 'No user ID')
    
    try {
      const headers: Record<string, string> = {
        'Content-Type': 'application/json',
      }

      // Add authentication header if user ID is provided (authenticated request)
      if (params?.userId) {
        const token = getAccessToken()
        console.log('🔐 [templateService] Token check:', { 
          hasUserId: !!params.userId, 
          hasToken: !!token, 
          tokenLength: token?.length || 0,
          tokenStart: token?.substring(0, 20) + '...' || 'No token',
          timestamp: new Date().toISOString(),
          url: url
        })
        if (token) {
          headers['Authorization'] = `Bearer ${token}`
          console.log('🔐 [templateService] Authorization header added with token')
          console.log('🔐 [templateService] Token format check:', {
            tokenType: typeof token,
            tokenLength: token.length,
            startsWithBearer: token.startsWith('Bearer'),
            firstChars: token.substring(0, 10),
            lastChars: token.substring(token.length - 10)
          })
        } else {
          console.log('❌ [templateService] No token available for authenticated request')
        }
      } else {
        console.log('🔐 [templateService] No userId provided, making public request')
      }

      console.log('🔐 [templateService] Final headers being sent:', headers)
      console.log('🔐 [templateService] Authorization header value:', headers['Authorization'])
      
      const resp = await fetch(url, { headers })
      console.log('[templateService.getCombinedTemplates] Response status:', resp.status, resp.statusText)
      
      if (!resp.ok) {
        const text = await resp.text().catch(() => '')
        console.error('[templateService.getCombinedTemplates] HTTP error', resp.status, text)
        
        // Handle authentication errors gracefully
        if (resp.status === 401) {
          throw new Error('Authentication required. Please sign in to continue.')
        }
        if (resp.status === 403) {
          throw new Error('Access denied. You do not have permission to view this resource.')
        }
        
        // If combined endpoint returns 404, throw error
        if (resp.status === 404) {
          throw new Error(`/api/templates/combined endpoint not found. Please ensure this endpoint exists and is working.`)
        }
        
        throw new Error(`HTTP error! status: ${resp.status}`)
      }
      
      const json = await resp.json()
      console.log('[templateService.getCombinedTemplates] Raw JSON:', json)
      
      // Handle merged endpoint response
      console.log('[templateService.getCombinedTemplates] Response structure:', {
        success: json?.success,
        hasData: !!json?.data,
        dataLength: json?.data?.length,
        hasPagination: !!json?.pagination,
        pagination: json?.pagination
      })
      
      // Extract data from the response
      let templates = []
      if (json?.success && json?.data) {
        if (Array.isArray(json.data)) {
          // If data is already an array
          templates = json.data
        } else if (typeof json.data === 'object') {
          // If data is an object with categories (like { "System": [...], "Marketing": [...] })
          // Flatten all categories into a single array
          for (const category in json.data) {
            if (Array.isArray(json.data[category])) {
              templates.push(...json.data[category])
            }
          }
        }
      } else if (Array.isArray(json)) {
        // Fallback: if response is directly an array
        templates = json
      }
      
      // Extract pagination info
      let paginationInfo = json?.pagination || {}
      if (!paginationInfo.total && templates.length > 0) {
        // If no pagination info, calculate it from the data
        paginationInfo = {
          total: templates.length,
          offset,
          limit,
          hasMore: false // Since we got all data
        }
      }
      
      const result = {
        data: templates,
        count: templates.length,
        pagination: paginationInfo
      }
      
      console.log('[templateService.getCombinedTemplates] Processed result:', result)
      console.log('[templateService.getCombinedTemplates] Templates array:', templates)
      console.log('[templateService.getCombinedTemplates] Pagination info:', paginationInfo)
      
      return result
    } catch (error) {
      console.error('[templateService.getCombinedTemplates] Error:', error)
      throw error
    }
  }

  async getTemplatesByUser(params: {
    userId: string
    status?: string
    limit?: number
    offset?: number
  }): Promise<{
    defaultTemplates: DatabaseTemplate[]
    customTemplates: DatabaseTemplate[]
  }> {
    const { userId, status, limit = 20, offset = 0 } = params
    const queryParts: string[] = []
    if (typeof status === 'string' && status.length > 0) {
      queryParts.push(`status=${encodeURIComponent(status)}`)
    }
    queryParts.push(`limit=${encodeURIComponent(String(limit))}`)
    queryParts.push(`offset=${encodeURIComponent(String(offset))}`)
    const query = queryParts.join('&')
    const url = `${BACKEND_URL}/api/templates/by-user/${encodeURIComponent(userId)}?${query}`
    try {
      console.log('[templateService.getTemplatesByUser] URL (matching curl):', url)
      const resp = await fetch(url, { headers: { 'Content-Type': 'application/json' } })
      if (!resp.ok) throw new Error(`HTTP error! status: ${resp.status}`)
      const json = await resp.json()
      console.log('[templateService.getTemplatesByUser] Raw JSON:', json)
      // Support both wrapped {success,data} and direct payloads
      const payload = (json && json.success !== undefined) ? json.data : json
      // If payload is an array, partition by flags
      let defaultTemplates: DatabaseTemplate[] = []
      let customTemplates: DatabaseTemplate[] = []
      if (Array.isArray(payload)) {
        const arr = payload as DatabaseTemplate[]
        defaultTemplates = arr.filter((t: DatabaseTemplate) => !(t?.is_custom || t?.created_by_user))
        customTemplates = arr.filter((t: DatabaseTemplate) => (t?.is_custom || t?.created_by_user))
      } else {
        // Normalize likely object shapes
        defaultTemplates = payload?.defaultTemplates || payload?.default_templates || payload?.defaults || []
        customTemplates = payload?.customTemplates || payload?.custom_templates || payload?.customs || []
      }
      const normalized = { defaultTemplates, customTemplates }
      console.log('[templateService.getTemplatesByUser] Normalized:', normalized)
      return normalized
    } catch (err) {
      console.error('[templateService.getTemplatesByUser] Error:', err)
      throw err
    }
  }

  async createTemplate(templateData: Partial<DatabaseTemplate>): Promise<DatabaseTemplate> {
    console.log(templateData, "templateData___");
    try {
      const headers: Record<string, string> = {
        'Content-Type': 'application/json',
      }

      // Add authentication header
      const token = getAccessToken()
      if (token) {
        headers['Authorization'] = `Bearer ${token}`
      }

      // Add is_custom flag to ensure custom templates are stored in custom_templates table
      const payload = {
        ...templateData,
        is_custom: true,
        isCustom: true
      };

      const response = await fetch(`${BACKEND_URL}/api/templates`, {
        method: 'POST',
        headers,
        body: JSON.stringify(payload),
      })

      if (!response.ok) {
        // Try to extract backend error message
        let backendMessage = ''
        let backendError = ''
        try {
          const errJson = await response.json()
          backendMessage = errJson?.message || ''
          backendError = errJson?.error || ''
        } catch {
          try {
            backendMessage = await response.text()
          } catch {}
        }

        // Handle specific error cases
        if (response.status === 401) {
          throw new Error(backendMessage || 'Authentication required. Please sign in to create templates.')
        }
        if (response.status === 403) {
          throw new Error(backendMessage || 'Access denied. You do not have permission to create templates.')
        }
        if (response.status === 409) {
          // Surface duplicate-specific message from backend
          throw new Error(backendMessage || backendError || 'Template already exists with same name or type.')
        }
        throw new Error(backendMessage || `HTTP error! status: ${response.status}`)
      }

      const data = await response.json()
      
      if (!data.success) {
        throw new Error(data.message || 'Failed to create template')
      }

      return data.data
    } catch (error) {
      console.error('Create template error:', error)
      throw error
    }
  }

  // Features API
  async getFeaturesForTemplate(templateId: string): Promise<TemplateFeature[]> {
    // Use merged endpoint to include custom features (returns custom_feature.id for custom items)
    const dedupe = (items: TemplateFeature[]) => {
      const byKey = new Map<string, TemplateFeature>()

      const toKey = (f: TemplateFeature) => {
        const normName = (f.name || '').trim().toLowerCase()
        // For custom features, dedupe by normalized name; for others, prefer feature_id
        if (f.feature_type === 'custom') return `custom:${normName}`
        return `std:${f.feature_id || normName}`
      }

      const prefer = (a: TemplateFeature, b: TemplateFeature): TemplateFeature => {
        // Prefer user-created, then higher usage_count, then newer updated_at
        const aUser = !!a.created_by_user
        const bUser = !!b.created_by_user
        if (aUser !== bUser) return aUser ? a : b
        const aUsage = typeof a.usage_count === 'number' ? a.usage_count : -1
        const bUsage = typeof b.usage_count === 'number' ? b.usage_count : -1
        if (aUsage !== bUsage) return aUsage > bUsage ? a : b
        const aTime = a.updated_at ? Date.parse(a.updated_at) : 0
        const bTime = b.updated_at ? Date.parse(b.updated_at) : 0
        return aTime >= bTime ? a : b
      }

      for (const item of items) {
        const key = toKey(item)
        const existing = byKey.get(key)
        if (!existing) {
          byKey.set(key, item)
        } else {
          byKey.set(key, prefer(existing, item))
        }
      }

      return Array.from(byKey.values())
    }

    try {
      const merged = await this.makeRequest<TemplateFeature[]>(`/api/templates/${templateId}/features`)
      return dedupe(merged)
    } catch {
      // Fallback to compatible route in features router
      const defaults = await this.makeRequest<TemplateFeature[]>(`/api/features/templates/${templateId}/features`)
      return dedupe(defaults)
    }
  }

  // Default-only features for template (does not include custom/merged)
  // async getDefaultFeaturesForTemplate(templateId: string): Promise<TemplateFeature[]> {
  //   return this.makeRequest<TemplateFeature[]>(`/api/templates/${templateId}/features`)
  // }

  async searchFeatures(searchTerm: string, templateId?: string): Promise<TemplateFeature[]> {
    const q = encodeURIComponent(searchTerm)
    const extra = templateId ? `&template_id=${encodeURIComponent(templateId)}` : ''
    return this.makeRequest<TemplateFeature[]>(`/api/features/search?q=${q}${extra}`)
  }

  async createFeature(featureData: CreateFeaturePayload): Promise<TemplateFeature> {
    // Normalize potentially stringified JSON fields to proper JSON before sending
    const normalizeJsonField = (value: unknown): unknown => {
      if (value === undefined || value === null || value === '') return undefined
      if (typeof value === 'string') {
        try {
          const trimmed = value.trim()
          if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
            return JSON.parse(trimmed)
          }
          // If it's a plain string not JSON, leave as-is for non-JSONB fields
          return value
        } catch {
          // Leave as-is; backend will reject invalid JSON, but we prefer to avoid sending broken JSONB
          return undefined
        }
      }
      return value
    }

    const cleanedFeatureData: CreateFeaturePayload = {
      ...featureData,
      // Only include normalized fields if valid
      business_rules: normalizeJsonField(featureData.business_rules) as CreateFeaturePayload['business_rules'],
      logic_rules: normalizeJsonField(featureData.logic_rules) as CreateFeaturePayload['logic_rules'],
      // @ts-expect-error: allow passthrough of optional technical_requirements if present in callers
      technical_requirements: normalizeJsonField((featureData as any).technical_requirements),
    }

    if (
      cleanedFeatureData &&
      (cleanedFeatureData.feature_type === 'custom')
    ) {
      const customHeaders: Record<string, string> = { 'Content-Type': 'application/json' }
      const customToken = getAccessToken()
      if (customToken) {
        customHeaders['Authorization'] = `Bearer ${customToken}`
      }
      const response = await fetch(`${BACKEND_URL}/api/features/custom`, {
        method: 'POST',
        headers: customHeaders,
        body: JSON.stringify(cleanedFeatureData),
      })
      if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`)
      const data = await response.json()
      if (!data.success) throw new Error(data.message || 'Failed to create custom feature')
      return data.data
    }
    const headers: Record<string, string> = { 'Content-Type': 'application/json' }
    const token = getAccessToken()
    if (token) {
      headers['Authorization'] = `Bearer ${token}`
    }
    const response = await fetch(`${BACKEND_URL}/api/features`, {
      method: 'POST',
      headers,
      body: JSON.stringify(cleanedFeatureData),
    })
    if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`)
    const data = await response.json()
    if (!data.success) throw new Error(data.message || 'Failed to create feature')
    return data.data
  }

  async updateFeature(id: string, featureData: Partial<TemplateFeature> & { isCustom?: boolean }): Promise<TemplateFeature> {
    const isCustom = featureData.isCustom || featureData.feature_type === 'custom'
    const url = isCustom ? `${BACKEND_URL}/api/features/custom/${id}` : `${BACKEND_URL}/api/features/${id}`
    const headers: Record<string, string> = { 'Content-Type': 'application/json' }
    const token = getAccessToken()
    if (token) headers['Authorization'] = `Bearer ${token}`
    const response = await fetch(url, {
      method: 'PUT',
      headers,
      body: JSON.stringify(featureData),
    })
    if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`)
    const data = await response.json()
    if (!data.success) throw new Error(data.message || 'Failed to update feature')
    return data.data
  }

  async deleteFeature(id: string, opts?: { isCustom?: boolean }): Promise<void> {
    const url = opts?.isCustom ? `${BACKEND_URL}/api/features/custom/${id}` : `${BACKEND_URL}/api/features/${id}`
    const headers: Record<string, string> = { 'Content-Type': 'application/json' }
    const token = getAccessToken()
    if (token) headers['Authorization'] = `Bearer ${token}`
    const response = await fetch(url, {
      method: 'DELETE',
      headers,
    })
    if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`)
    const data = await response.json()
    if (!data.success) throw new Error(data.message || 'Failed to delete feature')
  }

  async updateTemplate(id: string, templateData: Partial<DatabaseTemplate>, isCustom: boolean = false): Promise<DatabaseTemplate> {
    try {
      const headers: Record<string, string> = {
        'Content-Type': 'application/json',
      }

      // Add authentication header
      const token = getAccessToken()
      if (token) {
        headers['Authorization'] = `Bearer ${token}`
      }

      // Single endpoint with query flag
      const endpoint = `/api/templates/${id}?isCustom=${encodeURIComponent(String(!!isCustom))}`

      const response = await fetch(`${BACKEND_URL}${endpoint}`, {
        method: 'PUT',
        headers,
        body: JSON.stringify(templateData),
      })

      if (!response.ok) {
        // Try to surface backend error message
        let backendMessage = ''
        try {
          const errJson = await response.json()
          backendMessage = errJson?.message || errJson?.error || ''
        } catch {
          try {
            backendMessage = await response.text()
          } catch {}
        }
        // Handle specific error cases
        if (response.status === 401) {
          throw new Error(backendMessage || 'Authentication required. Please sign in to update templates.')
        }
        if (response.status === 403) {
          throw new Error(backendMessage || 'Access denied. You do not have permission to update this template.')
        }
        if (response.status === 404) {
          throw new Error(backendMessage || 'Template not found. It may have been deleted or you may not have access to it.')
        }
        throw new Error(backendMessage || `HTTP error! status: ${response.status}`)
      }

      const data = await response.json()
      
      if (!data.success) {
        throw new Error(data.message || 'Failed to update template')
      }

      return data.data
    } catch (error) {
      console.error('Update template error:', error)
      throw error
    }
  }

  async deleteTemplate(id: string, isCustom: boolean = false): Promise<void> {
    try {
      const headers: Record<string, string> = {
        'Content-Type': 'application/json',
      }

      // Add authentication header
      const token = getAccessToken()
      if (token) {
        headers['Authorization'] = `Bearer ${token}`
      }

      // Single endpoint with query flag
      const endpoint = `/api/templates/${id}?isCustom=${encodeURIComponent(String(!!isCustom))}`
      
      const response = await fetch(`${BACKEND_URL}${endpoint}`, {
        method: 'DELETE',
        headers,
      })

      if (!response.ok) {
        // Try to surface backend error message
        let backendMessage = ''
        try {
          const errJson = await response.json()
          backendMessage = errJson?.message || errJson?.error || ''
        } catch {
          try {
            backendMessage = await response.text()
          } catch {}
        }
        // Handle specific error cases
        if (response.status === 401) {
          throw new Error(backendMessage || 'Authentication required. Please sign in to delete templates.')
        }
        if (response.status === 403) {
          throw new Error(backendMessage || 'Access denied. You do not have permission to delete this template.')
        }
        if (response.status === 404) {
          throw new Error(backendMessage || 'Template not found. It may have been deleted or you may not have access to it.')
        }
        throw new Error(backendMessage || `HTTP error! status: ${response.status}`)
      }

      const data = await response.json()
      
      if (!data.success) {
        throw new Error(data.message || 'Failed to delete template')
      }
    } catch (error) {
      console.error('Delete template error:', error)
      throw error
    }
  }
}

export const templateService = new TemplateService()
