import { authFetch } from './auth'
import { BASE_URL } from 'src/config/erpnext'

async function apiGet (path) {
  const res = await authFetch(BASE_URL + path)
  if (!res.ok) throw new Error(`API ${res.status}: ${path}`)
  const ct = (res.headers.get('content-type') || '')
  if (!ct.includes('application/json')) throw new Error('Not JSON response for: ' + path)
  const data = await res.json()
  if (data.exc) throw new Error(data.exc)
  return data
}

/**
 * Get current portal user info from Authentik headers.
 * Returns { email, customer_id, customer_name }
 */
export async function getPortalUser () {
  const data = await apiGet('/api/method/client_portal_get_user_info')
  return data.message
}

/**
 * Fetch paginated Sales Invoices for a customer.
 */
export async function fetchInvoices (customer, { page = 1, pageSize = 20 } = {}) {
  const start = (page - 1) * pageSize
  const filters = JSON.stringify([
    ['customer', '=', customer],
    ['docstatus', '=', 1],
  ])
  const fields = JSON.stringify([
    'name', 'posting_date', 'due_date', 'grand_total',
    'outstanding_amount', 'status', 'currency',
  ])
  const path = `/api/resource/Sales Invoice?filters=${encodeURIComponent(filters)}&fields=${encodeURIComponent(fields)}&order_by=posting_date desc&limit_page_length=${pageSize}&limit_start=${start}`
  const data = await apiGet(path)
  return data.data || []
}

/**
 * Count total invoices for pagination.
 */
export async function countInvoices (customer) {
  const filters = JSON.stringify([
    ['customer', '=', customer],
    ['docstatus', '=', 1],
  ])
  const data = await apiGet(`/api/method/frappe.client.get_count?doctype=Sales Invoice&filters=${encodeURIComponent(filters)}`)
  return data.message || 0
}

/**
 * Download invoice PDF.
 */
export async function fetchInvoicePDF (invoiceName, format = 'Facture TARGO') {
  const url = `${BASE_URL}/api/method/frappe.utils.print_format.download_pdf?doctype=Sales%20Invoice&name=${encodeURIComponent(invoiceName)}&format=${encodeURIComponent(format)}`
  const res = await authFetch(url)
  if (!res.ok) throw new Error('PDF download failed')
  return res.blob()
}

/**
 * Fetch customer's Issues/Tickets.
 */
export async function fetchTickets (customer) {
  const filters = JSON.stringify([['customer', '=', customer]])
  const fields = JSON.stringify([
    'name', 'subject', 'status', 'priority', 'creation',
    'issue_type', 'sla_resolution_date',
  ])
  const path = `/api/resource/Issue?filters=${encodeURIComponent(filters)}&fields=${encodeURIComponent(fields)}&order_by=creation desc&limit_page_length=50`
  const data = await apiGet(path)
  return data.data || []
}

/**
 * Create a new support ticket.
 */
export async function createTicket (customer, subject, description) {
  const res = await authFetch(BASE_URL + '/api/resource/Issue', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      customer,
      subject,
      description,
      issue_type: 'Support',
      priority: 'Medium',
    }),
  })
  if (!res.ok) throw new Error('Failed to create ticket')
  const data = await res.json()
  return data.data
}

/**
 * Fetch customer profile with addresses.
 */
export async function fetchProfile (customer) {
  const data = await apiGet(`/api/resource/Customer/${encodeURIComponent(customer)}`)
  return data.data
}

/**
 * Fetch addresses linked to customer.
 */
export async function fetchAddresses (customer) {
  const filters = JSON.stringify([
    ['Dynamic Link', 'link_doctype', '=', 'Customer'],
    ['Dynamic Link', 'link_name', '=', customer],
  ])
  const fields = JSON.stringify([
    'name', 'address_title', 'address_line1', 'address_line2',
    'city', 'state', 'pincode', 'country', 'is_primary_address',
  ])
  const path = `/api/resource/Address?filters=${encodeURIComponent(filters)}&fields=${encodeURIComponent(fields)}`
  const data = await apiGet(path)
  return data.data || []
}

