/**
 * API — ServiceRequest, ServiceBid, EquipmentInstall
 *
 * Uses authFetch (token-based) instead of CSRF session auth.
 * Tries Frappe custom doctypes first, falls back to Lead + localStorage
 * so the app works before the backend doctypes are created.
 */
import { BASE_URL } from 'src/config/erpnext'
import { authFetch } from './auth'

async function frappePOST (doctype, data) {
  const r = await authFetch(`${BASE_URL}/api/resource/${encodeURIComponent(doctype)}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  })
  if (!r.ok) throw new Error(`HTTP ${r.status}`)
  const body = await r.json()
  return body.data
}

async function frappePUT (doctype, name, data) {
  const r = await authFetch(`${BASE_URL}/api/resource/${encodeURIComponent(doctype)}/${encodeURIComponent(name)}`, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  })
  if (!r.ok) throw new Error(`HTTP ${r.status}`)
  const body = await r.json()
  return body.data
}

async function frappeGET (doctype, filters = {}, fields = ['name']) {
  const params = new URLSearchParams({
    fields: JSON.stringify(fields),
    filters: JSON.stringify(filters),
    limit: 50,
  })
  const r = await authFetch(`${BASE_URL}/api/resource/${encodeURIComponent(doctype)}?${params}`)
  if (!r.ok) throw new Error(`HTTP ${r.status}`)
  const body = await r.json()
  return body.data || []
}

// ─────────────────────────────────────────────────────────────────────────────
// ServiceRequest
// ─────────────────────────────────────────────────────────────────────────────

export async function createServiceRequest (data) {
  /**
   * data = {
   *   service_type: 'internet' | 'tv' | 'telephone' | 'multi',
   *   problem_type: string,
   *   description: string,
   *   address: string,
   *   coordinates: [lng, lat],
   *   preferred_dates: [{ date, time_slot, time_slots[] }, ...],  // up to 3
   *   contact: { name, phone, email },
   *   urgency: 'normal' | 'urgent',
   *   budget: { id, label, min, max } | null,
   * }
   */
  const ref = 'SR-' + Date.now().toString(36).toUpperCase().slice(-6)

  // Try Frappe ServiceRequest doctype
  try {
    const doc = await frappePOST('Service Request', {
      customer_name:    data.contact.name,
      phone:            data.contact.phone,
      email:            data.contact.email,
      service_type:     data.service_type,
      problem_type:     data.problem_type,
      description:      data.description,
      address:          data.address,
      lng:              data.coordinates?.[0] || 0,
      lat:              data.coordinates?.[1] || 0,
      preferred_date_1: data.preferred_dates[0]?.date || '',
      time_slot_1:      data.preferred_dates[0]?.time_slot || '',
      preferred_date_2: data.preferred_dates[1]?.date || '',
      time_slot_2:      data.preferred_dates[1]?.time_slot || '',
      preferred_date_3: data.preferred_dates[2]?.date || '',
      time_slot_3:      data.preferred_dates[2]?.time_slot || '',
      urgency:          data.urgency || 'normal',
      budget_label:     data.budget?.label || '',
      budget_min:       data.budget?.min   || 0,
      budget_max:       data.budget?.max   || 0,
      status:           'New',
    })
    return { ref: doc.name, source: 'frappe' }
  } catch (_) {}

  // Fallback: create as Frappe Lead + HD Ticket
  try {
    const notes = buildNotes(data)
    const doc = await frappePOST('Lead', {
      lead_name:  data.contact.name,
      mobile_no:  data.contact.phone,
      email_id:   data.contact.email || '',
      source:     'Dispatch Booking',
      lead_owner: '',
      status:     'Open',
      notes,
    })
    return { ref: doc.name, source: 'lead' }
  } catch (_) {}

  // Final fallback: localStorage
  const list = JSON.parse(localStorage.getItem('dispatch_service_requests') || '[]')
  list.push({ ref, ...data, lng: data.coordinates?.[0] || 0, lat: data.coordinates?.[1] || 0, budget_label: data.budget?.label || '', created: new Date().toISOString(), status: 'new' })
  localStorage.setItem('dispatch_service_requests', JSON.stringify(list))
  return { ref, source: 'local' }
}

function buildNotes (data) {
  const dates = data.preferred_dates
    .filter(d => d.date)
    .map((d, i) => `  Date ${i + 1}: ${d.date} — ${d.time_slot}`)
    .join('\n')
  return [
    `SERVICE: ${data.service_type?.toUpperCase()}`,
    `PROBLÈME: ${data.problem_type}`,
    `DESCRIPTION: ${data.description}`,
    `ADRESSE: ${data.address}`,
    `URGENCE: ${data.urgency}`,
    '',
    'DATES PRÉFÉRÉES:',
    dates,
  ].join('\n')
}

export async function fetchServiceRequests (status = null) {
  try {
    const filters = status ? { status } : {}
    return await frappeGET('Service Request', filters, [
      'name', 'customer_name', 'phone', 'service_type', 'problem_type',
      'description', 'address', 'status', 'urgency',
      'preferred_date_1', 'time_slot_1',
      'preferred_date_2', 'time_slot_2',
      'preferred_date_3', 'time_slot_3',
      'confirmed_date', 'creation',
      'budget_label', 'budget_min', 'budget_max',
    ])
  } catch (_) {
    return JSON.parse(localStorage.getItem('dispatch_service_requests') || '[]')
  }
}

export async function updateServiceRequestStatus (name, status, confirmedDate = null) {
  try {
    const data = {}
    if (status) data.status = status
    if (confirmedDate) data.confirmed_date = confirmedDate
    if (Object.keys(data).length === 0) return
    return await frappePUT('Service Request', name, data)
  } catch (_) {
    const list = JSON.parse(localStorage.getItem('dispatch_service_requests') || '[]')
    const item = list.find(r => r.ref === name || r.name === name)
    if (item) {
      if (status) item.status = status
      if (confirmedDate) item.confirmed_date = confirmedDate
    }
    localStorage.setItem('dispatch_service_requests', JSON.stringify(list))
  }
}

// ─────────────────────────────────────────────────────────────────────────────
// ServiceBid  (tech bids on a date)
// ─────────────────────────────────────────────────────────────────────────────

export async function createServiceBid (data) {
  /**
   * data = { request, technician, proposed_date, time_slot, estimated_duration, notes, price }
   */
  try {
    return await frappePOST('Service Bid', { ...data, status: 'Pending' })
  } catch (_) {
    const list = JSON.parse(localStorage.getItem('dispatch_service_bids') || '[]')
    const bid = { ref: 'BID-' + Date.now().toString(36).toUpperCase().slice(-6), ...data, status: 'pending', created: new Date().toISOString() }
    list.push(bid)
    localStorage.setItem('dispatch_service_bids', JSON.stringify(list))
    return bid
  }
}

export async function fetchBidsForRequest (requestName) {
  try {
    return await frappeGET('Service Bid', { request: requestName }, [
      'name', 'technician', 'proposed_date', 'time_slot',
      'estimated_duration', 'notes', 'status', 'creation',
    ])
  } catch (_) {
    const list = JSON.parse(localStorage.getItem('dispatch_service_bids') || '[]')
    return list.filter(b => b.request === requestName)
  }
}

export async function fetchBidsForTech (techName) {
  try {
    return await frappeGET('Service Bid', { technician: techName }, [
      'name', 'request', 'proposed_date', 'time_slot', 'status', 'creation',
    ])
  } catch (_) {
    const list = JSON.parse(localStorage.getItem('dispatch_service_bids') || '[]')
    return list.filter(b => b.technician === techName)
  }
}

export async function fetchOpenRequests () {
  try {
    return await frappeGET('Service Request', { status: ['in', ['New', 'Bidding']] }, [
      'name', 'customer_name', 'service_type', 'problem_type', 'description',
      'address', 'lng', 'lat', 'urgency', 'preferred_date_1', 'time_slot_1',
      'preferred_date_2', 'time_slot_2', 'preferred_date_3', 'time_slot_3',
      'creation', 'budget_label', 'budget_min', 'budget_max',
    ])
  } catch (_) {
    const list = JSON.parse(localStorage.getItem('dispatch_service_requests') || '[]')
    return list.filter(r => ['new', 'bidding'].includes(r.status))
  }
}

export async function acceptBid (bidName, requestName, confirmedDate) {
  try {
    await frappePUT('Service Bid', bidName, { status: 'Accepted' })
    await frappePUT('Service Request', requestName, { status: 'Confirmed', confirmed_date: confirmedDate })
  } catch (_) {}
}

// ─────────────────────────────────────────────────────────────────────────────
// EquipmentInstall  (barcode scan on site)
// ─────────────────────────────────────────────────────────────────────────────

export async function createEquipmentInstall (data) {
  /**
   * data = { request, barcode, equipment_type, brand, model, notes, photo_base64 }
   */
  try {
    return await frappePOST('Equipment Install', {
      ...data,
      installation_date: new Date().toISOString().split('T')[0],
    })
  } catch (_) {
    const list = JSON.parse(localStorage.getItem('dispatch_equipment') || '[]')
    const item = { ref: 'EQ-' + Date.now().toString(36).toUpperCase().slice(-6), ...data, created: new Date().toISOString() }
    list.push(item)
    localStorage.setItem('dispatch_equipment', JSON.stringify(list))
    return item
  }
}

export async function fetchEquipmentForRequest (requestName) {
  try {
    return await frappeGET('Equipment Install', { request: requestName }, [
      'name', 'barcode', 'equipment_type', 'brand', 'model', 'notes', 'installation_date',
    ])
  } catch (_) {
    const list = JSON.parse(localStorage.getItem('dispatch_equipment') || '[]')
    return list.filter(e => e.request === requestName)
  }
}