/**
 * Fetch Service Locations with their active Service Subscriptions.
 * Returns locations grouped with subscriptions and monthly totals.
 */
export async function fetchServiceLocations (customer) {
  // Fetch locations
  const locFields = JSON.stringify([
    'name', 'location_name', 'address_line', 'city', 'postal_code',
    'province', 'status', 'connection_type',
  ])
  const locFilters = JSON.stringify([['customer', '=', customer]])
  const locPath = `/api/resource/Service Location?filters=${encodeURIComponent(locFilters)}&fields=${encodeURIComponent(locFields)}&order_by=creation asc&limit_page_length=50`
  const locData = await apiGet(locPath)
  const locations = locData.data || []

  // Fetch subscriptions
  const subFields = JSON.stringify([
    'name', 'service_location', 'status', 'service_category',
    'plan_name', 'monthly_price', 'speed_down', 'speed_up',
    'billing_cycle', 'start_date', 'end_date', 'promo_end',
  ])
  const subFilters = JSON.stringify([
    ['customer', '=', customer],
    ['status', '=', 'Actif'],
  ])
  const subPath = `/api/resource/Service Subscription?filters=${encodeURIComponent(subFilters)}&fields=${encodeURIComponent(subFields)}&order_by=service_category asc, monthly_price desc&limit_page_length=200`
  const subData = await apiGet(subPath)
  const subscriptions = subData.data || []

  // Group subscriptions by location
  const subsByLoc = {}
  for (const sub of subscriptions) {
    const loc = sub.service_location || '_unassigned'
    if (!subsByLoc[loc]) subsByLoc[loc] = []
    subsByLoc[loc].push(sub)
  }

  // Attach subscriptions to locations and compute totals
  for (const loc of locations) {
    loc.subscriptions = subsByLoc[loc.name] || []
    loc.monthly_total = loc.subscriptions.reduce((sum, s) => sum + (s.monthly_price || 0), 0)
  }

  // Grand total across all locations
  const grandTotal = locations.reduce((sum, loc) => sum + loc.monthly_total, 0)

  return { locations, grandTotal, subscriptionCount: subscriptions.length }
}

/**
 * Fetch a single Sales Invoice with line items.
 */
export async function fetchInvoice (invoiceName) {
  const data = await apiGet(`/api/resource/Sales Invoice/${encodeURIComponent(invoiceName)}`)
  return data.data
}

/**
 * Fetch invoice HTML print preview (Jinja rendered).
 */
export async function fetchInvoiceHTML (invoiceName, format = 'Facture TARGO') {
  const url = `${BASE_URL}/api/method/frappe.www.printview.get_html_and_style?doc=Sales Invoice&name=${encodeURIComponent(invoiceName)}&print_format=${encodeURIComponent(format)}&no_letterhead=0`
  const res = await authFetch(url)
  if (!res.ok) throw new Error('Print preview failed')
  const data = await res.json()
  return data.message || {}
}

/**
 * Fetch a single Issue with full details.
 */
export async function fetchTicket (ticketName) {
  const data = await apiGet(`/api/resource/Issue/${encodeURIComponent(ticketName)}`)
  return data.data
}

/**
 * Fetch Communications linked to a reference (Issue or Customer).
 */
export async function fetchCommunications (refDoctype, refName, limit = 100) {
  const filters = JSON.stringify([
    ['reference_doctype', '=', refDoctype],
    ['reference_name', '=', refName],
  ])
  const fields = JSON.stringify([
    'name', 'communication_medium', 'communication_type',
    'sent_or_received', 'sender', 'sender_full_name', 'phone_no',
    'subject', 'content', 'creation', 'status',
    'reference_doctype', 'reference_name',
  ])
  const path = `/api/resource/Communication?filters=${encodeURIComponent(filters)}&fields=${encodeURIComponent(fields)}&order_by=creation asc&limit_page_length=${limit}`
  const data = await apiGet(path)
  return data.data || []
}

/**
 * Fetch all Communications for a customer (across all references + direct).
 * Returns Communications where reference is Customer or Issue belonging to customer.
 */
export async function fetchAllCommunications (customer, limit = 200) {
  // Direct communications on customer
  const directFilters = JSON.stringify([
    ['reference_doctype', '=', 'Customer'],
    ['reference_name', '=', customer],
  ])
  const fields = JSON.stringify([
    'name', 'communication_medium', 'communication_type',
    'sent_or_received', 'sender', 'sender_full_name', 'phone_no',
    'subject', 'content', 'creation', 'status',
    'reference_doctype', 'reference_name',
  ])
  const directPath = `/api/resource/Communication?filters=${encodeURIComponent(directFilters)}&fields=${encodeURIComponent(fields)}&order_by=creation desc&limit_page_length=${limit}`
  const directData = await apiGet(directPath)

  // Communications on customer's Issues
  const issueFilters = JSON.stringify([
    ['reference_doctype', '=', 'Issue'],
    ['reference_name', 'in', []],  // will be filled after ticket fetch
  ])
  // First get the customer's ticket names
  const ticketFilters = JSON.stringify([['customer', '=', customer]])
  const ticketFields = JSON.stringify(['name'])
  const ticketPath = `/api/resource/Issue?filters=${encodeURIComponent(ticketFilters)}&fields=${encodeURIComponent(ticketFields)}&limit_page_length=200`
  const ticketData = await apiGet(ticketPath)
  const ticketNames = (ticketData.data || []).map(t => t.name)

  let issueComs = []
  if (ticketNames.length) {
    const issueComsFilters = JSON.stringify([
      ['reference_doctype', '=', 'Issue'],
      ['reference_name', 'in', ticketNames],
    ])
    const issueComsPath = `/api/resource/Communication?filters=${encodeURIComponent(issueComsFilters)}&fields=${encodeURIComponent(fields)}&order_by=creation desc&limit_page_length=${limit}`
    const issueComsData = await apiGet(issueComsPath)
    issueComs = issueComsData.data || []
  }

  // Merge, deduplicate, sort desc
  const all = [...(directData.data || []), ...issueComs]
  const seen = new Set()
  const unique = all.filter(c => {
    if (seen.has(c.name)) return false
    seen.add(c.name)
    return true
  })
  unique.sort((a, b) => new Date(b.creation) - new Date(a.creation))
  return unique
}

/**
 * Post a reply on a ticket (creates a Communication).
 */
export async function replyToTicket (ticketName, message) {
  const res = await authFetch(BASE_URL + '/api/resource/Communication', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      communication_type: 'Communication',
      communication_medium: 'Other',
      sent_or_received: 'Sent',
      sender: 'portal@gigafibre.ca',
      content: message,
      reference_doctype: 'Issue',
      reference_name: ticketName,
      status: 'Linked',
    }),
  })
  if (!res.ok) throw new Error('Failed to send reply')
  const data = await res.json()
  return data.data
}

/**
 * Fetch Comments linked to a document (visible to portal users).
 */
export async function fetchComments (refDoctype, refName) {
  const filters = JSON.stringify([
    ['reference_doctype', '=', refDoctype],
    ['reference_name', '=', refName],
    ['comment_type', '=', 'Comment'],
  ])
  const fields = JSON.stringify([
    'name', 'comment_by', 'content', 'creation',
  ])
  const path = `/api/resource/Comment?filters=${encodeURIComponent(filters)}&fields=${encodeURIComponent(fields)}&order_by=creation asc&limit_page_length=100`
  const data = await apiGet(path)
  return data.data || []
}
